Statistics
| Branch: | Revision:

root / thunk.h @ b6d78bfa

History | View | Annotate | Download (7.1 kB)

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#ifndef THUNK_H
21
#define THUNK_H
22

    
23
#include <inttypes.h>
24
#include "config.h"
25

    
26
#ifdef HAVE_BYTESWAP_H
27
#include <byteswap.h>
28
#else
29

    
30
#define bswap_16(x) \
31
({ \
32
        uint16_t __x = (x); \
33
        ((uint16_t)( \
34
                (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
35
                (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
36
})
37

    
38
#define bswap_32(x) \
39
({ \
40
        uint32_t __x = (x); \
41
        ((uint32_t)( \
42
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
43
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
44
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
45
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
46
})
47

    
48
#define bswap_64(x) \
49
({ \
50
        uint64_t __x = (x); \
51
        ((uint64_t)( \
52
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
53
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
54
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
55
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
56
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
57
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
58
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
59
                (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
60
})
61

    
62
#endif
63

    
64
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
65
#define BSWAP_NEEDED
66
#endif
67

    
68
/* XXX: autoconf */
69
#define TARGET_LONG_BITS 32
70

    
71
#if defined(__alpha__) || defined (__ia64__)
72
#define HOST_LONG_BITS 64
73
#else
74
#define HOST_LONG_BITS 32
75
#endif
76

    
77
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
78
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
79

    
80
static inline uint16_t bswap16(uint16_t x)
81
{
82
    return bswap_16(x);
83
}
84

    
85
static inline uint32_t bswap32(uint32_t x) 
86
{
87
    return bswap_32(x);
88
}
89

    
90
static inline uint64_t bswap64(uint64_t x) 
91
{
92
    return bswap_64(x);
93
}
94

    
95
static inline void bswap16s(uint16_t *s)
96
{
97
    *s = bswap16(*s);
98
}
99

    
100
static inline void bswap32s(uint32_t *s)
101
{
102
    *s = bswap32(*s);
103
}
104

    
105
static inline void bswap64s(uint64_t *s)
106
{
107
    *s = bswap64(*s);
108
}
109

    
110
#ifdef BSWAP_NEEDED
111

    
112
static inline uint16_t tswap16(uint16_t s)
113
{
114
    return bswap16(s);
115
}
116

    
117
static inline uint32_t tswap32(uint32_t s)
118
{
119
    return bswap32(s);
120
}
121

    
122
static inline uint64_t tswap64(uint64_t s)
123
{
124
    return bswap64(s);
125
}
126

    
127
static inline void tswap16s(uint16_t *s)
128
{
129
    *s = bswap16(*s);
130
}
131

    
132
static inline void tswap32s(uint32_t *s)
133
{
134
    *s = bswap32(*s);
135
}
136

    
137
static inline void tswap64s(uint64_t *s)
138
{
139
    *s = bswap64(*s);
140
}
141

    
142
#else
143

    
144
static inline uint16_t tswap16(uint16_t s)
145
{
146
    return s;
147
}
148

    
149
static inline uint32_t tswap32(uint32_t s)
150
{
151
    return s;
152
}
153

    
154
static inline uint64_t tswap64(uint64_t s)
155
{
156
    return s;
157
}
158

    
159
static inline void tswap16s(uint16_t *s)
160
{
161
}
162

    
163
static inline void tswap32s(uint32_t *s)
164
{
165
}
166

    
167
static inline void tswap64s(uint64_t *s)
168
{
169
}
170

    
171
#endif
172

    
173
#if TARGET_LONG_SIZE == 4
174
#define tswapl(s) tswap32(s)
175
#define tswapls(s) tswap32s((uint32_t *)(s))
176
#else
177
#define tswapl(s) tswap64(s)
178
#define tswapls(s) tswap64s((uint64_t *)(s))
179
#endif
180

    
181
#if TARGET_LONG_SIZE == 4
182
typedef int32_t target_long;
183
typedef uint32_t target_ulong;
184
#elif TARGET_LONG_SIZE == 8
185
typedef int64_t target_long;
186
typedef uint64_t target_ulong;
187
#else
188
#error TARGET_LONG_SIZE undefined
189
#endif
190

    
191
/* types enums definitions */
192

    
193
typedef enum argtype {
194
    TYPE_NULL,
195
    TYPE_CHAR,
196
    TYPE_SHORT,
197
    TYPE_INT,
198
    TYPE_LONG,
199
    TYPE_ULONG,
200
    TYPE_PTRVOID, /* pointer on unknown data */
201
    TYPE_LONGLONG,
202
    TYPE_ULONGLONG,
203
    TYPE_PTR,
204
    TYPE_ARRAY,
205
    TYPE_STRUCT,
206
} argtype;
207

    
208
#define MK_PTR(type) TYPE_PTR, type
209
#define MK_ARRAY(type, size) TYPE_ARRAY, size, type
210
#define MK_STRUCT(id) TYPE_STRUCT, id
211

    
212
#define THUNK_TARGET 0
213
#define THUNK_HOST   1
214

    
215
typedef struct {
216
    /* standard struct handling */
217
    const argtype *field_types;
218
    int nb_fields;
219
    int *field_offsets[2];
220
    /* special handling */
221
    void (*convert[2])(void *dst, const void *src);
222
    int size[2];
223
    int align[2];
224
    const char *name;
225
} StructEntry;
226

    
227
/* Translation table for bitmasks... */
228
typedef struct bitmask_transtbl {
229
        unsigned int        x86_mask;
230
        unsigned int        x86_bits;
231
        unsigned int        alpha_mask;
232
        unsigned int        alpha_bits;
233
} bitmask_transtbl;
234

    
235
void thunk_register_struct(int id, const char *name, const argtype *types);
236
void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
237
const argtype *thunk_convert(void *dst, const void *src, 
238
                             const argtype *type_ptr, int to_host);
239
#ifndef NO_THUNK_TYPE_SIZE
240

    
241
extern StructEntry struct_entries[];
242

    
243
static inline int thunk_type_size(const argtype *type_ptr, int is_host)
244
{
245
    int type, size;
246
    const StructEntry *se;
247

    
248
    type = *type_ptr;
249
    switch(type) {
250
    case TYPE_CHAR:
251
        return 1;
252
    case TYPE_SHORT:
253
        return 2;
254
    case TYPE_INT:
255
        return 4;
256
    case TYPE_LONGLONG:
257
    case TYPE_ULONGLONG:
258
        return 8;
259
    case TYPE_LONG:
260
    case TYPE_ULONG:
261
    case TYPE_PTRVOID:
262
    case TYPE_PTR:
263
        if (is_host) {
264
            return HOST_LONG_SIZE;
265
        } else {
266
            return TARGET_LONG_SIZE;
267
        }
268
        break;
269
    case TYPE_ARRAY:
270
        size = type_ptr[1];
271
        return size * thunk_type_size(type_ptr + 2, is_host);
272
    case TYPE_STRUCT:
273
        se = struct_entries + type_ptr[1];
274
        return se->size[is_host];
275
    default:
276
        return -1;
277
    }
278
}
279

    
280
static inline int thunk_type_align(const argtype *type_ptr, int is_host)
281
{
282
    int type;
283
    const StructEntry *se;
284

    
285
    type = *type_ptr;
286
    switch(type) {
287
    case TYPE_CHAR:
288
        return 1;
289
    case TYPE_SHORT:
290
        return 2;
291
    case TYPE_INT:
292
        return 4;
293
    case TYPE_LONGLONG:
294
    case TYPE_ULONGLONG:
295
        return 8;
296
    case TYPE_LONG:
297
    case TYPE_ULONG:
298
    case TYPE_PTRVOID:
299
    case TYPE_PTR:
300
        if (is_host) {
301
            return HOST_LONG_SIZE;
302
        } else {
303
            return TARGET_LONG_SIZE;
304
        }
305
        break;
306
    case TYPE_ARRAY:
307
        return thunk_type_align(type_ptr + 2, is_host);
308
    case TYPE_STRUCT:
309
        se = struct_entries + type_ptr[1];
310
        return se->align[is_host];
311
    default:
312
        return -1;
313
    }
314
}
315

    
316
#endif /* NO_THUNK_TYPE_SIZE */
317

    
318
unsigned int target_to_host_bitmask(unsigned int x86_mask, 
319
                                    bitmask_transtbl * trans_tbl);
320
unsigned int host_to_target_bitmask(unsigned int alpha_mask, 
321
                                    bitmask_transtbl * trans_tbl);
322

    
323
#endif