Statistics
| Branch: | Revision:

root / thunk.c @ 3ef693a0

History | View | Annotate | Download (8.4 kB)

1 31e31b8a bellard
/*
2 31e31b8a bellard
 *  Generic thunking code to convert data between host and target CPU
3 31e31b8a bellard
 * 
4 31e31b8a bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 31e31b8a bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 31e31b8a bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 31e31b8a bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 31e31b8a bellard
 */
20 31e31b8a bellard
#include <stdlib.h>
21 31e31b8a bellard
#include <stdio.h>
22 31e31b8a bellard
#include <stdarg.h>
23 31e31b8a bellard
24 3ef693a0 bellard
#include "qemu.h"
25 31e31b8a bellard
#include "thunk.h"
26 31e31b8a bellard
27 31e31b8a bellard
//#define DEBUG
28 31e31b8a bellard
29 31e31b8a bellard
#define MAX_STRUCTS 128
30 31e31b8a bellard
31 31e31b8a bellard
/* XXX: make it dynamic */
32 31e31b8a bellard
static StructEntry struct_entries[MAX_STRUCTS];
33 31e31b8a bellard
34 31e31b8a bellard
static inline int thunk_type_size(const argtype *type_ptr, int is_host)
35 31e31b8a bellard
{
36 31e31b8a bellard
    int type, size;
37 31e31b8a bellard
    const StructEntry *se;
38 31e31b8a bellard
39 31e31b8a bellard
    type = *type_ptr;
40 31e31b8a bellard
    switch(type) {
41 31e31b8a bellard
    case TYPE_CHAR:
42 31e31b8a bellard
        return 1;
43 31e31b8a bellard
    case TYPE_SHORT:
44 31e31b8a bellard
        return 2;
45 31e31b8a bellard
    case TYPE_INT:
46 31e31b8a bellard
        return 4;
47 31e31b8a bellard
    case TYPE_LONGLONG:
48 31e31b8a bellard
    case TYPE_ULONGLONG:
49 31e31b8a bellard
        return 8;
50 31e31b8a bellard
    case TYPE_LONG:
51 31e31b8a bellard
    case TYPE_ULONG:
52 31e31b8a bellard
    case TYPE_PTRVOID:
53 31e31b8a bellard
    case TYPE_PTR:
54 31e31b8a bellard
        if (is_host) {
55 31e31b8a bellard
            return HOST_LONG_SIZE;
56 31e31b8a bellard
        } else {
57 31e31b8a bellard
            return TARGET_LONG_SIZE;
58 31e31b8a bellard
        }
59 31e31b8a bellard
        break;
60 31e31b8a bellard
    case TYPE_ARRAY:
61 31e31b8a bellard
        size = type_ptr[1];
62 31e31b8a bellard
        return size * thunk_type_size(type_ptr + 2, is_host);
63 31e31b8a bellard
    case TYPE_STRUCT:
64 31e31b8a bellard
        se = struct_entries + type_ptr[1];
65 31e31b8a bellard
        return se->size[is_host];
66 31e31b8a bellard
    default:
67 31e31b8a bellard
        return -1;
68 31e31b8a bellard
    }
69 31e31b8a bellard
}
70 31e31b8a bellard
71 31e31b8a bellard
static inline int thunk_type_align(const argtype *type_ptr, int is_host)
72 31e31b8a bellard
{
73 31e31b8a bellard
    int type;
74 31e31b8a bellard
    const StructEntry *se;
75 31e31b8a bellard
76 31e31b8a bellard
    type = *type_ptr;
77 31e31b8a bellard
    switch(type) {
78 31e31b8a bellard
    case TYPE_CHAR:
79 31e31b8a bellard
        return 1;
80 31e31b8a bellard
    case TYPE_SHORT:
81 31e31b8a bellard
        return 2;
82 31e31b8a bellard
    case TYPE_INT:
83 31e31b8a bellard
        return 4;
84 31e31b8a bellard
    case TYPE_LONGLONG:
85 31e31b8a bellard
    case TYPE_ULONGLONG:
86 31e31b8a bellard
        return 8;
87 31e31b8a bellard
    case TYPE_LONG:
88 31e31b8a bellard
    case TYPE_ULONG:
89 31e31b8a bellard
    case TYPE_PTRVOID:
90 31e31b8a bellard
    case TYPE_PTR:
91 31e31b8a bellard
        if (is_host) {
92 31e31b8a bellard
            return HOST_LONG_SIZE;
93 31e31b8a bellard
        } else {
94 31e31b8a bellard
            return TARGET_LONG_SIZE;
95 31e31b8a bellard
        }
96 31e31b8a bellard
        break;
97 31e31b8a bellard
    case TYPE_ARRAY:
98 31e31b8a bellard
        return thunk_type_align(type_ptr + 2, is_host);
99 31e31b8a bellard
    case TYPE_STRUCT:
100 31e31b8a bellard
        se = struct_entries + type_ptr[1];
101 31e31b8a bellard
        return se->align[is_host];
102 31e31b8a bellard
    default:
103 31e31b8a bellard
        return -1;
104 31e31b8a bellard
    }
105 31e31b8a bellard
}
106 31e31b8a bellard
107 31e31b8a bellard
static inline const argtype *thunk_type_next(const argtype *type_ptr)
108 31e31b8a bellard
{
109 31e31b8a bellard
    int type;
110 31e31b8a bellard
111 31e31b8a bellard
    type = *type_ptr++;
112 31e31b8a bellard
    switch(type) {
113 31e31b8a bellard
    case TYPE_CHAR:
114 31e31b8a bellard
    case TYPE_SHORT:
115 31e31b8a bellard
    case TYPE_INT:
116 31e31b8a bellard
    case TYPE_LONGLONG:
117 31e31b8a bellard
    case TYPE_ULONGLONG:
118 31e31b8a bellard
    case TYPE_LONG:
119 31e31b8a bellard
    case TYPE_ULONG:
120 31e31b8a bellard
    case TYPE_PTRVOID:
121 31e31b8a bellard
        return type_ptr;
122 31e31b8a bellard
    case TYPE_PTR:
123 31e31b8a bellard
        return thunk_type_next(type_ptr);
124 31e31b8a bellard
    case TYPE_ARRAY:
125 31e31b8a bellard
        return thunk_type_next(type_ptr + 1);
126 31e31b8a bellard
    case TYPE_STRUCT:
127 31e31b8a bellard
        return type_ptr + 1;
128 31e31b8a bellard
    default:
129 31e31b8a bellard
        return NULL;
130 31e31b8a bellard
    }
131 31e31b8a bellard
}
132 31e31b8a bellard
133 31e31b8a bellard
void thunk_register_struct(int id, const char *name, const argtype *types)
134 31e31b8a bellard
{
135 31e31b8a bellard
    const argtype *type_ptr;
136 31e31b8a bellard
    StructEntry *se;
137 31e31b8a bellard
    int nb_fields, offset, max_align, align, size, i, j;
138 31e31b8a bellard
139 31e31b8a bellard
    se = struct_entries + id;
140 31e31b8a bellard
    
141 31e31b8a bellard
    /* first we count the number of fields */
142 31e31b8a bellard
    type_ptr = types;
143 31e31b8a bellard
    nb_fields = 0;
144 31e31b8a bellard
    while (*type_ptr != TYPE_NULL) {
145 31e31b8a bellard
        type_ptr = thunk_type_next(type_ptr);
146 31e31b8a bellard
        nb_fields++;
147 31e31b8a bellard
    }
148 31e31b8a bellard
    se->field_types = types;
149 31e31b8a bellard
    se->nb_fields = nb_fields;
150 31e31b8a bellard
    se->name = name;
151 31e31b8a bellard
#ifdef DEBUG
152 31e31b8a bellard
    printf("struct %s: id=%d nb_fields=%d\n", 
153 31e31b8a bellard
           se->name, id, se->nb_fields);
154 31e31b8a bellard
#endif
155 31e31b8a bellard
    /* now we can alloc the data */
156 31e31b8a bellard
157 31e31b8a bellard
    for(i = 0;i < 2; i++) {
158 31e31b8a bellard
        offset = 0;
159 31e31b8a bellard
        max_align = 1;
160 31e31b8a bellard
        se->field_offsets[i] = malloc(nb_fields * sizeof(int));
161 31e31b8a bellard
        type_ptr = se->field_types;
162 31e31b8a bellard
        for(j = 0;j < nb_fields; j++) {
163 31e31b8a bellard
            size = thunk_type_size(type_ptr, i);
164 31e31b8a bellard
            align = thunk_type_align(type_ptr, i);
165 31e31b8a bellard
            offset = (offset + align - 1) & ~(align - 1);
166 31e31b8a bellard
            se->field_offsets[i][j] = offset;
167 31e31b8a bellard
            offset += size;
168 31e31b8a bellard
            if (align > max_align)
169 31e31b8a bellard
                max_align = align;
170 31e31b8a bellard
        }
171 31e31b8a bellard
        offset = (offset + max_align - 1) & ~(max_align - 1);
172 31e31b8a bellard
        se->size[i] = offset;
173 31e31b8a bellard
        se->align[i] = max_align;
174 31e31b8a bellard
#ifdef DEBUG
175 31e31b8a bellard
        printf("%s: size=%d align=%d\n", 
176 31e31b8a bellard
               i == THUNK_HOST ? "host" : "target", offset, max_align);
177 31e31b8a bellard
#endif
178 31e31b8a bellard
    }
179 31e31b8a bellard
}
180 31e31b8a bellard
181 31e31b8a bellard
void thunk_register_struct_direct(int id, const char *name, StructEntry *se1)
182 31e31b8a bellard
{
183 31e31b8a bellard
    StructEntry *se;
184 31e31b8a bellard
    se = struct_entries + id;
185 31e31b8a bellard
    *se = *se1;
186 31e31b8a bellard
    se->name = name;
187 31e31b8a bellard
}
188 31e31b8a bellard
189 31e31b8a bellard
190 31e31b8a bellard
/* now we can define the main conversion functions */
191 31e31b8a bellard
const argtype *thunk_convert(void *dst, const void *src, 
192 31e31b8a bellard
                             const argtype *type_ptr, int to_host)
