1 /* $Id: recode.h,v 1.8 2010/03/07 16:29:27 fredette Exp $ */
2 
3 /* tme/recode.h - public header file for recode support: */
4 
5 /*
6  * Copyright (c) 2007 Matt Fredette
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Matt Fredette.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifndef _TME_RECODE_H
37 #define _TME_RECODE_H
38 
39 #include <tme/common.h>
40 _TME_RCSID("$Id: recode.h,v 1.8 2010/03/07 16:29:27 fredette Exp $");
41 
42 /* includes: */
43 #include <tme/recode-host.h>
44 #include <tme/generic/ic.h>
45 #include <tme/token.h>
46 
47 /* macros: */
48 
49 /* log base two of power-of-two sizes: */
50 #define TME_RECODE_SIZE_1	(0)
51 #define TME_RECODE_SIZE_2	(1)
52 #define TME_RECODE_SIZE_4	(2)
53 #define TME_RECODE_SIZE_8	(3)
54 #define TME_RECODE_SIZE_16	(4)
55 #define TME_RECODE_SIZE_32	(5)
56 #define TME_RECODE_SIZE_64	(6)
57 #define TME_RECODE_SIZE_128	(7)
58 
59 /* configure initially defines TME_RECODE_SIZE_GUEST_MAX to be the log
60    base two of the largest natural word size (in bits) of all guests
61    with recode support that are selected at configure time.
62 
63    however, we don't support guest sizes larger than twice the host's
64    size, or guest sizes for which we don't have an integral type, so
65    we may have to reduce TME_RECODE_SIZE_GUEST_MAX.
66    TME_RECODE_SIZE_GUEST_MAX is always at least five, to support
67    32-bit guests: */
68 
69 /* limit TME_RECODE_SIZE_GUEST_MAX to (TME_RECODE_SIZE_HOST + 1): */
70 #if TME_RECODE_SIZE_GUEST_MAX > (TME_RECODE_SIZE_HOST + 1)
71 #undef TME_RECODE_SIZE_GUEST_MAX
72 #define TME_RECODE_SIZE_GUEST_MAX (TME_RECODE_SIZE_HOST + 1)
73 #endif /* TME_RECODE_SIZE_GUEST_MAX > (TME_RECODE_SIZE_HOST + 1) */
74 
75 /* we don't support guests larger than 128 bits: */
76 #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_128
77 #undef TME_RECODE_SIZE_GUEST_MAX
78 #define TME_RECODE_SIZE_GUEST_MAX	TME_RECODE_SIZE_128
79 #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_128 */
80 
81 /* we only support 128-bit guests if we have a 128-bit integral type: */
82 #if TME_RECODE_SIZE_GUEST_MAX == TME_RECODE_SIZE_128
83 #ifdef TME_HAVE_INT128_T
84 typedef tme_int128_t tme_recode_guest_t;
85 typedef tme_uint128_t tme_recode_uguest_t;
86 #else  /* !TME_HAVE_INT128_T */
87 #undef TME_RECODE_SIZE_128
88 #undef TME_RECODE_SIZE_GUEST_MAX
89 #define TME_RECODE_SIZE_GUEST_MAX	TME_RECODE_SIZE_64
90 #endif /* !TME_HAVE_INT128_T */
91 #endif /* TME_RECODE_SIZE_GUEST_MAX == TME_RECODE_SIZE_128 */
92 
93 /* we only support 64-bit guests if we have a 64-bit integral type: */
94 #if TME_RECODE_SIZE_GUEST_MAX == TME_RECODE_SIZE_64
95 #ifdef TME_HAVE_INT64_T
96 typedef tme_int64_t tme_recode_guest_t;
97 typedef tme_uint64_t tme_recode_uguest_t;
98 #else  /* !TME_HAVE_INT64_T */
99 #undef TME_RECODE_SIZE_64
100 #undef TME_RECODE_SIZE_GUEST_MAX
101 #define TME_RECODE_SIZE_GUEST_MAX	TME_RECODE_SIZE_64
102 #endif /* !TME_HAVE_INT64_T */
103 #endif /* TME_RECODE_SIZE_GUEST_MAX == TME_RECODE_SIZE_64 */
104 
105 /* we always support at least 32-bit guests: */
106 #if TME_RECODE_SIZE_GUEST_MAX <= TME_RECODE_SIZE_32
107 typedef tme_int32_t tme_recode_guest_t;
108 typedef tme_uint32_t tme_recode_uguest_t;
109 #undef TME_RECODE_SIZE_GUEST_MAX
110 #define TME_RECODE_SIZE_GUEST_MAX	TME_RECODE_SIZE_32
111 #endif /* TME_RECODE_SIZE_GUEST_MAX <= TME_RECODE_SIZE_32 */
112 
113 /* this evaluates to nonzero if the size is double-host-size: */
114 #define TME_RECODE_SIZE_IS_DOUBLE_HOST(size)		\
115   (TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_HOST	\
116    && (size) == TME_RECODE_SIZE_GUEST_MAX)
117 
118 /* this evaluates to nonzero if the given unsigned value fits in the
119    given size.  the value is only evaluated once, while the size is
120    evaluated many times and so should be a constant.  NB that we are
121    careful not to generate any compile-time shift counts that equal to
122    or greater than the number of bits in value's type: */
123 #define TME_RECODE_SIZE_FITS(value, size)		\
124   (((sizeof(value) * 8) <= TME_BIT(size))		\
125    || (((value)						\
126 	>> ((((TME_BIT(size)				\
127 	       > (sizeof(unsigned int) * 8))		\
128 	      * (TME_BIT(size)				\
129 		 - (sizeof(unsigned int) * 8)))		\
130 	     + 1)					\
131 	    * ((sizeof(value) * 8) > TME_BIT(size))))	\
132        < (((unsigned int) 1)				\
133 	  << (TME_MIN(TME_BIT(size),			\
134 		      sizeof(unsigned int) * 8)		\
135 	      - 1))))
136 
137 /* conditions: */
138 #define TME_RECODE_COND_MOD_NOT	TME_BIT(0)
139 #define _TME_RECODE_COND(x)	((x) << 4)
140 #define TME_RECODE_COND_UNDEF	_TME_RECODE_COND(0)
141 #define TME_RECODE_COND_FALSE	_TME_RECODE_COND(1)
142 #define TME_RECODE_COND_N	_TME_RECODE_COND(2)
143 #define TME_RECODE_COND_C	_TME_RECODE_COND(3)
144 #define TME_RECODE_COND_V	_TME_RECODE_COND(4)
145 #define TME_RECODE_COND_Z	_TME_RECODE_COND(5)
146 #define TME_RECODE_COND_PE	_TME_RECODE_COND(6)
147 #define TME_RECODE_COND_BE	_TME_RECODE_COND(7)
148 #define TME_RECODE_COND_LE	_TME_RECODE_COND(8)
149 #define TME_RECODE_COND_L	_TME_RECODE_COND(9)
150 #define TME_RECODE_COND_X(n)	_TME_RECODE_COND(10 + (n))
151 
152 /* bitwise operations.  NB that these are not instruction opcodes: */
153 #define TME_RECODE_BITWISE_OR	TME_BIT(0)
154 #define TME_RECODE_BITWISE_NOR	TME_BIT(1)
155 #define TME_RECODE_BITWISE_AND	TME_BIT(2)
156 #define TME_RECODE_BITWISE_NAND	TME_BIT(3)
157 
158 /* instruction classes: */
159 #define TME_RECODE_INSN_CLASS_ADDITIVE		(0)
160 #define TME_RECODE_INSN_CLASS_LOGICAL		(1)
161 #define TME_RECODE_INSN_CLASS_SHIFT		(2)
162 #define TME_RECODE_INSN_CLASS_EXT		(3)
163 
164 /* instruction opcodes: */
165 /* NB: these are in a deliberate order: */
166 #define TME_RECODE_OPCODE_ANDN			(0)
167 #define TME_RECODE_OPCODE_ORN			(1)
168 #define TME_RECODE_OPCODE_XORN			(2)
169 #define TME_RECODE_OPCODE_SUB			(3)
170 #define TME_RECODE_OPCODE_SUBC			(4)
171 #define TME_RECODE_OPCODE_AND			(5)
172 #define TME_RECODE_OPCODE_OR			(6)
173 #define TME_RECODE_OPCODE_XOR			(7)
174 #define TME_RECODE_OPCODE_ADD			(8)
175 #define TME_RECODE_OPCODE_ADDC			(9)
176 #define TME_RECODE_OPCODE_SHLL     		(10)
177 #define TME_RECODE_OPCODE_SHRL     		(11)
178 #define TME_RECODE_OPCODE_SHRA     		(12)
179 #define TME_RECODE_OPCODE_EXTZ     		(13)
180 #define TME_RECODE_OPCODE_EXTS     		(14)
181 #define  TME_RECODE_OPCODES_INTEGER		 (15)
182 #define TME_RECODE_OPCODE_GUEST     		(15)
183 #define TME_RECODE_OPCODE_DEFC			(16)
184 #define TME_RECODE_OPCODE_IF			(17)
185 #define TME_RECODE_OPCODE_ELSE			(18)
186 #define TME_RECODE_OPCODE_ENDIF			(19)
187 						/* 20 unused */
188 #define TME_RECODE_OPCODE_RW			(21)
189 
190 /* this maps a recode logical noncommutative opcode to its plain version: */
191 #define TME_RECODE_OPCODE_LOGICALN_TO_PLAIN(opcode)	\
192   (((opcode) + TME_RECODE_OPCODE_AND) - TME_RECODE_OPCODE_ANDN)
193 #if TME_RECODE_OPCODE_LOGICALN_TO_PLAIN(TME_RECODE_OPCODE_ANDN) != TME_RECODE_OPCODE_AND
194 #error "TME_RECODE_OPCODE_ values changed"
195 #endif
196 #if TME_RECODE_OPCODE_LOGICALN_TO_PLAIN(TME_RECODE_OPCODE_ORN) != TME_RECODE_OPCODE_OR
197 #error "TME_RECODE_OPCODE_ values changed"
198 #endif
199 #if TME_RECODE_OPCODE_LOGICALN_TO_PLAIN(TME_RECODE_OPCODE_XORN) != TME_RECODE_OPCODE_XOR
200 #error "TME_RECODE_OPCODE_ values changed"
201 #endif
202 
203 /* guest registers and guest non-register operands: */
204 #define TME_RECODE_REG_GUEST(x)			(x)
205 
206 /* non-register source operands: */
207 #define TME_RECODE_OPERAND_ZERO			TME_RECODE_REG_GUEST(-1)
208 #define TME_RECODE_OPERAND_IMM			TME_RECODE_REG_GUEST(-2)
209 #define TME_RECODE_OPERAND_UNDEF		TME_RECODE_REG_GUEST(-3)
210 
211 /* non-register destination operands: */
212 #define TME_RECODE_OPERAND_NULL			TME_RECODE_REG_GUEST(-1)
213 
214 /* the undefined guest register window: */
215 #define TME_RECODE_REG_GUEST_WINDOW_UNDEF	(3)
216 
217 /* host registers: */
218 #define TME_RECODE_REG_HOST(x)			(x)
219 
220 /* guest register info: */
221 /* NB: these are in a deliberate order, to match union
222    tme_recode_reginfo and the tme_recode_reginfo_ macros for its
223    parts: */
224 #define TME_RECODE_REGINFO_TYPE_FLAT		(0)
225 #define TME_RECODE_REGINFO_TYPE_WINDOW(n) 	(((n) + 1) << 30)
226 #define TME_RECODE_REGINFO_TYPE_IS_WINDOW(x)	((x) & (TME_RECODE_REG_GUEST_WINDOW_UNDEF << 30))
227 #define TME_RECODE_REGINFO_TYPE_WHICH_WINDOW(x)	(((x) >> 30) - 1)
228 #define TME_RECODE_REGINFO_TYPE_FIXED		TME_BIT(29)
229 #define TME_RECODE_REGINFO_TYPE_TEMPORARY	TME_BIT(28)
230 #define TME_RECODE_REGINFO_RUSES(x)		((tme_uint16_t) (x))
231 #define TME_RECODE_REGINFO_TAGS_VALID		TME_BIT(15)
232 #define TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK	(0x1e00)
233 #define TME_RECODE_REGINFO_TAGS_CLEAN		(1 << 8)
234 #define TME_RECODE_REGINFO_TAGS_WHICH_VALID_SIZE(x)			\
235   TME_FIELD_MASK_EXTRACTU(x, TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK)
236 #define TME_RECODE_REGINFO_TAGS_ARE_VALID_SIZE(x, size)			\
237   (TME_RECODE_REGINFO_TAGS_WHICH_VALID_SIZE(x)				\
238    >= (size))
239 #if ((TME_RECODE_REGINFO_TAGS_CLEAN << 1) & TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK) == 0
240 #error "TME_RECODE_REGINFO_TAGS_ values changed"
241 #endif
242 #define TME_RECODE_REGINFO_TAGS_WHICH_DIRTY_SIZE(x)				\
243   TME_FIELD_MASK_EXTRACTU((((TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK		\
244 			     + TME_RECODE_REGINFO_TAGS_CLEAN)			\
245 			    + ((x)						\
246 			       & TME_RECODE_REGINFO_TAGS_CLEAN))		\
247 			   & (x)),						\
248 			  TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK)
249 #define TME_RECODE_REGINFO_TAGS_ARE_DIRTY(x)	(TME_RECODE_REGINFO_TAGS_WHICH_DIRTY_SIZE(x) != 0)
250 #define TME_RECODE_REGINFO_TAGS_VALID_SIZE(x)	((x) * _TME_FIELD_MASK_FACTOR(TME_RECODE_REGINFO_TAGS_VALID_SIZE_MASK))
251 #define TME_RECODE_REGINFO_TAGS_REG_HOST(x)	(x)
252 #define TME_RECODE_REGINFO_TAGS_WHICH_REG_HOST(x) ((tme_uint8_t) (x))
253 
254 /* special register read-uses values: */
255 #define TME_RECODE_REG_RUSES_FREE		(0)
256 #define TME_RECODE_REG_RUSES_RESERVED		(TME_RECODE_REGINFO_TAGS_VALID)
257 
258 /* special register read-uses record values: */
259 #define TME_RECODE_REG_RUSES_RECORD_REG_GUEST(x)	(TME_RECODE_REG_RUSES_RESERVED + (x))
260 #define TME_RECODE_REG_RUSES_RECORD_UNDEF	(TME_RECODE_REG_RUSES_RESERVED + (TME_RECODE_REG_RUSES_RESERVED - 1))
261 
262 /* recode flags: */
263 #define TME_RECODE_FLAG(n)			(n)
264 #define TME_RECODE_FLAG_CARRY			TME_RECODE_FLAG(0)
265 #define TME_RECODE_FLAG_JUMP			TME_RECODE_FLAG(1)
266 
267 /* chain information: */
268 #define TME_RECODE_CHAIN_INFO_UNCONDITIONAL	(0 << 0)
269 #define TME_RECODE_CHAIN_INFO_CONDITIONAL	(1 << 0)
270 #define TME_RECODE_CHAIN_INFO_NEAR		(0 << 1)
271 #define TME_RECODE_CHAIN_INFO_FAR		(1 << 1)
272 #define TME_RECODE_CHAIN_INFO_JUMP		(1 << 2)
273 #define TME_RECODE_CHAIN_INFO_RETURN		(1 << 3)
274 #define TME_RECODE_CHAIN_INFO_CALL		(1 << 4)
275 #define TME_RECODE_CHAIN_INFO_ALTERNATE_NEAR	(0 << 5)
276 #define TME_RECODE_CHAIN_INFO_ALTERNATE_FAR	(1 << 5)
277 
278 /* the maximum size of a single instructions thunk, in insns: */
279 #define TME_RECODE_INSNS_THUNK_INSNS_MAX	\
280   ((TME_RECODE_HOST_THUNK_SIZE_MAX		\
281     - TME_RECODE_HOST_INSN_THUNK_OVERHEAD)	\
282    / TME_RECODE_HOST_INSN_SIZE_MAX)
283 
284 /* types: */
285 
286 /* one flag: */
287 struct tme_recode_flag {
288 
289   /* the condition that sets the flag: */
290   tme_uint16_t tme_recode_flag_cond;
291 
292   /* the operand size: */
293   tme_uint8_t tme_recode_flag_size;
294 
295   /* the flag: */
296   tme_recode_uguest_t tme_recode_flag_flag;
297 };
298 
299 /* a flags thunk: */
300 struct tme_recode_flags_thunk {
301 
302   /* the flags that are changed in any way (undefined, defined, set,
303      clear) by the thunk: */
304   tme_recode_uguest_t tme_recode_flags_thunk_flags_changed;
305 
306   /* the flags that are changed in a deterministic way (defined, set,
307      clear) by the thunk: */
308   tme_recode_uguest_t tme_recode_flags_thunk_flags_defined;
309 
310   /* the struct tme_ic offset of the flags register: */
311   tme_uint32_t tme_recode_flags_thunk_flags_offset;
312 
313   /* the host-specific members: */
314   TME_RECODE_HOST_FLAGS_THUNK;
315 };
316 
317 /* a flags group: */
318 struct tme_recode_flags_group {
319 
320   /* flags groups are kept on a list: */
321   _tme_const struct tme_recode_flags_group *tme_recode_flags_group_next;
322 
323   /* the class and size of instructions in this flags group: */
324   tme_uint8_t tme_recode_flags_group_insn_class;
325   tme_uint8_t tme_recode_flags_group_insn_size;
326 
327   /* the size and index of the flags register in the struct tme_ic: */
328   tme_uint8_t tme_recode_flags_group_flags_reg_size;
329   tme_uint32_t tme_recode_flags_group_flags_reg;
330 
331   /* the flags for all of the instructions in the group: */
332   _tme_const struct tme_recode_flag *tme_recode_flags_group_flags;
333 
334   /* the guest flags function: */
335   void (*tme_recode_flags_group_guest_func) _TME_P((struct tme_ic *, tme_recode_uguest_t, tme_recode_uguest_t, tme_recode_uguest_t));
336 
337   /* the flags thunk: */
338   struct tme_recode_flags_thunk *tme_recode_flags_group_thunk;
339 };
340 
341 /* a conditions thunk: */
342 struct tme_recode_conds_thunk {
343 
344   /* the flags tested by the thunk: */
345   tme_recode_uguest_t tme_recode_conds_thunk_flags;
346 
347   /* the struct tme_ic offset of the flags register: */
348   tme_uint32_t tme_recode_conds_thunk_flags_offset;
349 
350   /* the host-specific members: */
351   TME_RECODE_HOST_CONDS_THUNK;
352 };
353 
354 /* a conditions group: */
355 struct tme_recode_conds_group {
356 
357   /* conditions groups are kept on a list: */
358   _tme_const struct tme_recode_conds_group *tme_recode_conds_group_next;
359 
360   /* the size and index of the flags register in the struct tme_ic: */
361   tme_uint8_t tme_recode_conds_group_flags_reg_size;
362   tme_uint32_t tme_recode_conds_group_flags_reg;
363 
364   /* the flags tested by the conditions in the group: */
365   tme_recode_uguest_t tme_recode_conds_group_flags;
366 
367   /* the number of conditions in the group.  this must be at least
368      one, and not more than 32: */
369   tme_uint8_t tme_recode_conds_group_cond_count;
370 
371   /* the guest condition function.  this returns nonzero if the
372      condition is true for the given flags: */
373   int (*tme_recode_conds_group_guest_func) _TME_P((tme_recode_uguest_t, tme_uint32_t));
374 
375   /* the conditions thunk: */
376   struct tme_recode_conds_thunk *tme_recode_conds_group_thunk;
377 };
378 
379 #ifdef TME_RECODE_SIZE_128
380 #if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128
381 
382 /* a TLB entry with a 16-bit context and a 128-bit address: */
383 struct tme_recode_tlb_c16_a128 {
384 
385   /* adding an offset in this TLB entry's page to this pointer gives
386      the host memory address: */
387   _tme_const tme_shared tme_uint8_t *tme_recode_tlb_c16_a128_memory;
388 
389   /* the page frame of this TLB entry's page: */
390   tme_uint128_t tme_recode_tlb_c16_a128_page;
391 
392   /* the flags for this TLB entry: */
393   tme_uint32_t tme_recode_tlb_c16_a128_flags;
394 
395   /* the context for this TLB entry: */
396   tme_uint16_t tme_recode_tlb_c16_a128_context;
397 
398   /* the token for this TLB entry: */
399   struct tme_token tme_recode_tlb_c16_a128_token;
400 };
401 
402 #endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128 */
403 #endif /* TME_RECODE_SIZE_128 */
404 
405 #ifdef TME_RECODE_SIZE_64
406 #if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64
407 
408 /* a TLB entry with a 16-bit context and a 64-bit address: */
409 struct tme_recode_tlb_c16_a64 {
410 
411   /* adding an offset in this TLB entry's page to this pointer gives
412      the host memory address: */
413   _tme_const tme_shared tme_uint8_t *tme_recode_tlb_c16_a64_memory;
414 
415   /* the page frame of this TLB entry's page: */
416   tme_uint64_t tme_recode_tlb_c16_a64_page;
417 
418   /* the flags for this TLB entry: */
419   tme_uint32_t tme_recode_tlb_c16_a64_flags;
420 
421   /* the context for this TLB entry: */
422   tme_uint16_t tme_recode_tlb_c16_a64_context;
423 
424   /* the token for this TLB entry: */
425   struct tme_token tme_recode_tlb_c16_a64_token;
426 };
427 
428 #endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64 */
429 #endif /* TME_RECODE_SIZE_64 */
430 
431 /* a TLB entry with a 16-bit context and a 32-bit address: */
432 struct tme_recode_tlb_c16_a32 {
433 
434   /* adding an offset in this TLB entry's page to this pointer gives
435      the host memory address: */
436   _tme_const tme_shared tme_uint8_t *tme_recode_tlb_c16_a32_memory;
437 
438   /* the page frame of this TLB entry's page: */
439   tme_uint32_t tme_recode_tlb_c16_a32_page;
440 
441   /* the flags for this TLB entry: */
442   tme_uint32_t tme_recode_tlb_c16_a32_flags;
443 
444   /* the context for this TLB entry: */
445   tme_uint16_t tme_recode_tlb_c16_a32_context;
446 
447   /* the token for this TLB entry: */
448   struct tme_token tme_recode_tlb_c16_a32_token;
449 };
450 
451 /* an address type: */
452 struct tme_recode_address_type {
453 
454   /* the struct tme_ic_offset of the tme_bus_context_t context
455      register, or less than zero if this address type doesn't include
456      a context: */
457   tme_int32_t tme_recode_address_type_context_ic_offset;
458 
459   /* if this address type includes a context, this is the size of a
460      context value: */
461   tme_uint8_t tme_recode_address_type_context_size;
462 
463   /* the address size and signedness: */
464   unsigned int tme_recode_address_type_size;
465   int tme_recode_address_type_signed;
466 
467   /* the minimum alignment for an address to not always cause an
468      assist: */
469   /* NB: this is a power of two value in bytes, not a TME_RECODE_SIZE_: */
470   tme_uint32_t tme_recode_address_type_align_min;
471 
472   /* the TLB flags for this address type.  any TLB flag for the
473      address type that isn't cleared by the mask in the TLB entry or
474      any mask in the struct tme_ic causes an assist: */
475   tme_uint32_t tme_recode_address_type_tlb_flags;
476 
477   /* the struct tme_ic offset of any tme_uint32_t TLB flags: */
478   tme_int32_t tme_recode_address_type_tlb_flags_ic_offset;
479 
480   /* a mask of consecutive address bits that select a TLB entry: */
481   tme_uint32_t tme_recode_address_type_mask_tlb_index;
482 
483   /* the struct tme_ic offset of the first recode TLB: */
484   tme_int32_t tme_recode_address_type_tlb0_ic_offset;
485 };
486 
487 /* a read or a write thunk: */
488 struct tme_recode_rw_thunk {
489 
490   /* the address size and register size: */
491   tme_uint8_t tme_recode_rw_thunk_address_size;
492   tme_uint8_t tme_recode_rw_thunk_reg_size;
493 
494   /* this is nonzero if this is a write: */
495   tme_uint8_t tme_recode_rw_thunk_write;
496 
497   /* the host-specific members: */
498   TME_RECODE_HOST_RW_THUNK;
499 };
500 
501 /* a read or a write: */
502 struct tme_recode_rw {
503 
504   /* reads and writes are kept on a list: */
505   _tme_const struct tme_recode_rw *tme_recode_rw_next;
506 
507   /* the address type: */
508   struct tme_recode_address_type tme_recode_rw_address_type;
509 
510   /* this is nonzero if this is a write: */
511   int tme_recode_rw_write;
512 
513   /* the register size: */
514   unsigned int tme_recode_rw_reg_size;
515 
516   /* the memory size, byte order, and signedness: */
517   unsigned int tme_recode_rw_memory_size;
518   unsigned int tme_recode_rw_memory_endian;
519   int tme_recode_rw_memory_signed;
520 
521   /* the bus boundary.  reads and writes are split into atomic parts
522      at bus boundaries: */
523   /* NB: this is a power of two value in bytes, not a TME_RECODE_SIZE_: */
524   tme_uint32_t tme_recode_rw_bus_boundary;
525 
526   /* the assist functions: */
527   union {
528 
529     /* the read assist function: */
530     tme_recode_uguest_t (*_tme_recode_rw_guest_func_u_read) _TME_P((struct tme_ic *, tme_recode_uguest_t));
531 #define tme_recode_rw_guest_func_read _tme_recode_rw_guest_func_u._tme_recode_rw_guest_func_u_read
532 
533     /* the write assist function: */
534     void (*_tme_recode_rw_guest_func_u_write) _TME_P((struct tme_ic *, tme_recode_uguest_t, tme_recode_uguest_t));
535 #define tme_recode_rw_guest_func_write _tme_recode_rw_guest_func_u._tme_recode_rw_guest_func_u_write
536   } _tme_recode_rw_guest_func_u;
537 
538   /* the read/write thunk: */
539   _tme_const struct tme_recode_rw_thunk *tme_recode_rw_thunk;
540 };
541 
542 /* a chain thunk: */
543 struct tme_recode_chain_thunk {
544 
545   /* the host-specific members: */
546   TME_RECODE_HOST_CHAIN_THUNK;
547 };
548 
549 /* a chain: */
550 struct tme_recode_chain {
551 
552   /* the guest register with the next PC: */
553   tme_int16_t tme_recode_chain_reg_guest;
554 
555   /* the address type: */
556   struct tme_recode_address_type tme_recode_chain_address_type;
557 };
558 
559 /* one instruction: */
560 struct tme_recode_insn {
561 
562   /* the opcode and size: */
563   tme_uint8_t tme_recode_insn_opcode;
564   tme_uint8_t tme_recode_insn_size;
565 
566   /* two source operands and the destination operand: */
567   tme_int16_t tme_recode_insn_operands[3];
568 #define tme_recode_insn_operand_src tme_recode_insn_operands
569 #define tme_recode_insn_operand_dst tme_recode_insn_operands[2]
570 
571   /* any immediate for the instruction: */
572   union {
573     tme_recode_guest_t _tme_recode_insn_imm_u_guest;
574     tme_recode_uguest_t _tme_recode_insn_imm_u_uguest;
575   } _tme_recode_insn_imm_u;
576 #define tme_recode_insn_imm_guest _tme_recode_insn_imm_u._tme_recode_insn_imm_u_guest
577 #define tme_recode_insn_imm_uguest _tme_recode_insn_imm_u._tme_recode_insn_imm_u_uguest
578 #ifdef TME_RECODE_SIZE_128
579 #if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128
580 #define tme_recode_insn_imm_128 tme_recode_insn_imm_guest
581 #define tme_recode_insn_imm_u128 tme_recode_insn_imm_uguest
582 #endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128 */
583 #endif /* TME_RECODE_SIZE_128 */
584 #ifdef TME_RECODE_SIZE_64
585 #if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64
586 #define tme_recode_insn_imm_64 tme_recode_insn_imm_guest
587 #define tme_recode_insn_imm_u64 tme_recode_insn_imm_uguest
588 #endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64 */
589 #endif /* TME_RECODE_SIZE_64 */
590 #define tme_recode_insn_imm_32 tme_recode_insn_imm_guest
591 #define tme_recode_insn_imm_u32 tme_recode_insn_imm_uguest
592 #define tme_recode_insn_imm_16 tme_recode_insn_imm_guest
593 #define tme_recode_insn_imm_u16 tme_recode_insn_imm_uguest
594 #define tme_recode_insn_imm_8 tme_recode_insn_imm_guest
595 #define tme_recode_insn_imm_u8 tme_recode_insn_imm_uguest
596 
597   /* any extra information needed by the instruction: */
598   union {
599 
600     /* a generic pointer: */
601     void *_tme_recode_insn_extra_u_pointer;
602 
603     /* any thunk offset: */
604     tme_recode_thunk_off_t _tme_recode_insn_extra_u_thunk_off;
605 #define tme_recode_insn_thunk_off _tme_recode_insn_extra_u._tme_recode_insn_extra_u_thunk_off
606 
607     /* any flags thunk: */
608     _tme_const struct tme_recode_flags_thunk *_tme_recode_insn_extra_u_flags_thunk;
609 #define tme_recode_insn_flags_thunk _tme_recode_insn_extra_u._tme_recode_insn_extra_u_flags_thunk
610 
611     /* any conditions thunk: */
612     _tme_const struct tme_recode_conds_thunk *_tme_recode_insn_extra_u_conds_thunk;
613 #define tme_recode_insn_conds_thunk _tme_recode_insn_extra_u._tme_recode_insn_extra_u_conds_thunk
614 
615     /* any read/write thunk: */
616     _tme_const struct tme_recode_rw_thunk *_tme_recode_insn_extra_u_rw_thunk;
617 #define tme_recode_insn_rw_thunk _tme_recode_insn_extra_u._tme_recode_insn_extra_u_rw_thunk
618 
619     /* the guest function: */
620     tme_recode_uguest_t (*_tme_recode_insn_extra_u_guest_func) _TME_P((struct tme_ic *, tme_recode_uguest_t, tme_recode_uguest_t));
621 #define tme_recode_insn_guest_func _tme_recode_insn_extra_u._tme_recode_insn_extra_u_guest_func
622   } _tme_recode_insn_extra_u;
623 };
624 
625 /* an instructions group: */
626 struct tme_recode_insns_group {
627 
628   /* the instructions in the group: */
629   struct tme_recode_insn *tme_recode_insns_group_insns;
630 
631   /* one past the last instruction in the group: */
632   struct tme_recode_insn *tme_recode_insns_group_insns_end;
633 
634   /* the source address for the corresponding guest instructions: */
635   _tme_const tme_shared tme_uint8_t *tme_recode_insns_group_src;
636 
637   /* any validity flag for the group: */
638   _tme_const tme_shared tme_uint8_t *tme_recode_insns_group_valid_byte;
639   tme_uint8_t tme_recode_insns_group_valid_mask;
640 
641   /* the chain thunk for the group: */
642   _tme_const struct tme_recode_chain_thunk *tme_recode_insns_group_chain_thunk;
643 
644   /* the chain information for the group: */
645   tme_uint32_t tme_recode_insns_group_chain_info;
646 };
647 
648 /* the guest register info union: */
649 /* NB that this union, and the tme_recode_reginfo_ macros for its
650    parts, must match the TME_RECODE_REGINFO_ values: */
651 union tme_recode_reginfo {
652   tme_uint8_t _tme_recode_reginfo_uint8s[4];
653   tme_uint16_t _tme_recode_reginfo_uint16s[2];
654   tme_uint32_t tme_recode_reginfo_all;
655 };
656 #ifndef WORDS_BIGENDIAN
657 #define tme_recode_reginfo_type	_tme_recode_reginfo_uint8s[3]
658 #define tme_recode_reginfo_tags_ruses _tme_recode_reginfo_uint16s[0]
659 #else  /* WORDS_BIGENDIAN */
660 #define tme_recode_reginfo_type	_tme_recode_reginfo_uint8s[0]
661 #define tme_recode_reginfo_tags_ruses _tme_recode_reginfo_uint16s[1]
662 #endif /* WORDS_BIGENDIAN */
663 
664 /* a recode ic: */
665 struct tme_recode_ic {
666 
667   /* this maps from host register to ruses: */
668   tme_uint16_t tme_recode_ic_reg_host_to_ruses[TME_RECODE_REG_HOST_UNDEF];
669 
670   /* this maps from host register to guest register: */
671   tme_uint16_t tme_recode_ic_reg_host_to_reg_guest[TME_RECODE_REG_HOST_UNDEF];
672 
673   /* the register size: */
674   tme_uint8_t tme_recode_ic_reg_size;
675 
676   /* the count of guest registers: */
677   tme_uint32_t tme_recode_ic_reg_count;
678 
679   /* the next position in the thunk build memory: */
680   tme_recode_host_insn_t *tme_recode_ic_thunk_build_next;
681 
682   /* one past the last position in the thunk build memory: */
683   _tme_const tme_recode_host_insn_t *tme_recode_ic_thunk_build_end;
684 
685   /* the thunk offset of the first variable thunk: */
686   tme_recode_thunk_off_t tme_recode_ic_thunk_off_variable;
687 
688   /* the host-specific members: */
689   TME_RECODE_HOST_IC;
690 
691   /* up to four reserved registers: */
692   struct {
693     tme_uint16_t tme_reg_host_reserve_reg_host;
694     tme_uint16_t tme_reg_host_reserve_ruses;
695   } tme_recode_ic_reg_host_reserve[4];
696   unsigned int tme_recode_ic_reg_host_reserve_next;
697 
698   /* the read-uses records: */
699   tme_uint16_t *tme_recode_ic_reg_guest_ruses_records;
700   tme_uint32_t tme_recode_ic_reg_guest_ruses_record_count;
701   tme_uint32_t tme_recode_ic_reg_guest_ruses_record_next;
702 
703   /* the flags groups for this ic: */
704   _tme_const struct tme_recode_flags_group *tme_recode_ic_flags_groups;
705 
706   /* the conditions groups for this ic: */
707   _tme_const struct tme_recode_conds_group *tme_recode_ic_conds_groups;
708 
709   /* the reads and writes for this ic: */
710   _tme_const struct tme_recode_rw *tme_recode_ic_rws;
711 
712   /* the TLB page size for this ic: */
713   tme_uint32_t tme_recode_ic_tlb_page_size;
714 
715   /* the struct tme_ic offset of the pointer to the token for the
716      current instruction TLB entry: */
717   tme_int32_t tme_recode_ic_itlb_current_token_offset;
718 
719   /* the chain fixup function: */
720   tme_recode_thunk_off_t (*tme_recode_ic_chain_fixup) _TME_P((struct tme_ic *, tme_recode_thunk_off_t, tme_uint32_t));
721 
722   /* the struct tme_ic offset of the tme_uint32_t chain counter: */
723   tme_int32_t tme_recode_ic_chain_counter_offset;
724 
725   /* the number of entries in the chain return address stack: */
726   tme_uint32_t tme_recode_ic_chain_ras_size;
727 
728   /* the struct tme_ic offset of the tme_recode_ras_entry_t chain
729      return address stack: */
730   tme_int32_t tme_recode_ic_chain_ras_offset;
731 
732   /* the struct tme_ic offset of the tme_uint32_t chain return address
733      stack pointer: */
734   tme_int32_t tme_recode_ic_chain_ras_pointer_offset;
735 
736   /* the struct tme_ic offsets of window base registers, which are
737      also tme_int32_t struct tme_ic offsets: */
738   tme_int32_t tme_recode_ic_window_base_offsets[TME_RECODE_REG_GUEST_WINDOW_UNDEF];
739 
740   /* space for the dummy guest register information for the
741      non-register source and destination operands.  this dummy
742      information isn't actually accessed using this array; it's still
743      accessed using tme_recode_ic_reginfo[] below: */
744   union tme_recode_reginfo tme_recode_ic_reginfo_dummy[2];
745 
746   /* the guest register information.  the exact size of this array is
747      determined by the guest: */
748   union tme_recode_reginfo tme_recode_ic_reginfo[1];
749 };
750 
751 /* prototypes: */
752 
753 /* this initializes a new recode ic: */
754 void tme_recode_ic_new _TME_P((struct tme_recode_ic *, tme_recode_thunk_off_t));
755 
756 /* this returns a flags thunk for a flags group: */
757 _tme_const struct tme_recode_flags_thunk *tme_recode_flags_thunk _TME_P((struct tme_recode_ic *, _tme_const struct tme_recode_flags_group *));
758 
759 /* this returns a conditions thunk for a conditions group: */
760 _tme_const struct tme_recode_conds_thunk *tme_recode_conds_thunk _TME_P((struct tme_recode_ic *, _tme_const struct tme_recode_conds_group *));
761 
762 /* this returns a read/write thunk for a read or a write: */
763 _tme_const struct tme_recode_rw_thunk *tme_recode_rw_thunk _TME_P((struct tme_recode_ic *, _tme_const struct tme_recode_rw *));
764 
765 /* this clears the return address stack: */
766 void tme_recode_chain_ras_clear _TME_P((const struct tme_recode_ic *, struct tme_ic *));
767 
768 /* this returns a chain thunk: */
769 _tme_const struct tme_recode_chain_thunk *tme_recode_chain_thunk _TME_P((struct tme_recode_ic *, _tme_const struct tme_recode_chain *));
770 
771 /* this fixes up a chain: */
772 tme_recode_thunk_off_t tme_recode_chain_fixup _TME_P((struct tme_recode_ic *, tme_recode_thunk_off_t, tme_uint32_t, tme_recode_thunk_off_t, tme_recode_thunk_off_t));
773 
774 /* this returns an instructions thunk for an instructions group: */
775 tme_recode_thunk_off_t tme_recode_insns_thunk _TME_P((struct tme_recode_ic *, _tme_const struct tme_recode_insns_group *));
776 
777 /* this invalidates an instructions thunk: */
778 void tme_recode_insns_thunk_invalidate _TME_P((struct tme_recode_ic *, tme_recode_thunk_off_t));
779 
780 /* this invalidates all instructions thunks: */
781 void tme_recode_insns_thunk_invalidate_all _TME_P((struct tme_recode_ic *));
782 
783 #ifdef TME_RECODE_DEBUG
784 
785 /* this returns an opcode name: */
786 _tme_const char *tme_recode_opcode_dump _TME_P((unsigned int));
787 
788 /* this dumps a tme_recode_uguest_t: */
789 void tme_recode_uguest_dump _TME_P((tme_recode_uguest_t));
790 
791 /* this dumps a flags thunk: */
792 void tme_recode_flags_thunk_dump _TME_P((_tme_const struct tme_recode_ic *,
793 					 _tme_const struct tme_recode_flags_thunk *));
794 
795 /* this dumps a conditions thunk: */
796 void tme_recode_conds_thunk_dump _TME_P((_tme_const struct tme_recode_ic *,
797 					 _tme_const struct tme_recode_conds_thunk *,
798 					 _tme_const char * _tme_const *));
799 
800 /* this dumps a chain thunk: */
801 void tme_recode_chain_thunk_dump _TME_P((_tme_const struct tme_recode_ic *,
802 					 _tme_const struct tme_recode_chain_thunk *));
803 
804 #endif /* TME_RECODE_DEBUG */
805 
806 #endif /* _TME_RECODE_H */
807