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