193 31e31b8a bellard
{
194 31e31b8a bellard
    int type;
195 31e31b8a bellard
196 31e31b8a bellard
    type = *type_ptr++;
197 31e31b8a bellard
    switch(type) {
198 31e31b8a bellard
    case TYPE_CHAR:
199 31e31b8a bellard
        *(uint8_t *)dst = *(uint8_t *)src;
200 31e31b8a bellard
        break;
201 31e31b8a bellard
    case TYPE_SHORT:
202 31e31b8a bellard
        *(uint16_t *)dst = tswap16(*(uint16_t *)src);
203 31e31b8a bellard
        break;
204 31e31b8a bellard
    case TYPE_INT:
205 31e31b8a bellard
        *(uint32_t *)dst = tswap32(*(uint32_t *)src);
206 31e31b8a bellard
        break;
207 31e31b8a bellard
    case TYPE_LONGLONG:
208 31e31b8a bellard
    case TYPE_ULONGLONG:
209 31e31b8a bellard
        *(uint64_t *)dst = tswap64(*(uint64_t *)src);
210 31e31b8a bellard
        break;
211 31e31b8a bellard
#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
212 31e31b8a bellard
    case TYPE_LONG:
213 31e31b8a bellard
    case TYPE_ULONG:
214 31e31b8a bellard
    case TYPE_PTRVOID:
215 31e31b8a bellard
        *(uint32_t *)dst = tswap32(*(uint32_t *)src);
216 31e31b8a bellard
        break;
217 31e31b8a bellard
#elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
218 31e31b8a bellard
    case TYPE_LONG:
219 31e31b8a bellard
    case TYPE_ULONG:
220 31e31b8a bellard
    case TYPE_PTRVOID:
221 31e31b8a bellard
        if (target_to_host) {
222 31e31b8a bellard
            *(uint64_t *)dst = tswap32(*(uint32_t *)src);
223 31e31b8a bellard
        } else {
224 31e31b8a bellard
            *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
225 31e31b8a bellard
        }
226 31e31b8a bellard
        break;
227 31e31b8a bellard
#else
228 31e31b8a bellard
#error unsupported conversion
229 31e31b8a bellard
#endif
230 31e31b8a bellard
    case TYPE_ARRAY:
231 31e31b8a bellard
        {
232 31e31b8a bellard
            int array_length, i, dst_size, src_size;
233 31e31b8a bellard
            const uint8_t *s;
234 31e31b8a bellard
            uint8_t  *d;
235 31e31b8a bellard
236 31e31b8a bellard
            array_length = *type_ptr++;
237 31e31b8a bellard
            dst_size = thunk_type_size(type_ptr, to_host);
238 31e31b8a bellard
            src_size = thunk_type_size(type_ptr, 1 - to_host);
239 31e31b8a bellard
            d = dst;
240 31e31b8a bellard
            s = src;
241 31e31b8a bellard
            for(i = 0;i < array_length; i++) {
242 31e31b8a bellard
                thunk_convert(d, s, type_ptr, to_host);
243 31e31b8a bellard
                d += dst_size;
244 31e31b8a bellard
                s += src_size;
245 31e31b8a bellard
            }
246 31e31b8a bellard
            type_ptr = thunk_type_next(type_ptr);
247 31e31b8a bellard
        }
248 31e31b8a bellard
        break;
249 31e31b8a bellard
    case TYPE_STRUCT:
250 31e31b8a bellard
        {
251 31e31b8a bellard
            int i;
252 31e31b8a bellard
            const StructEntry *se;
253 31e31b8a bellard
            const uint8_t *s;
254 31e31b8a bellard
            uint8_t  *d;
255 31e31b8a bellard
            const argtype *field_types;
256 31e31b8a bellard
            const int *dst_offsets, *src_offsets;
257 31e31b8a bellard
            
258 31e31b8a bellard
            se = struct_entries + *type_ptr++;
259 31e31b8a bellard
            if (se->convert[0] != NULL) {
260 31e31b8a bellard
                /* specific conversion is needed */
261 31e31b8a bellard
                (*se->convert[to_host])(dst, src);
262 31e31b8a bellard
            } else {
263 31e31b8a bellard
                /* standard struct conversion */
264 31e31b8a bellard
                field_types = se->field_types;
265 31e31b8a bellard
                dst_offsets = se->field_offsets[to_host];
266 31e31b8a bellard
                src_offsets = se->field_offsets[1 - to_host];
267 31e31b8a bellard
                d = dst;
268 31e31b8a bellard
                s = src;
269 31e31b8a bellard
                for(i = 0;i < se->nb_fields; i++) {
270 31e31b8a bellard
                    field_types = thunk_convert(d + dst_offsets[i], 
271 31e31b8a bellard
                                                s + src_offsets[i], 
272 31e31b8a bellard
                                                field_types, to_host);
273 31e31b8a bellard
                }
274 31e31b8a bellard
            }
275 31e31b8a bellard
        }
276 31e31b8a bellard
        break;
277 31e31b8a bellard
    default:
278 31e31b8a bellard
        fprintf(stderr, "Invalid type 0x%x\n", type);
279 31e31b8a bellard
        break;
280 31e31b8a bellard
    }
281 31e31b8a bellard
    return type_ptr;
282 31e31b8a bellard
}
283 31e31b8a bellard
284 31e31b8a bellard
/* from em86 */
285 31e31b8a bellard
286 31e31b8a bellard
/* Utility function: Table-driven functions to translate bitmasks
287 31e31b8a bellard
 * between X86 and Alpha formats...
288 31e31b8a bellard
 */
