2 * Generic thunking code to convert data between host and target CPU
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
29 #define MAX_STRUCTS 128
31 /* XXX: make it dynamic */
32 static StructEntry struct_entries
[MAX_STRUCTS
];
34 static inline int thunk_type_size(const argtype
*type_ptr
, int is_host
)
37 const StructEntry
*se
;
55 return HOST_LONG_SIZE
;
57 return TARGET_LONG_SIZE
;
62 return size
* thunk_type_size(type_ptr
+ 2, is_host
);
64 se
= struct_entries
+ type_ptr
[1];
65 return se
->size
[is_host
];
71 static inline int thunk_type_align(const argtype
*type_ptr
, int is_host
)
74 const StructEntry
*se
;
92 return HOST_LONG_SIZE
;
94 return TARGET_LONG_SIZE
;
98 return thunk_type_align(type_ptr
+ 2, is_host
);
100 se
= struct_entries
+ type_ptr
[1];
101 return se
->align
[is_host
];
107 static inline const argtype
*thunk_type_next(const argtype
*type_ptr
)
123 return thunk_type_next(type_ptr
);
125 return thunk_type_next(type_ptr
+ 1);
133 void thunk_register_struct(int id
, const char *name
, const argtype
*types
)
135 const argtype
*type_ptr
;
137 int nb_fields
, offset
, max_align
, align
, size
, i
, j
;
139 se
= struct_entries
+ id
;
141 /* first we count the number of fields */
144 while (*type_ptr
!= TYPE_NULL
) {
145 type_ptr
= thunk_type_next(type_ptr
);
148 se
->field_types
= types
;
149 se
->nb_fields
= nb_fields
;
152 printf("struct %s: id=%d nb_fields=%d\n",
153 se
->name
, id
, se
->nb_fields
);
155 /* now we can alloc the data */
157 for(i
= 0;i
< 2; i
++) {
160 se
->field_offsets
[i
] = malloc(nb_fields
* sizeof(int));
161 type_ptr
= se
->field_types
;
162 for(j
= 0;j
< nb_fields
; j
++) {
163 size
= thunk_type_size(type_ptr
, i
);
164 align
= thunk_type_align(type_ptr
, i
);
165 offset
= (offset
+ align
- 1) & ~(align
- 1);
166 se
->field_offsets
[i
][j
] = offset
;
168 if (align
> max_align
)
171 offset
= (offset
+ max_align
- 1) & ~(max_align
- 1);
172 se
->size
[i
] = offset
;
173 se
->align
[i
] = max_align
;
175 printf("%s: size=%d align=%d\n",
176 i
== THUNK_HOST
? "host" : "target", offset
, max_align
);
181 void thunk_register_struct_direct(int id
, const char *name
, StructEntry
*se1
)
184 se
= struct_entries
+ id
;
190 /* now we can define the main conversion functions */
191 const argtype
*thunk_convert(void *dst
, const void *src
,
192 const argtype
*type_ptr
, int to_host
)
199 *(uint8_t *)dst
= *(uint8_t *)src
;
202 *(uint16_t *)dst
= tswap16(*(uint16_t *)src
);
205 *(uint32_t *)dst
= tswap32(*(uint32_t *)src
);
209 *(uint64_t *)dst
= tswap64(*(uint64_t *)src
);
211 #if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
215 *(uint32_t *)dst
= tswap32(*(uint32_t *)src
);
217 #elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
221 if (target_to_host
) {
222 *(uint64_t *)dst
= tswap32(*(uint32_t *)src
);
224 *(uint32_t *)dst
= tswap32(*(uint64_t *)src
& 0xffffffff);
228 #error unsupported conversion
232 int array_length
, i
, dst_size
, src_size
;
236 array_length
= *type_ptr
++;
237 dst_size
= thunk_type_size(type_ptr
, to_host
);
238 src_size
= thunk_type_size(type_ptr
, 1 - to_host
);
241 for(i
= 0;i
< array_length
; i
++) {
242 thunk_convert(d
, s
, type_ptr
, to_host
);
246 type_ptr
= thunk_type_next(type_ptr
);
252 const StructEntry
*se
;
255 const argtype
*field_types
;
256 const int *dst_offsets
, *src_offsets
;
258 se
= struct_entries
+ *type_ptr
++;
259 if (se
->convert
[0] != NULL
) {
260 /* specific conversion is needed */
261 (*se
->convert
[to_host
])(dst
, src
);
263 /* standard struct conversion */
264 field_types
= se
->field_types
;
265 dst_offsets
= se
->field_offsets
[to_host
];
266 src_offsets
= se
->field_offsets
[1 - to_host
];
269 for(i
= 0;i
< se
->nb_fields
; i
++) {
270 field_types
= thunk_convert(d
+ dst_offsets
[i
],
272 field_types
, to_host
);
278 fprintf(stderr
, "Invalid type 0x%x\n", type
);
286 /* Utility function: Table-driven functions to translate bitmasks
287 * between X86 and Alpha formats...
289 unsigned int target_to_host_bitmask(unsigned int x86_mask
,
290 bitmask_transtbl
* trans_tbl
)
292 bitmask_transtbl
* btp
;
293 unsigned int alpha_mask
= 0;
295 for(btp
= trans_tbl
; btp
->x86_mask
&& btp
->alpha_mask
; btp
++) {
296 if((x86_mask
& btp
->x86_mask
) == btp
->x86_bits
) {
297 alpha_mask
|= btp
->alpha_bits
;
303 unsigned int host_to_target_bitmask(unsigned int alpha_mask
,
304 bitmask_transtbl
* trans_tbl
)
306 bitmask_transtbl
* btp
;
307 unsigned int x86_mask
= 0;
309 for(btp
= trans_tbl
; btp
->x86_mask
&& btp
->alpha_mask
; btp
++) {
310 if((alpha_mask
& btp
->alpha_mask
) == btp
->alpha_bits
) {
311 x86_mask
|= btp
->x86_mask
;