ia64/xen-unstable

view tools/ioemu/thunk.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children f7b43e5c42b9
line source
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 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
24 #include "qemu.h"
25 #include "thunk.h"
27 //#define DEBUG
29 #define MAX_STRUCTS 128
31 /* XXX: make it dynamic */
32 StructEntry struct_entries[MAX_STRUCTS];
34 static inline const argtype *thunk_type_next(const argtype *type_ptr)
35 {
36 int type;
38 type = *type_ptr++;
39 switch(type) {
40 case TYPE_CHAR:
41 case TYPE_SHORT:
42 case TYPE_INT:
43 case TYPE_LONGLONG:
44 case TYPE_ULONGLONG:
45 case TYPE_LONG:
46 case TYPE_ULONG:
47 case TYPE_PTRVOID:
48 return type_ptr;
49 case TYPE_PTR:
50 return thunk_type_next(type_ptr);
51 case TYPE_ARRAY:
52 return thunk_type_next(type_ptr + 1);
53 case TYPE_STRUCT:
54 return type_ptr + 1;
55 default:
56 return NULL;
57 }
58 }
60 void thunk_register_struct(int id, const char *name, const argtype *types)
61 {
62 const argtype *type_ptr;
63 StructEntry *se;
64 int nb_fields, offset, max_align, align, size, i, j;
66 se = struct_entries + id;
68 /* first we count the number of fields */
69 type_ptr = types;
70 nb_fields = 0;
71 while (*type_ptr != TYPE_NULL) {
72 type_ptr = thunk_type_next(type_ptr);
73 nb_fields++;
74 }
75 se->field_types = types;
76 se->nb_fields = nb_fields;
77 se->name = name;
78 #ifdef DEBUG
79 printf("struct %s: id=%d nb_fields=%d\n",
80 se->name, id, se->nb_fields);
81 #endif
82 /* now we can alloc the data */
84 for(i = 0;i < 2; i++) {
85 offset = 0;
86 max_align = 1;
87 se->field_offsets[i] = malloc(nb_fields * sizeof(int));
88 type_ptr = se->field_types;
89 for(j = 0;j < nb_fields; j++) {
90 size = thunk_type_size(type_ptr, i);
91 align = thunk_type_align(type_ptr, i);
92 offset = (offset + align - 1) & ~(align - 1);
93 se->field_offsets[i][j] = offset;
94 offset += size;
95 if (align > max_align)
96 max_align = align;
97 type_ptr = thunk_type_next(type_ptr);
98 }
99 offset = (offset + max_align - 1) & ~(max_align - 1);
100 se->size[i] = offset;
101 se->align[i] = max_align;
102 #ifdef DEBUG
103 printf("%s: size=%d align=%d\n",
104 i == THUNK_HOST ? "host" : "target", offset, max_align);
105 #endif
106 }
107 }
109 void thunk_register_struct_direct(int id, const char *name, StructEntry *se1)
110 {
111 StructEntry *se;
112 se = struct_entries + id;
113 *se = *se1;
114 se->name = name;
115 }
118 /* now we can define the main conversion functions */
119 const argtype *thunk_convert(void *dst, const void *src,
120 const argtype *type_ptr, int to_host)
121 {
122 int type;
124 type = *type_ptr++;
125 switch(type) {
126 case TYPE_CHAR:
127 *(uint8_t *)dst = *(uint8_t *)src;
128 break;
129 case TYPE_SHORT:
130 *(uint16_t *)dst = tswap16(*(uint16_t *)src);
131 break;
132 case TYPE_INT:
133 *(uint32_t *)dst = tswap32(*(uint32_t *)src);
134 break;
135 case TYPE_LONGLONG:
136 case TYPE_ULONGLONG:
137 *(uint64_t *)dst = tswap64(*(uint64_t *)src);
138 break;
139 #if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
140 case TYPE_LONG:
141 case TYPE_ULONG:
142 case TYPE_PTRVOID:
143 *(uint32_t *)dst = tswap32(*(uint32_t *)src);
144 break;
145 #elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
146 case TYPE_LONG:
147 case TYPE_ULONG:
148 case TYPE_PTRVOID:
149 if (to_host) {
150 *(uint64_t *)dst = tswap32(*(uint32_t *)src);
151 } else {
152 *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
153 }
154 break;
155 #else
156 #error unsupported conversion
157 #endif
158 case TYPE_ARRAY:
159 {
160 int array_length, i, dst_size, src_size;
161 const uint8_t *s;
162 uint8_t *d;
164 array_length = *type_ptr++;
165 dst_size = thunk_type_size(type_ptr, to_host);
166 src_size = thunk_type_size(type_ptr, 1 - to_host);
167 d = dst;
168 s = src;
169 for(i = 0;i < array_length; i++) {
170 thunk_convert(d, s, type_ptr, to_host);
171 d += dst_size;
172 s += src_size;
173 }
174 type_ptr = thunk_type_next(type_ptr);
175 }
176 break;
177 case TYPE_STRUCT:
178 {
179 int i;
180 const StructEntry *se;
181 const uint8_t *s;
182 uint8_t *d;
183 const argtype *field_types;
184 const int *dst_offsets, *src_offsets;
186 se = struct_entries + *type_ptr++;
187 if (se->convert[0] != NULL) {
188 /* specific conversion is needed */
189 (*se->convert[to_host])(dst, src);
190 } else {
191 /* standard struct conversion */
192 field_types = se->field_types;
193 dst_offsets = se->field_offsets[to_host];
194 src_offsets = se->field_offsets[1 - to_host];
195 d = dst;
196 s = src;
197 for(i = 0;i < se->nb_fields; i++) {
198 field_types = thunk_convert(d + dst_offsets[i],
199 s + src_offsets[i],
200 field_types, to_host);
201 }
202 }
203 }
204 break;
205 default:
206 fprintf(stderr, "Invalid type 0x%x\n", type);
207 break;
208 }
209 return type_ptr;
210 }
212 /* from em86 */
214 /* Utility function: Table-driven functions to translate bitmasks
215 * between X86 and Alpha formats...
216 */
217 unsigned int target_to_host_bitmask(unsigned int x86_mask,
218 bitmask_transtbl * trans_tbl)
219 {
220 bitmask_transtbl * btp;
221 unsigned int alpha_mask = 0;
223 for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
224 if((x86_mask & btp->x86_mask) == btp->x86_bits) {
225 alpha_mask |= btp->alpha_bits;
226 }
227 }
228 return(alpha_mask);
229 }
231 unsigned int host_to_target_bitmask(unsigned int alpha_mask,
232 bitmask_transtbl * trans_tbl)
233 {
234 bitmask_transtbl * btp;
235 unsigned int x86_mask = 0;
237 for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
238 if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
239 x86_mask |= btp->x86_bits;
240 }
241 }
242 return(x86_mask);
243 }