289 31e31b8a bellard
unsigned int target_to_host_bitmask(unsigned int x86_mask, 
290 31e31b8a bellard
                                    bitmask_transtbl * trans_tbl)
291 31e31b8a bellard
{
292 31e31b8a bellard
    bitmask_transtbl *        btp;
293 31e31b8a bellard
    unsigned int        alpha_mask = 0;
294 31e31b8a bellard
295 31e31b8a bellard
    for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
296 31e31b8a bellard
        if((x86_mask & btp->x86_mask) == btp->x86_bits) {
297 31e31b8a bellard
            alpha_mask |= btp->alpha_bits;
298 31e31b8a bellard
        }
299 31e31b8a bellard
    }
300 31e31b8a bellard
    return(alpha_mask);
301 31e31b8a bellard
}
302 31e31b8a bellard
303 31e31b8a bellard
unsigned int host_to_target_bitmask(unsigned int alpha_mask, 
304 31e31b8a bellard
                                    bitmask_transtbl * trans_tbl)
305 31e31b8a bellard
{
306 31e31b8a bellard
    bitmask_transtbl *        btp;
307 31e31b8a bellard
    unsigned int        x86_mask = 0;
308 31e31b8a bellard
309 31e31b8a bellard
    for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
310 31e31b8a bellard
        if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
311 31e31b8a bellard
            x86_mask |= btp->x86_mask;
312 31e31b8a bellard
        }
313 31e31b8a bellard
    }
314 31e31b8a bellard
    return(x86_mask);
315 31e31b8a bellard
}