Annotation of tme/libtme/host/x86/recode-x86.c, revision 1.1

1.1     ! root        1: /* $Id: recode-x86.c,v 1.5 2010/02/07 17:06:28 fredette Exp $ */
        !             2: 
        !             3: /* libtme/host/x86/recode-x86.c - recode code file for x86 hosts: */
        !             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: #include <tme/common.h>
        !            37: _TME_RCSID("$Id: recode-x86.c,v 1.5 2010/02/07 17:06:28 fredette Exp $");
        !            38: 
        !            39: #if TME_HAVE_RECODE
        !            40: 
        !            41: /* includes: */
        !            42: #include "recode-impl.h"
        !            43: 
        !            44: /* the maximum number of bytes in an x86 instruction: */
        !            45: #define TME_RECODE_X86_INSN_BYTES_MAX  (15)
        !            46: 
        !            47: /* register encodings: */
        !            48: #define TME_RECODE_X86_REG_A   (0)
        !            49: #define TME_RECODE_X86_REG_C   (1)
        !            50: #define TME_RECODE_X86_REG_D   (2)
        !            51: #define TME_RECODE_X86_REG_B   (3)
        !            52: #define TME_RECODE_X86_REG_SP  (4)
        !            53: #define TME_RECODE_X86_REG_BP  (5)
        !            54: #define TME_RECODE_X86_REG_SI  (6)
        !            55: #define TME_RECODE_X86_REG_DI  (7)
        !            56: #define TME_RECODE_X86_REG_N(n)        (n)
        !            57: #define TME_RECODE_X86_REG_XMM(n) (n)
        !            58: #define TME_RECODE_X86_REG_UNDEF (64)
        !            59: 
        !            60: /* flags: */
        !            61: #define TME_RECODE_X86_FLAG_Z                          (1 << 6)
        !            62: 
        !            63: /* REX prefixes and register number masking: */
        !            64: #if TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32
        !            65: #define _TME_RECODE_X86_REX(size, reg, n)      \
        !            66:   ((((size) == TME_RECODE_SIZE_8               \
        !            67:      && (reg) >= TME_RECODE_X86_REG_SP         \
        !            68:      && (reg) <= TME_RECODE_X86_REG_DI)                \
        !            69:     ? 0x40                                     \
        !            70:     : 0x00)                                    \
        !            71:    | ((size) > TME_RECODE_SIZE_32              \
        !            72:       ? 0x48                                   \
        !            73:       : 0x00)                                  \
        !            74:    | ((reg) >= TME_RECODE_X86_REG_N(8)         \
        !            75:       ? (0x40 | (1 << (n)))                    \
        !            76:       : 0x00))
        !            77: #define TME_RECODE_X86_REG(x)                          ((x) & 7)
        !            78: #else  /* TME_RECODE_SIZE_HOST == TME_RECODE_SIZE_32 */
        !            79: #define _TME_RECODE_X86_REX(size, reg, n)              (0x00)
        !            80: #define TME_RECODE_X86_REG(x)                          (x)
        !            81: #endif /* TME_RECODE_SIZE_HOST == TME_RECODE_SIZE_32 */
        !            82: #define TME_RECODE_X86_REX_B(size, reg)                        _TME_RECODE_X86_REX(size, reg, 0)
        !            83: #define TME_RECODE_X86_REX_X(reg)                      _TME_RECODE_X86_REX(0, reg, 1)
        !            84: #define TME_RECODE_X86_REX_R(size, reg)                        _TME_RECODE_X86_REX(size, reg, 2)
        !            85: #define TME_RECODE_X86_REX_W(size)                     _TME_RECODE_X86_REX(size, TME_RECODE_X86_REG_A, 3)
        !            86: 
        !            87: /* conditions: */
        !            88: #define TME_RECODE_X86_COND_NOT                                (1 << 0)
        !            89: #define TME_RECODE_X86_COND_O                          (0x0)
        !            90: #define TME_RECODE_X86_COND_C                          (0x2)
        !            91: #define TME_RECODE_X86_COND_Z                          (0x4)
        !            92: #define TME_RECODE_X86_COND_BE                         (0x6)
        !            93: #define TME_RECODE_X86_COND_S                          (0x8)
        !            94: #define TME_RECODE_X86_COND_PE                         (0xa)
        !            95: #define TME_RECODE_X86_COND_L                          (0xc)
        !            96: #define TME_RECODE_X86_COND_LE                         (0xe)
        !            97: 
        !            98: /* one-byte opcode table instructions: */
        !            99: #define TME_RECODE_X86_OPCODE_BINOP_ADD                        (0x00)
        !           100: #define TME_RECODE_X86_OPCODE_BINOP_OR                 (0x08)
        !           101: #define TME_RECODE_X86_OPCODE_BINOP_ADC                        (0x10)
        !           102: #define TME_RECODE_X86_OPCODE_BINOP_SBB                        (0x18)
        !           103: #define TME_RECODE_X86_OPCODE_BINOP_AND                        (0x20)
        !           104: #define TME_RECODE_X86_OPCODE_BINOP_SUB                        (0x28)
        !           105: #define TME_RECODE_X86_OPCODE_BINOP_XOR                        (0x30)
        !           106: #define TME_RECODE_X86_OPCODE_BINOP_CMP                        (0x38)
        !           107: #define TME_RECODE_X86_OPCODE_PUSH_Gv(reg)             (0x50 + TME_RECODE_X86_REG(reg))
        !           108: #define TME_RECODE_X86_OPCODE_POP_Gv(reg)              (0x58 + TME_RECODE_X86_REG(reg))
        !           109: #define TME_RECODE_X86_OPCODE_MOVS_El_Gv               (0x63)
        !           110: #define TME_RECODE_X86_PREFIX_OPSIZ                    (0x66)
        !           111: #define TME_RECODE_X86_OPCODE_PUSH_Ib                  (0x6a)
        !           112: #define TME_RECODE_X86_OPCODE_JCC(cond)                        (0x70 + (cond))
        !           113: #define TME_RECODE_X86_OPCODE_GRP1_Ib_Eb               (0x80)
        !           114: #define TME_RECODE_X86_OPCODE_GRP1_Iz_Ev               (0x81)
        !           115: #define TME_RECODE_X86_OPCODE_GRP1_Ib_Ev               (0x83)
        !           116: #define TME_RECODE_X86_OPCODE_BINOP_TEST               (0x84)
        !           117: #define TME_RECODE_X86_OPCODE_BINOP_XCHG               (0x86)
        !           118: #define TME_RECODE_X86_OPCODE_BINOP_MOV                        (0x88)
        !           119: #define  TME_RECODE_X86_OPCODE_BINOP_Gb_Eb              (0x0)
        !           120: #define  TME_RECODE_X86_OPCODE_BINOP_Gv_Ev              (0x1)
        !           121: #define  TME_RECODE_X86_OPCODE_BINOP_Eb_Gb              (0x2)
        !           122: #define  TME_RECODE_X86_OPCODE_BINOP_Ev_Gv              (0x3)
        !           123: #define  TME_RECODE_X86_OPCODE_BINOP_Iz_A               (0x5)
        !           124: #define  TME_RECODE_X86_OPCODE_GRP1_BINOP(binop)        ((binop) / 0x08)
        !           125: #define TME_RECODE_X86_OPCODE_LEA                      (0x8d)
        !           126: #define TME_RECODE_X86_OPCODE_PUSHF                    (0x9c)
        !           127: #define TME_RECODE_X86_OPCODE_POPF                     (0x9d)
        !           128: #define TME_RECODE_X86_OPCODE_MOV_Iv_Gv(reg)           (0xb8 + TME_RECODE_X86_REG(reg))
        !           129: #define TME_RECODE_X86_OPCODE_GRP2_Ib_Ev               (0xc1)
        !           130: #define  TME_RECODE_X86_OPCODE_GRP2_ROR                         (0x1)
        !           131: #define  TME_RECODE_X86_OPCODE_GRP2_SHL                         (0x4)
        !           132: #define  TME_RECODE_X86_OPCODE_GRP2_SHR                         (0x5)
        !           133: #define  TME_RECODE_X86_OPCODE_GRP2_SAR                         (0x7)
        !           134: #define TME_RECODE_X86_OPCODE_RET                      (0xc3)
        !           135: #define TME_RECODE_X86_OPCODE_MOV_Ib_Eb                        (0xc6)
        !           136: #define TME_RECODE_X86_OPCODE_MOV_Iz_Ev                        (0xc7)
        !           137: #define TME_RECODE_X86_OPCODE_GRP2_1_Ev                        (0xd1)
        !           138: #define TME_RECODE_X86_OPCODE_CALL_RELz                        (0xe8)
        !           139: #define TME_RECODE_X86_OPCODE_JMP_RELz                 (0xe9)
        !           140: #define TME_RECODE_X86_OPCODE_JMP_RELb                 (0xeb)
        !           141: #define TME_RECODE_X86_PREFIX_REP                      (0xf3)
        !           142: #define TME_RECODE_X86_OPCODE_GRP3_Eb                  (0xf6)
        !           143: #define TME_RECODE_X86_OPCODE_GRP3_Ev                  (0xf7)
        !           144: #define  TME_RECODE_X86_OPCODE_GRP3_TEST                (0x0)
        !           145: #define  TME_RECODE_X86_OPCODE_GRP3_NOT                         (0x2)
        !           146: #define  TME_RECODE_X86_OPCODE_GRP3_NEG                         (0x3)
        !           147: #define TME_RECODE_X86_OPCODE_GRP5                     (0xff)
        !           148: #define  TME_RECODE_X86_OPCODE_GRP5_CALL                (0x2)
        !           149: #define  TME_RECODE_X86_OPCODE_GRP5_JMP                         (0x4)
        !           150: #define  TME_RECODE_X86_OPCODE_GRP5_PUSH                (0x6)
        !           151: 
        !           152: /* two-byte opcode table instructions: */
        !           153: #define TME_RECODE_X86_OPCODE_ESC_0F                   (0x0f)
        !           154: #define TME_RECODE_X86_OPCODE0F_UD2                    (0x0b)
        !           155: #define TME_RECODE_X86_OPCODE0F_JCC(cond)              (0x80 + (cond))
        !           156: #define TME_RECODE_X86_OPCODE0F_SETCC(cond)            (0x90 + (cond))
        !           157: #define TME_RECODE_X86_OPCODE0F_SHRD_Ib_Gv_Ev          (0xac)
        !           158: #define TME_RECODE_X86_OPCODE0F_GRP15                  (0xae)
        !           159: #define  TME_RECODE_X86_OPCODE0F_GRP15_MFENCE          TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(0), 6)
        !           160: #define TME_RECODE_X86_OPCODE0F_MOVZ_Eb_Gv             (0xb6)
        !           161: #define TME_RECODE_X86_OPCODE0F_MOVZ_Ew_Gv             (0xb7)
        !           162: #define TME_RECODE_X86_OPCODE0F_MOVS_Eb_Gv             (0xbe)
        !           163: #define TME_RECODE_X86_OPCODE0F_MOVS_Ew_Gv             (0xbf)
        !           164: #define TME_RECODE_X86_OPCODE0F_BSWAP(reg)             (0xc8 + TME_RECODE_X86_REG(reg))
        !           165: 
        !           166: /* OPSIZ and REP two-byte opcode table instructions: */
        !           167: #define TME_RECODE_X86_OPCODE660F_MOVDQA_Wdq_Vdq       (0x6f)
        !           168: #define TME_RECODE_X86_OPCODEF30F_MOVDQU_Wdq_Vdq       (0x6f)
        !           169: #define TME_RECODE_X86_OPCODE660F_MOVQ_Vq_Wq           (0xd6)
        !           170: #define TME_RECODE_X86_OPCODEF30F_MOVQ_Wq_Vq           (0x7e)
        !           171: #define TME_RECODE_X86_OPCODE660F_MOVDQA_Vdq_Wdq       (0x7f)
        !           172: #define TME_RECODE_X86_OPCODEF30F_MOVDQU_Vdq_Wdq       (0x7f)
        !           173: 
        !           174: /* modR/M bytes: */
        !           175: #define TME_RECODE_X86_MOD_OPREG_RM(mod_rm, opreg)     ((mod_rm) + ((opreg) << 3))
        !           176: #define TME_RECODE_X86_MOD_RM_EA(reg)                  ((0x0 << 6) + TME_RECODE_X86_REG(reg))
        !           177: #define TME_RECODE_X86_MOD_RM_EA_DISP8(reg)            ((0x1 << 6) + TME_RECODE_X86_REG(reg))
        !           178: #define TME_RECODE_X86_MOD_RM_EA_DISP32(reg)           ((0x2 << 6) + TME_RECODE_X86_REG(reg))
        !           179: #define TME_RECODE_X86_MOD_RM_REG(reg)                 ((0x3 << 6) + TME_RECODE_X86_REG(reg))
        !           180: #define TME_RECODE_X86_EA_BASE_SIB                     TME_RECODE_X86_REG_SP
        !           181: #define TME_RECODE_X86_EA_BASE_NONE                    TME_RECODE_X86_REG_BP
        !           182: #define TME_RECODE_X86_EA_BASE_IP                      TME_RECODE_X86_EA_BASE_NONE
        !           183: 
        !           184: /* scale-index-base bytes: */
        !           185: #define TME_RECODE_X86_SIB(base, index, scale)         \
        !           186:   ((((((scale) - 1) - ((scale) == 4)) & 3) << 6)       \
        !           187:    | (TME_RECODE_X86_REG(index) << 3)                  \
        !           188:    | TME_RECODE_X86_REG(base))
        !           189: #define TME_RECODE_X86_SIB_INDEX_NONE                  TME_RECODE_X86_REG_SP
        !           190: #define TME_RECODE_X86_SIB_BASE_NONE                   TME_RECODE_X86_REG_BP
        !           191: 
        !           192: /* multibyte NOP instructions: */
        !           193: #define _TME_RECODE_X86_NOP2                           \
        !           194:   ((TME_RECODE_X86_OPCODE_BINOP_MOV                    \
        !           195:     + TME_RECODE_X86_OPCODE_BINOP_Gv_Ev)               \
        !           196:    + (TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(TME_RECODE_X86_REG_C), \
        !           197:                                  TME_RECODE_X86_REG_C) \
        !           198:       << 8))
        !           199: #define _TME_RECODE_X86_NOP3                           \
        !           200:   (TME_RECODE_X86_OPCODE_LEA                           \
        !           201:    + (TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_EA_DISP8(TME_RECODE_X86_REG_C), \
        !           202:                                  TME_RECODE_X86_REG_C) \
        !           203:         << 8)                                          \
        !           204:    + (0x00 << 16))
        !           205: #define _TME_RECODE_X86_NOP4                           \
        !           206:    (TME_RECODE_X86_OPCODE_LEA                          \
        !           207:     + (TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_EA_DISP8(TME_RECODE_X86_EA_BASE_SIB), \
        !           208:                                   TME_RECODE_X86_REG_C)\
        !           209:        << 8)                                           \
        !           210:     + (TME_RECODE_X86_SIB(TME_RECODE_X86_REG_C, TME_RECODE_X86_SIB_INDEX_NONE, 1) \
        !           211:        << 16)                                          \
        !           212:     + (0x00 << 24))
        !           213: #define TME_RECODE_X86_NOP3                            \
        !           214:   (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32           \
        !           215:    ? (TME_RECODE_X86_REX_R(TME_RECODE_SIZE_HOST,       \
        !           216:                           TME_RECODE_X86_REG_C)        \
        !           217:       + (_TME_RECODE_X86_NOP2                          \
        !           218:         << 8))                                         \
        !           219:    : _TME_RECODE_X86_NOP3)
        !           220: #define TME_RECODE_X86_NOP4                            \
        !           221:   (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32           \
        !           222:    ? (TME_RECODE_X86_REX_R(TME_RECODE_SIZE_HOST,       \
        !           223:                           TME_RECODE_X86_REG_C)        \
        !           224:       + (_TME_RECODE_X86_NOP3                          \
        !           225:         << 8))                                         \
        !           226:    : _TME_RECODE_X86_NOP4)
        !           227: 
        !           228: /* fixed registers: */
        !           229: 
        !           230: /* we always use the b register to hold the struct tme_ic *: */
        !           231: #define TME_RECODE_X86_REG_IC                          TME_RECODE_X86_REG_B
        !           232: 
        !           233: /* we use the insn generic thunk offset to hold a subs thunk
        !           234:    offset: */
        !           235: #define tme_recode_x86_insn_subs_thunk_off tme_recode_insn_thunk_off
        !           236: 
        !           237: /* this returns the bit number of the first set bit in the value.  it
        !           238:    returns zero if the value is zero.  this is slow, but it's only
        !           239:    meant to be used at initialization time: */
        !           240: static unsigned int
        !           241: _tme_recode_x86_ffs(tme_recode_uguest_t value)
        !           242: {
        !           243:   unsigned int shift;
        !           244: 
        !           245:   shift = 0;
        !           246:   if (value != 0) {
        !           247:     for (; (value & 1) == 0; value >>= 1, shift++);
        !           248:   }
        !           249:   return (shift);
        !           250: }
        !           251: 
        !           252: /* this returns the value with any first set bit in the value shifted
        !           253:    down into the first byte.  only whole bytes of zero bits are
        !           254:    shifted off.  this is slow, but it's only meant to be used at
        !           255:    initialization time: */
        !           256: static tme_recode_uguest_t
        !           257: _tme_recode_x86_ffs_byte_shift(tme_recode_uguest_t value)
        !           258: {
        !           259:   return (value
        !           260:          >> (_tme_recode_x86_ffs(value)
        !           261:              & (0 - (unsigned int) 8)));
        !           262: }
        !           263: 
        !           264: /* this starts more instructions: */
        !           265: #define tme_recode_x86_insns_start(ic, thunk_bytes)                    \
        !           266:   do {                                                                 \
        !           267:     thunk_bytes = (ic)->tme_recode_ic_thunk_build_next;                        \
        !           268:   } while (/* CONSTCOND */ 0)
        !           269: 
        !           270: /* this finishes instructions: */
        !           271: #define tme_recode_x86_insns_finish(ic, thunk_bytes)                   \
        !           272:   do {                                                                 \
        !           273:     assert (thunk_bytes <= (ic)->tme_recode_ic_thunk_build_end);       \
        !           274:     (ic)->tme_recode_ic_thunk_build_next = thunk_bytes;                        \
        !           275:   } while (/* CONSTCOND */ 0)
        !           276: 
        !           277: /* this emits an instruction to adjust the stack pointer: */
        !           278: static inline tme_uint8_t *
        !           279: _tme_recode_x86_emit_adjust_sp(tme_uint8_t *thunk_bytes, int adjust)
        !           280: {
        !           281: 
        !           282:   /* emit the add $imm, %sp: */
        !           283:   assert (adjust <= 127 && adjust >= -128);
        !           284:   if (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32) {
        !           285:     thunk_bytes[0] = TME_RECODE_X86_REX_B(TME_RECODE_SIZE_HOST, TME_RECODE_X86_REG_SP);
        !           286:   }
        !           287:   *((tme_uint16_t *) (thunk_bytes + (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32)))
        !           288:     = (TME_RECODE_X86_OPCODE_GRP1_Ib_Ev
        !           289:        + (TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(TME_RECODE_X86_REG_SP),
        !           290:                                      TME_RECODE_X86_OPCODE_GRP1_BINOP(TME_RECODE_X86_OPCODE_BINOP_ADD))
        !           291:          << 8));
        !           292:   thunk_bytes[(TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32) + 2] = (tme_int8_t) adjust;
        !           293:   thunk_bytes += (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32) + 3;
        !           294:   return (thunk_bytes);
        !           295: }
        !           296: 
        !           297: /* this gives the raw bytes for a binop instruction from one register into another: */
        !           298: #define _tme_recode_x86_raw_reg_binop(binop, reg_x86_src, reg_x86_dst)         \
        !           299:   ((TME_RECODE_X86_REX_B(TME_RECODE_SIZE_HOST, reg_x86_dst)                    \
        !           300:     | TME_RECODE_X86_REX_R(TME_RECODE_SIZE_HOST, reg_x86_src))                 \
        !           301:    + (((binop)                                                                 \
        !           302:        + TME_RECODE_X86_OPCODE_BINOP_Gv_Ev)                                    \
        !           303:       << (8 * (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32)))                    \
        !           304:    + (TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(reg_x86_dst),      \
        !           305:                                  TME_RECODE_X86_REG(reg_x86_src))              \
        !           306:       << (8 + 8 * (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32))))
        !           307: 
        !           308: /* this emits an instruction that copies one register into another: */
        !           309: #define _tme_recode_x86_emit_reg_copy(thunk_bytes, reg_x86_src, reg_x86_dst)           \
        !           310:   _tme_recode_x86_emit_reg_binop(thunk_bytes, TME_RECODE_X86_OPCODE_BINOP_MOV, reg_x86_src, reg_x86_dst)
        !           311: 
        !           312: /* this emits a binop instruction from one register into another: */
        !           313: #define _tme_recode_x86_emit_reg_binop(thunk_bytes, binop, reg_x86_src, reg_x86_dst)   \
        !           314:   do {                                                                                 \
        !           315:     if (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32) {                                   \
        !           316:       *((tme_uint32_t *) (thunk_bytes))                                                        \
        !           317:         = _tme_recode_x86_raw_reg_binop(binop, reg_x86_src, reg_x86_dst);              \
        !           318:       (thunk_bytes) += 3;                                                              \
        !           319:     }                                                                                  \
        !           320:     else {                                                                             \
        !           321:       *((tme_uint16_t *) (thunk_bytes))                                                        \
        !           322:         = (tme_uint16_t) _tme_recode_x86_raw_reg_binop(binop, reg_x86_src, reg_x86_dst);\
        !           323:       (thunk_bytes) += 2;                                                              \
        !           324:     }                                                                                  \
        !           325:   } while (/* CONSTCOND */ 0)
        !           326: 
        !           327: /* this emits an instruction that pushes or pops a register: */
        !           328: #define __tme_recode_x86_emit_reg_push_pop(thunk_bytes, reg_x86, opcode)               \
        !           329:   do {                                                                                 \
        !           330:     if (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32                                      \
        !           331:        && (reg_x86) >= TME_RECODE_X86_REG_N(8)) {                                      \
        !           332:       *((tme_uint16_t *) (thunk_bytes))                                                        \
        !           333:        = (TME_RECODE_X86_REX_B(0, TME_RECODE_X86_REG_N(8))                             \
        !           334:           + ((opcode)                                                                  \
        !           335:              << 8));                                                                   \
        !           336:       (thunk_bytes) += 2;                                                              \
        !           337:     }                                                                                  \
        !           338:     else {                                                                             \
        !           339:       *(thunk_bytes) = (opcode);                                                       \
        !           340:       (thunk_bytes) += 1;                                                              \
        !           341:     }                                                                                  \
        !           342:   } while (/* CONSTCOND */ 0)
        !           343: 
        !           344: /* this emits an instruction that pushes a register: */
        !           345: #define _tme_recode_x86_emit_reg_push(thunk_bytes, reg_x86)                            \
        !           346:   __tme_recode_x86_emit_reg_push_pop(thunk_bytes, reg_x86, TME_RECODE_X86_OPCODE_PUSH_Gv(reg_x86))
        !           347: 
        !           348: /* this emits an instruction that pops a register: */
        !           349: #define _tme_recode_x86_emit_reg_pop(thunk_bytes, reg_x86)                             \
        !           350:   __tme_recode_x86_emit_reg_push_pop(thunk_bytes, reg_x86, TME_RECODE_X86_OPCODE_POP_Gv(reg_x86))
        !           351: 
        !           352: /* this emits a ModR/M byte with a constant displacement to reference
        !           353:    a struct tme_ic *: */
        !           354: static inline tme_uint8_t *
        !           355: _tme_recode_x86_emit_ic_modrm(tme_uint8_t *thunk_bytes,
        !           356:                              unsigned long disp,
        !           357:                              tme_uint8_t opreg)
        !           358: {
        !           359:   unsigned int disp_size;
        !           360:   tme_uint8_t mod_rm;
        !           361: 
        !           362:   /* on x86-64 the displacement must fit into 31 bits, because it's
        !           363:      sign-extended: */
        !           364:   assert (TME_RECODE_SIZE_HOST == TME_RECODE_SIZE_32
        !           365:          || disp <= 0x7fffffff);
        !           366: 
        !           367:   /* assume that this must be a 32-bit displacement: */
        !           368:   *((tme_uint32_t *) (thunk_bytes + 1)) = disp;
        !           369:   disp_size = sizeof(tme_uint32_t);
        !           370:   mod_rm = TME_RECODE_X86_MOD_RM_EA_DISP32(TME_RECODE_X86_REG_IC);
        !           371: 
        !           372:   /* if this can be an eight-bit displacement, adjust the displacement
        !           373:      size and ModR/M byte: */
        !           374:   if (disp < 0x80) {
        !           375:     disp_size = sizeof(tme_uint8_t);
        !           376:   }
        !           377:   if (disp < 0x80) {
        !           378:     mod_rm = TME_RECODE_X86_MOD_RM_EA_DISP8(TME_RECODE_X86_REG_IC);
        !           379:   }
        !           380: 
        !           381:   /* write the ModR/M byte and return the end of the instruction: */
        !           382:   thunk_bytes[0] = TME_RECODE_X86_MOD_OPREG_RM(mod_rm, TME_RECODE_X86_REG(opreg));
        !           383:   return (thunk_bytes + 1 + disp_size);
        !           384: }
        !           385: 
        !           386: /* this emits a call or a jmp to a C function: */
        !           387: static void
        !           388: _tme_recode_x86_emit_transfer_func(struct tme_recode_ic *ic,
        !           389:                                   unsigned int opcode_relz,
        !           390:                                   void (*func) _TME_P((void)))
        !           391: {
        !           392:   tme_uint8_t *thunk_bytes;
        !           393:   tme_recode_thunk_off_t thunk_off;
        !           394:   tme_int32_t relv;
        !           395: 
        !           396:   /* start more instructions: */
        !           397:   tme_recode_x86_insns_start(ic, thunk_bytes);
        !           398: 
        !           399:   /* assume that we can emit a relative call or jmp, and get the
        !           400:      relative offset to the C function: */
        !           401:   thunk_bytes += 1 + sizeof(tme_int32_t);
        !           402:   thunk_off = tme_recode_build_to_thunk_off(ic, thunk_bytes);
        !           403:   relv = tme_recode_function_to_thunk_off(ic, func) - thunk_off;
        !           404: 
        !           405:   /* if this relative offset will reach the C function: */
        !           406:   if (tme_recode_thunk_off_to_pointer(ic,
        !           407:                                      (thunk_off + relv),
        !           408:                                      void (*) _TME_P((void)))
        !           409:       == func) {
        !           410: 
        !           411:     /* emit the relative call or jmp: */
        !           412:     thunk_bytes[-(1 + sizeof(tme_int32_t))] = opcode_relz;
        !           413:     ((tme_int32_t *) thunk_bytes)[-1] = relv;
        !           414:   }
        !           415: 
        !           416:   /* otherwise, we have to do an indirect call or jmp: */
        !           417:   else {
        !           418: 
        !           419:     /* we must be on an x86-64 host: */
        !           420:     assert (TME_RECODE_SIZE_HOST > TME_RECODE_SIZE_32);
        !           421: 
        !           422:     /* abort the relative call or jmp: */
        !           423:     thunk_bytes -= 1 + sizeof(tme_int32_t);
        !           424: 
        !           425:     /* load the a register with the address of the C function: */
        !           426:     thunk_bytes[0] = TME_RECODE_X86_REX_B(TME_RECODE_SIZE_HOST, TME_RECODE_X86_REG_A);
        !           427:     thunk_bytes[1] = TME_RECODE_X86_OPCODE_MOV_Iv_Gv(TME_RECODE_X86_REG_A);
        !           428:     memset(&thunk_bytes[2], 0, TME_BIT(TME_RECODE_SIZE_HOST - TME_RECODE_SIZE_8));
        !           429:     memcpy(&thunk_bytes[2], &func, sizeof(func));
        !           430:     thunk_bytes += 2 + TME_BIT(TME_RECODE_SIZE_HOST - TME_RECODE_SIZE_8);
        !           431: 
        !           432:     /* emit the indirect call or jmp: */
        !           433:     thunk_bytes[0] = TME_RECODE_X86_OPCODE_GRP5;
        !           434:     thunk_bytes[1]
        !           435:       = TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(TME_RECODE_X86_REG_A),
        !           436:                                    (opcode_relz == TME_RECODE_X86_OPCODE_CALL_RELz
        !           437:                                     ? TME_RECODE_X86_OPCODE_GRP5_CALL
        !           438:                                     : TME_RECODE_X86_OPCODE_GRP5_JMP));
        !           439:     thunk_bytes += 2;
        !           440:   }
        !           441: 
        !           442:   /* finish these instructions: */
        !           443:   tme_recode_x86_insns_finish(ic, thunk_bytes);
        !           444: }
        !           445: 
        !           446: /* this emits a multiplication by a constant: */
        !           447: /* NB: since this only does shifts and adds, this shouldn't be used
        !           448:    for large factors: */
        !           449: static tme_uint8_t *
        !           450: _tme_recode_x86_emit_mul_constant(tme_uint8_t *thunk_bytes,
        !           451:                                  unsigned int reg_size,
        !           452:                                  unsigned int reg_x86_factor,
        !           453:                                  tme_recode_uguest_t constant_factor,
        !           454:                                  unsigned int reg_x86_scratch)
        !           455: {
        !           456:   unsigned int shift_count;
        !           457:   unsigned int rex;
        !           458:   unsigned int scale_factor;
        !           459:   int need_pop;
        !           460: 
        !           461:   assert (constant_factor > 0);
        !           462: 
        !           463:   /* if the constant has any two factors in it: */
        !           464:   shift_count = _tme_recode_x86_ffs(constant_factor);
        !           465:   if (shift_count > 0) {
        !           466: 
        !           467:     /* multiply by the constant with the two factors removed: */
        !           468:     thunk_bytes = _tme_recode_x86_emit_mul_constant(thunk_bytes,
        !           469:                                                    reg_size,
        !           470:                                                    reg_x86_factor,
        !           471:                                                    constant_factor >> shift_count,
        !           472:                                                    reg_x86_scratch);
        !           473: 
        !           474:     /* emit a shift for the two factors: */
        !           475:     rex = TME_RECODE_X86_REX_B(reg_size, reg_x86_factor);
        !           476:     if (rex != 0) {
        !           477:       *(thunk_bytes++) = rex;
        !           478:     }
        !           479:     thunk_bytes[0] = TME_RECODE_X86_OPCODE_GRP2_Ib_Ev;
        !           480:     thunk_bytes[1]
        !           481:       = TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(reg_x86_factor),
        !           482:                                    TME_RECODE_X86_OPCODE_GRP2_SHL);
        !           483:     thunk_bytes[2] = shift_count;
        !           484:     thunk_bytes += 3;
        !           485: 
        !           486:     /* done: */
        !           487:     return (thunk_bytes);
        !           488:   }
        !           489: 
        !           490:   /* handle all of the nine, five, and three factors: */
        !           491:   scale_factor = 8;
        !           492:   for (; scale_factor > 1; ) {
        !           493: 
        !           494:     /* if this constant doesn't have any more of this factor: */
        !           495:     if ((constant_factor % (1 + scale_factor)) != 0) {
        !           496: 
        !           497:       /* advance to the next factor: */
        !           498:       scale_factor /= 2;
        !           499:       continue;
        !           500:     }
        !           501: 
        !           502:     /* emit an lea to multiply by this factor: */
        !           503:     rex
        !           504:       = (TME_RECODE_X86_REX_W(reg_size)
        !           505:         | TME_RECODE_X86_REX_R(reg_size, reg_x86_factor)
        !           506:         | TME_RECODE_X86_REX_X(reg_x86_factor)
        !           507:         | TME_RECODE_X86_REX_B(reg_size, reg_x86_factor));
        !           508:     if (rex != 0) {
        !           509:       *(thunk_bytes++) = rex;
        !           510:     }
        !           511:     thunk_bytes[0] = TME_RECODE_X86_OPCODE_LEA;
        !           512:     thunk_bytes[1] = TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_EA(TME_RECODE_X86_EA_BASE_SIB),
        !           513:                                                 TME_RECODE_X86_REG(reg_x86_factor));
        !           514:     thunk_bytes[2] = TME_RECODE_X86_SIB(reg_x86_factor, reg_x86_factor, scale_factor);
        !           515:     thunk_bytes += 3;
        !           516:     constant_factor /= (1 + scale_factor);
        !           517:   }
        !           518: 
        !           519:   /* if we still have a constant: */
        !           520:   if (constant_factor > 1) {
        !           521: 
        !           522:     /* if we need to, push the scratch register: */
        !           523:     need_pop = (reg_x86_scratch > TME_RECODE_X86_REG_UNDEF);
        !           524:     if (need_pop) {
        !           525:       reg_x86_scratch -= TME_RECODE_X86_REG_UNDEF;
        !           526:       _tme_recode_x86_emit_reg_push(thunk_bytes, reg_x86_scratch);
        !           527:     }
        !           528: 
        !           529:     /* copy the register into the scratch register: */
        !           530:     rex
        !           531:       = (TME_RECODE_X86_REX_B(reg_size, reg_x86_factor)
        !           532:         | TME_RECODE_X86_REX_R(reg_size, reg_x86_scratch));
        !           533:     if (rex != 0) {
        !           534:       *(thunk_bytes++) = rex;
        !           535:     }
        !           536:     thunk_bytes[0] = (TME_RECODE_X86_OPCODE_BINOP_MOV + TME_RECODE_X86_OPCODE_BINOP_Ev_Gv);
        !           537:     thunk_bytes[1]
        !           538:       = TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(reg_x86_factor),
        !           539:                                    reg_x86_scratch);
        !           540:     thunk_bytes += 2;
        !           541: 
        !           542:     /* if the constant ends in 11 binary, we will multiply by the
        !           543:        constant plus one and then subtract one, otherwise we will
        !           544:        multiply by the constant minus one and add one: */
        !           545:     thunk_bytes
        !           546:       = _tme_recode_x86_emit_mul_constant(thunk_bytes,
        !           547:                                          reg_size,
        !           548:                                          reg_x86_factor,
        !           549:                                          (constant_factor
        !           550:                                           + (constant_factor & 2)
        !           551:                                           - 1),
        !           552:                                          (TME_RECODE_X86_REG_UNDEF
        !           553:                                           + reg_x86_scratch));
        !           554:     rex
        !           555:       = (TME_RECODE_X86_REX_B(reg_size, reg_x86_scratch)
        !           556:         | TME_RECODE_X86_REX_R(reg_size, reg_x86_factor));
        !           557:     if (rex != 0) {
        !           558:       *(thunk_bytes++) = rex;
        !           559:     }
        !           560:     thunk_bytes[0]
        !           561:       = (TME_RECODE_X86_OPCODE_BINOP_Ev_Gv
        !           562:         + ((constant_factor & 2)
        !           563:            ? TME_RECODE_X86_OPCODE_BINOP_SUB
        !           564:            : TME_RECODE_X86_OPCODE_BINOP_ADD));
        !           565:     thunk_bytes[1]
        !           566:       = TME_RECODE_X86_MOD_OPREG_RM(TME_RECODE_X86_MOD_RM_REG(reg_x86_scratch),
        !           567:                                    reg_x86_factor);
        !           568:     thunk_bytes += 2;
        !           569: 
        !           570:     /* if we need to, pop the scratch register: */
        !           571:     if (need_pop) {
        !           572:       _tme_recode_x86_emit_reg_pop(thunk_bytes, reg_x86_scratch);
        !           573:     }
        !           574:   }
        !           575: 
        !           576:   /* done: */
        !           577:   return (thunk_bytes);
        !           578: }
        !           579: 
        !           580: /* this emits a jmp or jcc: */
        !           581: static tme_uint8_t *
        !           582: _tme_recode_x86_emit_jmp(tme_uint8_t *thunk_bytes,
        !           583:                         tme_uint32_t opcode,
        !           584:                         const tme_uint8_t *thunk_bytes_target)
        !           585: {
        !           586:   int one_if_opcode0f_jcc;
        !           587:   signed long disp;
        !           588: 
        !           589:   /* write the opcode: */
        !           590:   *((tme_uint16_t *) thunk_bytes) = opcode;
        !           591:   
        !           592:   /* see if this is a six-byte jcc instruction: */
        !           593:   one_if_opcode0f_jcc = ((opcode & 0xff) == TME_RECODE_X86_OPCODE_ESC_0F);
        !           594: 
        !           595:   /* the opcode must be for a jmp or jcc instruction: */
        !           596:   assert (opcode == TME_RECODE_X86_OPCODE_JMP_RELb
        !           597:          || opcode == TME_RECODE_X86_OPCODE_JMP_RELz
        !           598:          || (opcode & 0xf0) == TME_RECODE_X86_OPCODE_JCC(0)
        !           599:          || (one_if_opcode0f_jcc
        !           600:              && (opcode >> 12) == (TME_RECODE_X86_OPCODE0F_JCC(0) >> 4)));
        !           601: 
        !           602:   /* if we know the jump target now: */
        !           603:   if (thunk_bytes_target != NULL) {
        !           604: 
        !           605:     /* if the displacement can be a sign-extended eight bits: */
        !           606:     disp = thunk_bytes_target - (thunk_bytes + 2);
        !           607:     if (disp == (tme_int8_t) disp) {
        !           608: 
        !           609:       /* write the displacement: */
        !           610:       thunk_bytes[1] = disp;
        !           611: 
        !           612:       /* if the given opcode uses a 32-bit displacement, convert it to
        !           613:         one the uses an 8-bit displacement: */
        !           614:       if (opcode == TME_RECODE_X86_OPCODE_JMP_RELz) {
        !           615:        opcode = TME_RECODE_X86_OPCODE_JMP_RELb;
        !           616:       }
        !           617:       else if (one_if_opcode0f_jcc) {
        !           618:        opcode
        !           619:          = TME_RECODE_X86_OPCODE_JCC((opcode >> 8)
        !           620:                                      - TME_RECODE_X86_OPCODE0F_JCC(0));
        !           621:       }
        !           622:       one_if_opcode0f_jcc = 0;
        !           623: 
        !           624:       /* rewrite the possibly changed opcode: */
        !           625:       thunk_bytes[0] = opcode;
        !           626:     }
        !           627: 
        !           628:     /* otherwise, the displacement can't be a sign-extended eight bits: */
        !           629:     else {
        !           630: 
        !           631:       /* the opcode must use a 32-bit displacement: */
        !           632:       assert (opcode == TME_RECODE_X86_OPCODE_JMP_RELz
        !           633:              || one_if_opcode0f_jcc);
        !           634: 
        !           635:       /* the displacement must fit in a sign-extended 32 bits: */
        !           636:       disp = (thunk_bytes_target
        !           637:              - (thunk_bytes
        !           638:                 + 1
        !           639:                 + one_if_opcode0f_jcc
        !           640:                 + sizeof(tme_int32_t)));
        !           641:       assert (disp == (tme_int32_t) disp);
        !           642: 
        !           643:       /* write the displacement: */
        !           644:       *((tme_int32_t *) &thunk_bytes[1 + one_if_opcode0f_jcc]) = disp;
        !           645:     }
        !           646:   }
        !           647: 
        !           648:   /* advance: */
        !           649:   thunk_bytes += 1 + one_if_opcode0f_jcc + 1;
        !           650:   if (opcode == TME_RECODE_X86_OPCODE_JMP_RELz
        !           651:       || one_if_opcode0f_jcc) {
        !           652:     thunk_bytes += sizeof(tme_uint32_t) - 1;
        !           653:   }
        !           654: 
        !           655:   return (thunk_bytes);
        !           656: }
        !           657: 
        !           658: /* this fixes up a jmp or jcc: */
        !           659: static void
        !           660: _tme_recode_x86_fixup_jmp(tme_uint8_t *thunk_bytes,
        !           661:                          const tme_uint8_t *thunk_bytes_target)
        !           662: {
        !           663:   tme_uint8_t opcode;
        !           664:   int one_if_opcode0f_jcc;
        !           665:   signed long disp;
        !           666: 
        !           667:   /* get the first byte of the opcode: */
        !           668:   opcode = thunk_bytes[0];
        !           669: 
        !           670:   /* see if this is a six-byte jcc instruction: */
        !           671:   one_if_opcode0f_jcc = (opcode == TME_RECODE_X86_OPCODE_ESC_0F);
        !           672: 
        !           673:   /* if the opcode uses a 32-bit displacement: */
        !           674:   if (opcode == TME_RECODE_X86_OPCODE_JMP_RELz
        !           675:       || one_if_opcode0f_jcc) {
        !           676: 
        !           677:     /* the displacement must fit in a sign-extended 32 bits: */
        !           678:     disp = (thunk_bytes_target
        !           679:            - (thunk_bytes
        !           680:               + 1
        !           681:               + one_if_opcode0f_jcc
        !           682:               + sizeof(tme_int32_t)));
        !           683:     assert (disp == (tme_int32_t) disp);
        !           684: 
        !           685:     /* write the displacement: */
        !           686:     *((tme_int32_t *) &thunk_bytes[1 + one_if_opcode0f_jcc]) = disp;
        !           687:   }
        !           688: 
        !           689:   /* otherwise, the opcode uses an 8-bit displacement: */
        !           690:   else {
        !           691: 
        !           692:     /* the displacement must fit in a sign-extended eight bits: */
        !           693:     disp = thunk_bytes_target - (thunk_bytes + 2);
        !           694:     assert (disp == (tme_int8_t) disp);
        !           695: 
        !           696:     /* write the displacement: */
        !           697:     thunk_bytes[1] = disp;
        !           698:   }
        !           699: }
        !           700: 
        !           701: /* prototypes: */
        !           702: 
        !           703: /* this emits instructions for a chain in: */
        !           704: static void _tme_recode_x86_chain_in _TME_P((struct tme_recode_ic *, const struct tme_recode_insns_group *));
        !           705: 
        !           706: /* this emits instructions for a chain out: */
        !           707: static void _tme_recode_x86_chain_out _TME_P((struct tme_recode_ic *, const struct tme_recode_insns_group *));
        !           708: 
        !           709: /* include the other code files: */
        !           710: #include "host/x86/rc-x86-subs.c"
        !           711: #include "host/x86/rc-x86-regs.c"
        !           712: #include "host/x86/rc-x86-conds.c"
        !           713: #include "host/x86/rc-x86-insns.c"
        !           714: #include "host/x86/rc-x86-flags.c"
        !           715: #include "host/x86/rc-x86-tlb.c"
        !           716: #include "host/x86/rc-x86-rws.c"
        !           717: #include "host/x86/rc-x86-chain.c"
        !           718: 
        !           719: /* this host function starts a new IC: */
        !           720: void
        !           721: tme_recode_host_ic_new(struct tme_recode_ic *ic)
        !           722: {
        !           723:   tme_uint8_t *thunk_bytes;
        !           724:   tme_recode_thunk_off_t thunk_off;
        !           725: 
        !           726:   /* make the chain epilogue: */
        !           727:   _tme_recode_x86_chain_epilogue(ic);
        !           728: 
        !           729:   /* copy the hand-coded subs: */
        !           730:   tme_recode_x86_insns_start(ic, thunk_bytes);
        !           731:   thunk_off = tme_recode_build_to_thunk_off(ic, thunk_bytes);
        !           732:   memcpy(thunk_bytes, _tme_recode_x86_subs, sizeof(_tme_recode_x86_subs));
        !           733:   thunk_bytes += sizeof(_tme_recode_x86_subs);
        !           734:   tme_recode_x86_insns_finish(ic, thunk_bytes);
        !           735:   tme_recode_host_thunk_finish(ic);
        !           736: 
        !           737:   /* set the thunk offsets of the shift insn subs: */
        !           738: #if (TME_RECODE_OPCODE_SHLL + 1) != TME_RECODE_OPCODE_SHRL || (TME_RECODE_OPCODE_SHRL + 1) != TME_RECODE_OPCODE_SHRA
        !           739: #error "TME_RECODE_OPCODE_ values changed"
        !           740: #endif
        !           741: #define _tme_recode_x86_set_subs_shift(size, opcode, subs)             \
        !           742:   ic->tme_recode_x86_ic_subs_shift                                     \
        !           743:     [_TME_CONCAT(TME_RECODE_SIZE_,size) - TME_RECODE_SIZE_8]           \
        !           744:     [_TME_CONCAT(TME_RECODE_OPCODE_,opcode) - TME_RECODE_OPCODE_SHLL]  \
        !           745:     = (thunk_off + _TME_CONCAT3(tme_recode_x86_,subs,size))
        !           746:   _tme_recode_x86_set_subs_shift(8, SHLL, shll);
        !           747:   _tme_recode_x86_set_subs_shift(8, SHRL, shrl);
        !           748:   _tme_recode_x86_set_subs_shift(8, SHRA, shra);
        !           749:   _tme_recode_x86_set_subs_shift(16, SHLL, shll);
        !           750:   _tme_recode_x86_set_subs_shift(16, SHRL, shrl);
        !           751:   _tme_recode_x86_set_subs_shift(16, SHRA, shra);
        !           752:   _tme_recode_x86_set_subs_shift(32, SHLL, shll);
        !           753:   _tme_recode_x86_set_subs_shift(32, SHRL, shrl);
        !           754:   _tme_recode_x86_set_subs_shift(32, SHRA, shra);
        !           755: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32
        !           756:   _tme_recode_x86_set_subs_shift(64, SHLL, shll);
        !           757:   _tme_recode_x86_set_subs_shift(64, SHRL, shrl);
        !           758:   _tme_recode_x86_set_subs_shift(64, SHRA, shra);
        !           759: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */
        !           760: #if TME_RECODE_SIZE_GUEST_MAX > (TME_RECODE_SIZE_32 + 1)
        !           761:   _tme_recode_x86_set_subs_shift(128, SHLL, shll);
        !           762:   _tme_recode_x86_set_subs_shift(128, SHRL, shrl);
        !           763:   _tme_recode_x86_set_subs_shift(128, SHRA, shra);
        !           764: #endif /* TME_RECODE_SIZE_GUEST_MAX > (TME_RECODE_SIZE_32 + 1) */
        !           765: #undef _tme_recode_x86_set_subs_shift
        !           766: 
        !           767:   /* check the value of TME_RECODE_HOST_INSN_SIZE_MAX: */
        !           768:   _tme_recode_x86_insn_size_max_check();
        !           769: }
        !           770: 
        !           771: #endif /* TME_HAVE_RECODE */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.