Annotation of embedaddon/pcre/sljit/sljitNativeX86_common.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:  *    Stack-less Just-In-Time compiler
                      3:  *
1.1.1.2   misho       4:  *    Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
1.1       misho       5:  *
                      6:  * Redistribution and use in source and binary forms, with or without modification, are
                      7:  * permitted provided that the following conditions are met:
                      8:  *
                      9:  *   1. Redistributions of source code must retain the above copyright notice, this list of
                     10:  *      conditions and the following disclaimer.
                     11:  *
                     12:  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
                     13:  *      of conditions and the following disclaimer in the documentation and/or other materials
                     14:  *      provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
                     17:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
                     19:  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
                     21:  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
                     22:  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     23:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     24:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26: 
1.1.1.4 ! misho      27: SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
1.1       misho      28: {
1.1.1.2   misho      29:        return "x86" SLJIT_CPUINFO;
1.1       misho      30: }
                     31: 
                     32: /*
                     33:    32b register indexes:
                     34:      0 - EAX
                     35:      1 - ECX
                     36:      2 - EDX
                     37:      3 - EBX
                     38:      4 - none
                     39:      5 - EBP
                     40:      6 - ESI
                     41:      7 - EDI
                     42: */
                     43: 
                     44: /*
                     45:    64b register indexes:
                     46:      0 - RAX
                     47:      1 - RCX
                     48:      2 - RDX
                     49:      3 - RBX
                     50:      4 - none
                     51:      5 - RBP
                     52:      6 - RSI
                     53:      7 - RDI
                     54:      8 - R8   - From now on REX prefix is required
                     55:      9 - R9
                     56:     10 - R10
                     57:     11 - R11
                     58:     12 - R12
                     59:     13 - R13
                     60:     14 - R14
                     61:     15 - R15
                     62: */
                     63: 
                     64: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                     65: 
                     66: /* Last register + 1. */
                     67: #define TMP_REGISTER   (SLJIT_NO_REGISTERS + 1)
                     68: 
                     69: static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = {
1.1.1.4 ! misho      70:        0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
1.1       misho      71: };
                     72: 
                     73: #define CHECK_EXTRA_REGS(p, w, do) \
                     74:        if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \
1.1.1.4 ! misho      75:                w = compiler->scratches_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_sw); \
1.1       misho      76:                p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
                     77:                do; \
                     78:        } \
1.1.1.2   misho      79:        else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
1.1.1.4 ! misho      80:                w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_sw); \
1.1       misho      81:                p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
                     82:                do; \
                     83:        }
                     84: 
                     85: #else /* SLJIT_CONFIG_X86_32 */
                     86: 
                     87: /* Last register + 1. */
                     88: #define TMP_REGISTER   (SLJIT_NO_REGISTERS + 1)
                     89: #define TMP_REG2       (SLJIT_NO_REGISTERS + 2)
                     90: #define TMP_REG3       (SLJIT_NO_REGISTERS + 3)
                     91: 
                     92: /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
                     93:    Note: avoid to use r12 and r13 for memory addessing
1.1.1.2   misho      94:    therefore r12 is better for SAVED_EREG than SAVED_REG. */
1.1       misho      95: #ifndef _WIN64
                     96: /* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
                     97: static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
1.1.1.4 ! misho      98:        0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
1.1       misho      99: };
                    100: /* low-map. reg_map & 0x7. */
                    101: static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
1.1.1.4 ! misho     102:        0, 0, 6, 1, 0, 3,  3, 7,  6,  5,  4,  4, 2, 7, 1
1.1       misho     103: };
                    104: #else
                    105: /* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
                    106: static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
1.1.1.4 ! misho     107:        0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 15, 4, 10, 8, 9
1.1       misho     108: };
                    109: /* low-map. reg_map & 0x7. */
                    110: static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = {
1.1.1.4 ! misho     111:        0, 0, 2, 1, 3,  5,  3, 6, 7,  6,  7, 4, 2,  0, 1
1.1       misho     112: };
                    113: #endif
                    114: 
                    115: #define REX_W          0x48
                    116: #define REX_R          0x44
                    117: #define REX_X          0x42
                    118: #define REX_B          0x41
                    119: #define REX            0x40
                    120: 
                    121: #define IS_HALFWORD(x)         ((x) <= 0x7fffffffll && (x) >= -0x80000000ll)
                    122: #define NOT_HALFWORD(x)                ((x) > 0x7fffffffll || (x) < -0x80000000ll)
                    123: 
                    124: #define CHECK_EXTRA_REGS(p, w, do)
                    125: 
                    126: #endif /* SLJIT_CONFIG_X86_32 */
                    127: 
                    128: #if (defined SLJIT_SSE2 && SLJIT_SSE2)
1.1.1.4 ! misho     129: #define TMP_FREG       (0)
1.1       misho     130: #endif
                    131: 
                    132: /* Size flags for emit_x86_instruction: */
                    133: #define EX86_BIN_INS           0x0010
                    134: #define EX86_SHIFT_INS         0x0020
                    135: #define EX86_REX               0x0040
                    136: #define EX86_NO_REXW           0x0080
                    137: #define EX86_BYTE_ARG          0x0100
                    138: #define EX86_HALF_ARG          0x0200
                    139: #define EX86_PREF_66           0x0400
                    140: 
                    141: #if (defined SLJIT_SSE2 && SLJIT_SSE2)
1.1.1.4 ! misho     142: #define EX86_SSE2              0x0800
        !           143: #define EX86_PREF_F2           0x1000
        !           144: #define EX86_PREF_F3           0x2000
1.1       misho     145: #endif
                    146: 
1.1.1.4 ! misho     147: /* --------------------------------------------------------------------- */
        !           148: /*  Instrucion forms                                                     */
        !           149: /* --------------------------------------------------------------------- */
1.1       misho     150: 
1.1.1.4 ! misho     151: #define ADD            (/* BINARY */ 0 << 3)
        !           152: #define ADD_EAX_i32    0x05
        !           153: #define ADD_r_rm       0x03
        !           154: #define ADD_rm_r       0x01
        !           155: #define ADDSD_x_xm     0x58
        !           156: #define ADC            (/* BINARY */ 2 << 3)
        !           157: #define ADC_EAX_i32    0x15
        !           158: #define ADC_r_rm       0x13
        !           159: #define ADC_rm_r       0x11
        !           160: #define AND            (/* BINARY */ 4 << 3)
        !           161: #define AND_EAX_i32    0x25
        !           162: #define AND_r_rm       0x23
        !           163: #define AND_rm_r       0x21
        !           164: #define ANDPD_x_xm     0x54
        !           165: #define BSR_r_rm       (/* GROUP_0F */ 0xbd)
        !           166: #define CALL_i32       0xe8
        !           167: #define CALL_rm                (/* GROUP_FF */ 2 << 3)
        !           168: #define CDQ            0x99
        !           169: #define CMOVNE_r_rm    (/* GROUP_0F */ 0x45)
        !           170: #define CMP            (/* BINARY */ 7 << 3)
        !           171: #define CMP_EAX_i32    0x3d
        !           172: #define CMP_r_rm       0x3b
        !           173: #define CMP_rm_r       0x39
        !           174: #define DIV            (/* GROUP_F7 */ 6 << 3)
        !           175: #define DIVSD_x_xm     0x5e
        !           176: #define INT3           0xcc
        !           177: #define IDIV           (/* GROUP_F7 */ 7 << 3)
        !           178: #define IMUL           (/* GROUP_F7 */ 5 << 3)
        !           179: #define IMUL_r_rm      (/* GROUP_0F */ 0xaf)
        !           180: #define IMUL_r_rm_i8   0x6b
        !           181: #define IMUL_r_rm_i32  0x69
        !           182: #define JE_i8          0x74
        !           183: #define JMP_i8         0xeb
        !           184: #define JMP_i32                0xe9
        !           185: #define JMP_rm         (/* GROUP_FF */ 4 << 3)
        !           186: #define LEA_r_m                0x8d
        !           187: #define MOV_r_rm       0x8b
        !           188: #define MOV_r_i32      0xb8
        !           189: #define MOV_rm_r       0x89
        !           190: #define MOV_rm_i32     0xc7
        !           191: #define MOV_rm8_i8     0xc6
        !           192: #define MOV_rm8_r8     0x88
        !           193: #define MOVSD_x_xm     0x10
        !           194: #define MOVSD_xm_x     0x11
        !           195: #define MOVSXD_r_rm    0x63
        !           196: #define MOVSX_r_rm8    (/* GROUP_0F */ 0xbe)
        !           197: #define MOVSX_r_rm16   (/* GROUP_0F */ 0xbf)
        !           198: #define MOVZX_r_rm8    (/* GROUP_0F */ 0xb6)
        !           199: #define MOVZX_r_rm16   (/* GROUP_0F */ 0xb7)
        !           200: #define MUL            (/* GROUP_F7 */ 4 << 3)
        !           201: #define MULSD_x_xm     0x59
        !           202: #define NEG_rm         (/* GROUP_F7 */ 3 << 3)
        !           203: #define NOP            0x90
        !           204: #define NOT_rm         (/* GROUP_F7 */ 2 << 3)
        !           205: #define OR             (/* BINARY */ 1 << 3)
        !           206: #define OR_r_rm                0x0b
        !           207: #define OR_EAX_i32     0x0d
        !           208: #define OR_rm_r                0x09
        !           209: #define OR_rm8_r8      0x08
        !           210: #define POP_r          0x58
        !           211: #define POP_rm         0x8f
        !           212: #define POPF           0x9d
        !           213: #define PUSH_i32       0x68
        !           214: #define PUSH_r         0x50
        !           215: #define PUSH_rm                (/* GROUP_FF */ 6 << 3)
        !           216: #define PUSHF          0x9c
        !           217: #define RET_near       0xc3
        !           218: #define RET_i16                0xc2
        !           219: #define SBB            (/* BINARY */ 3 << 3)
        !           220: #define SBB_EAX_i32    0x1d
        !           221: #define SBB_r_rm       0x1b
        !           222: #define SBB_rm_r       0x19
        !           223: #define SAR            (/* SHIFT */ 7 << 3)
        !           224: #define SHL            (/* SHIFT */ 4 << 3)
        !           225: #define SHR            (/* SHIFT */ 5 << 3)
        !           226: #define SUB            (/* BINARY */ 5 << 3)
        !           227: #define SUB_EAX_i32    0x2d
        !           228: #define SUB_r_rm       0x2b
        !           229: #define SUB_rm_r       0x29
        !           230: #define SUBSD_x_xm     0x5c
        !           231: #define TEST_EAX_i32   0xa9
        !           232: #define TEST_rm_r      0x85
        !           233: #define UCOMISD_x_xm   0x2e
        !           234: #define XCHG_EAX_r     0x90
        !           235: #define XCHG_r_rm      0x87
        !           236: #define XOR            (/* BINARY */ 6 << 3)
        !           237: #define XOR_EAX_i32    0x35
        !           238: #define XOR_r_rm       0x33
        !           239: #define XOR_rm_r       0x31
        !           240: #define XORPD_x_xm     0x57
        !           241: 
        !           242: #define GROUP_0F       0x0f
        !           243: #define GROUP_F7       0xf7
        !           244: #define GROUP_FF       0xff
        !           245: #define GROUP_BINARY_81        0x81
        !           246: #define GROUP_BINARY_83        0x83
        !           247: #define GROUP_SHIFT_1  0xd1
        !           248: #define GROUP_SHIFT_N  0xc1
        !           249: #define GROUP_SHIFT_CL 0xd3
        !           250: 
        !           251: #define MOD_REG                0xc0
        !           252: #define MOD_DISP8      0x40
        !           253: 
        !           254: #define INC_SIZE(s)                    (*inst++ = (s), compiler->size += (s))
        !           255: 
        !           256: #define PUSH_REG(r)                    (*inst++ = (PUSH_r + (r)))
        !           257: #define POP_REG(r)                     (*inst++ = (POP_r + (r)))
        !           258: #define RET()                          (*inst++ = (RET_near))
        !           259: #define RET_I16(n)                     (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0)
1.1       misho     260: /* r32, r/m32 */
1.1.1.4 ! misho     261: #define MOV_RM(mod, reg, rm)           (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm))
        !           262: 
        !           263: /* Multithreading does not affect these static variables, since they store
        !           264:    built-in CPU features. Therefore they can be overwritten by different threads
        !           265:    if they detect the CPU features in the same time. */
        !           266: #if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
        !           267: static sljit_si cpu_has_sse2 = -1;
        !           268: #endif
        !           269: static sljit_si cpu_has_cmov = -1;
        !           270: 
        !           271: #if defined(_MSC_VER) && _MSC_VER >= 1400
        !           272: #include <intrin.h>
        !           273: #endif
        !           274: 
        !           275: static void get_cpu_features(void)
        !           276: {
        !           277:        sljit_ui features;
        !           278: 
        !           279: #if defined(_MSC_VER) && _MSC_VER >= 1400
        !           280: 
        !           281:        int CPUInfo[4];
        !           282:        __cpuid(CPUInfo, 1);
        !           283:        features = (sljit_ui)CPUInfo[3];
        !           284: 
        !           285: #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
        !           286: 
        !           287:        /* AT&T syntax. */
        !           288:        __asm__ (
        !           289:                "movl $0x1, %%eax\n"
        !           290: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
        !           291:                /* On x86-32, there is no red zone, so this
        !           292:                   should work (no need for a local variable). */
        !           293:                "push %%ebx\n"
        !           294: #endif
        !           295:                "cpuid\n"
        !           296: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
        !           297:                "pop %%ebx\n"
        !           298: #endif
        !           299:                "movl %%edx, %0\n"
        !           300:                : "=g" (features)
        !           301:                :
        !           302: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
        !           303:                : "%eax", "%ecx", "%edx"
        !           304: #else
        !           305:                : "%rax", "%rbx", "%rcx", "%rdx"
        !           306: #endif
        !           307:        );
        !           308: 
        !           309: #else /* _MSC_VER && _MSC_VER >= 1400 */
        !           310: 
        !           311:        /* Intel syntax. */
        !           312:        __asm {
        !           313:                mov eax, 1
        !           314:                cpuid
        !           315:                mov features, edx
        !           316:        }
1.1       misho     317: 
1.1.1.4 ! misho     318: #endif /* _MSC_VER && _MSC_VER >= 1400 */
        !           319: 
        !           320: #if (defined SLJIT_SSE2 && SLJIT_SSE2) && (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
        !           321:        cpu_has_sse2 = (features >> 26) & 0x1;
        !           322: #endif
        !           323:        cpu_has_cmov = (features >> 15) & 0x1;
        !           324: }
        !           325: 
        !           326: static sljit_ub get_jump_code(sljit_si type)
1.1       misho     327: {
                    328:        switch (type) {
                    329:        case SLJIT_C_EQUAL:
                    330:        case SLJIT_C_FLOAT_EQUAL:
1.1.1.4 ! misho     331:                return 0x84 /* je */;
1.1       misho     332: 
                    333:        case SLJIT_C_NOT_EQUAL:
                    334:        case SLJIT_C_FLOAT_NOT_EQUAL:
1.1.1.4 ! misho     335:                return 0x85 /* jne */;
1.1       misho     336: 
                    337:        case SLJIT_C_LESS:
                    338:        case SLJIT_C_FLOAT_LESS:
1.1.1.4 ! misho     339:                return 0x82 /* jc */;
1.1       misho     340: 
                    341:        case SLJIT_C_GREATER_EQUAL:
                    342:        case SLJIT_C_FLOAT_GREATER_EQUAL:
1.1.1.4 ! misho     343:                return 0x83 /* jae */;
1.1       misho     344: 
                    345:        case SLJIT_C_GREATER:
                    346:        case SLJIT_C_FLOAT_GREATER:
1.1.1.4 ! misho     347:                return 0x87 /* jnbe */;
1.1       misho     348: 
                    349:        case SLJIT_C_LESS_EQUAL:
                    350:        case SLJIT_C_FLOAT_LESS_EQUAL:
1.1.1.4 ! misho     351:                return 0x86 /* jbe */;
1.1       misho     352: 
                    353:        case SLJIT_C_SIG_LESS:
1.1.1.4 ! misho     354:                return 0x8c /* jl */;
1.1       misho     355: 
                    356:        case SLJIT_C_SIG_GREATER_EQUAL:
1.1.1.4 ! misho     357:                return 0x8d /* jnl */;
1.1       misho     358: 
                    359:        case SLJIT_C_SIG_GREATER:
1.1.1.4 ! misho     360:                return 0x8f /* jnle */;
1.1       misho     361: 
                    362:        case SLJIT_C_SIG_LESS_EQUAL:
1.1.1.4 ! misho     363:                return 0x8e /* jle */;
1.1       misho     364: 
                    365:        case SLJIT_C_OVERFLOW:
                    366:        case SLJIT_C_MUL_OVERFLOW:
1.1.1.4 ! misho     367:                return 0x80 /* jo */;
1.1       misho     368: 
                    369:        case SLJIT_C_NOT_OVERFLOW:
                    370:        case SLJIT_C_MUL_NOT_OVERFLOW:
1.1.1.4 ! misho     371:                return 0x81 /* jno */;
1.1       misho     372: 
1.1.1.4 ! misho     373:        case SLJIT_C_FLOAT_UNORDERED:
        !           374:                return 0x8a /* jp */;
1.1       misho     375: 
1.1.1.4 ! misho     376:        case SLJIT_C_FLOAT_ORDERED:
        !           377:                return 0x8b /* jpo */;
1.1       misho     378:        }
                    379:        return 0;
                    380: }
                    381: 
1.1.1.4 ! misho     382: static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type);
1.1       misho     383: 
                    384: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho     385: static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type);
1.1       misho     386: #endif
                    387: 
1.1.1.4 ! misho     388: static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, sljit_si type)
1.1       misho     389: {
1.1.1.4 ! misho     390:        sljit_si short_jump;
1.1       misho     391:        sljit_uw label_addr;
                    392: 
                    393:        if (jump->flags & JUMP_LABEL)
                    394:                label_addr = (sljit_uw)(code + jump->u.label->size);
                    395:        else
                    396:                label_addr = jump->u.target;
1.1.1.4 ! misho     397:        short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
1.1       misho     398: 
                    399: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho     400:        if ((sljit_sw)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_sw)(label_addr - (jump->addr + 1)) < -0x80000000ll)
1.1       misho     401:                return generate_far_jump_code(jump, code_ptr, type);
                    402: #endif
                    403: 
                    404:        if (type == SLJIT_JUMP) {
                    405:                if (short_jump)
1.1.1.4 ! misho     406:                        *code_ptr++ = JMP_i8;
1.1       misho     407:                else
1.1.1.4 ! misho     408:                        *code_ptr++ = JMP_i32;
1.1       misho     409:                jump->addr++;
                    410:        }
                    411:        else if (type >= SLJIT_FAST_CALL) {
                    412:                short_jump = 0;
1.1.1.4 ! misho     413:                *code_ptr++ = CALL_i32;
1.1       misho     414:                jump->addr++;
                    415:        }
                    416:        else if (short_jump) {
                    417:                *code_ptr++ = get_jump_code(type) - 0x10;
                    418:                jump->addr++;
                    419:        }
                    420:        else {
1.1.1.4 ! misho     421:                *code_ptr++ = GROUP_0F;
1.1       misho     422:                *code_ptr++ = get_jump_code(type);
                    423:                jump->addr += 2;
                    424:        }
                    425: 
                    426:        if (short_jump) {
                    427:                jump->flags |= PATCH_MB;
1.1.1.4 ! misho     428:                code_ptr += sizeof(sljit_sb);
1.1       misho     429:        } else {
                    430:                jump->flags |= PATCH_MW;
                    431: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     432:                code_ptr += sizeof(sljit_sw);
1.1       misho     433: #else
1.1.1.4 ! misho     434:                code_ptr += sizeof(sljit_si);
1.1       misho     435: #endif
                    436:        }
                    437: 
                    438:        return code_ptr;
                    439: }
                    440: 
                    441: SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
                    442: {
                    443:        struct sljit_memory_fragment *buf;
                    444:        sljit_ub *code;
                    445:        sljit_ub *code_ptr;
                    446:        sljit_ub *buf_ptr;
                    447:        sljit_ub *buf_end;
                    448:        sljit_ub len;
                    449: 
                    450:        struct sljit_label *label;
                    451:        struct sljit_jump *jump;
                    452:        struct sljit_const *const_;
                    453: 
                    454:        CHECK_ERROR_PTR();
                    455:        check_sljit_generate_code(compiler);
                    456:        reverse_buf(compiler);
                    457: 
                    458:        /* Second code generation pass. */
                    459:        code = (sljit_ub*)SLJIT_MALLOC_EXEC(compiler->size);
                    460:        PTR_FAIL_WITH_EXEC_IF(code);
                    461:        buf = compiler->buf;
                    462: 
                    463:        code_ptr = code;
                    464:        label = compiler->labels;
                    465:        jump = compiler->jumps;
                    466:        const_ = compiler->consts;
                    467:        do {
                    468:                buf_ptr = buf->memory;
                    469:                buf_end = buf_ptr + buf->used_size;
                    470:                do {
                    471:                        len = *buf_ptr++;
                    472:                        if (len > 0) {
                    473:                                /* The code is already generated. */
                    474:                                SLJIT_MEMMOVE(code_ptr, buf_ptr, len);
                    475:                                code_ptr += len;
                    476:                                buf_ptr += len;
                    477:                        }
                    478:                        else {
                    479:                                if (*buf_ptr >= 4) {
                    480:                                        jump->addr = (sljit_uw)code_ptr;
                    481:                                        if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
                    482:                                                code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 4);
                    483:                                        else
                    484:                                                code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 4);
                    485:                                        jump = jump->next;
                    486:                                }
                    487:                                else if (*buf_ptr == 0) {
                    488:                                        label->addr = (sljit_uw)code_ptr;
                    489:                                        label->size = code_ptr - code;
                    490:                                        label = label->next;
                    491:                                }
                    492:                                else if (*buf_ptr == 1) {
1.1.1.4 ! misho     493:                                        const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
1.1       misho     494:                                        const_ = const_->next;
                    495:                                }
                    496:                                else {
                    497: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     498:                                        *code_ptr++ = (*buf_ptr == 2) ? CALL_i32 : JMP_i32;
1.1       misho     499:                                        buf_ptr++;
1.1.1.4 ! misho     500:                                        *(sljit_sw*)code_ptr = *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw));
        !           501:                                        code_ptr += sizeof(sljit_sw);
        !           502:                                        buf_ptr += sizeof(sljit_sw) - 1;
1.1       misho     503: #else
1.1.1.4 ! misho     504:                                        code_ptr = generate_fixed_jump(code_ptr, *(sljit_sw*)(buf_ptr + 1), *buf_ptr);
        !           505:                                        buf_ptr += sizeof(sljit_sw);
1.1       misho     506: #endif
                    507:                                }
                    508:                                buf_ptr++;
                    509:                        }
                    510:                } while (buf_ptr < buf_end);
                    511:                SLJIT_ASSERT(buf_ptr == buf_end);
                    512:                buf = buf->next;
                    513:        } while (buf);
                    514: 
                    515:        SLJIT_ASSERT(!label);
                    516:        SLJIT_ASSERT(!jump);
                    517:        SLJIT_ASSERT(!const_);
                    518: 
                    519:        jump = compiler->jumps;
                    520:        while (jump) {
                    521:                if (jump->flags & PATCH_MB) {
1.1.1.4 ! misho     522:                        SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb))) <= 127);
        !           523:                        *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_sb)));
1.1       misho     524:                } else if (jump->flags & PATCH_MW) {
                    525:                        if (jump->flags & JUMP_LABEL) {
                    526: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     527:                                *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw)));
1.1       misho     528: #else
1.1.1.4 ! misho     529:                                SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
        !           530:                                *(sljit_si*)jump->addr = (sljit_si)(jump->u.label->addr - (jump->addr + sizeof(sljit_si)));
1.1       misho     531: #endif
                    532:                        }
                    533:                        else {
                    534: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     535:                                *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw)));
1.1       misho     536: #else
1.1.1.4 ! misho     537:                                SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) >= -0x80000000ll && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_si))) <= 0x7fffffffll);
        !           538:                                *(sljit_si*)jump->addr = (sljit_si)(jump->u.target - (jump->addr + sizeof(sljit_si)));
1.1       misho     539: #endif
                    540:                        }
                    541:                }
                    542: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                    543:                else if (jump->flags & PATCH_MD)
1.1.1.4 ! misho     544:                        *(sljit_sw*)jump->addr = jump->u.label->addr;
1.1       misho     545: #endif
                    546: 
                    547:                jump = jump->next;
                    548:        }
                    549: 
                    550:        /* Maybe we waste some space because of short jumps. */
                    551:        SLJIT_ASSERT(code_ptr <= code + compiler->size);
                    552:        compiler->error = SLJIT_ERR_COMPILED;
1.1.1.4 ! misho     553:        compiler->executable_size = code_ptr - code;
1.1       misho     554:        return (void*)code;
                    555: }
                    556: 
                    557: /* --------------------------------------------------------------------- */
                    558: /*  Operators                                                            */
                    559: /* --------------------------------------------------------------------- */
                    560: 
1.1.1.4 ! misho     561: static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
1.1       misho     562:        sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
1.1.1.4 ! misho     563:        sljit_si dst, sljit_sw dstw,
        !           564:        sljit_si src1, sljit_sw src1w,
        !           565:        sljit_si src2, sljit_sw src2w);
1.1       misho     566: 
1.1.1.4 ! misho     567: static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
1.1       misho     568:        sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
1.1.1.4 ! misho     569:        sljit_si dst, sljit_sw dstw,
        !           570:        sljit_si src1, sljit_sw src1w,
        !           571:        sljit_si src2, sljit_sw src2w);
1.1       misho     572: 
1.1.1.4 ! misho     573: static sljit_si emit_mov(struct sljit_compiler *compiler,
        !           574:        sljit_si dst, sljit_sw dstw,
        !           575:        sljit_si src, sljit_sw srcw);
1.1       misho     576: 
1.1.1.4 ! misho     577: static SLJIT_INLINE sljit_si emit_save_flags(struct sljit_compiler *compiler)
1.1       misho     578: {
1.1.1.4 ! misho     579:        sljit_ub *inst;
1.1       misho     580: 
                    581: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     582:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
        !           583:        FAIL_IF(!inst);
1.1       misho     584:        INC_SIZE(5);
                    585: #else
1.1.1.4 ! misho     586:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
        !           587:        FAIL_IF(!inst);
1.1       misho     588:        INC_SIZE(6);
1.1.1.4 ! misho     589:        *inst++ = REX_W;
1.1       misho     590: #endif
1.1.1.4 ! misho     591:        *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */
        !           592:        *inst++ = 0x64;
        !           593:        *inst++ = 0x24;
        !           594:        *inst++ = (sljit_ub)sizeof(sljit_sw);
        !           595:        *inst++ = PUSHF;
1.1       misho     596:        compiler->flags_saved = 1;
                    597:        return SLJIT_SUCCESS;
                    598: }
                    599: 
1.1.1.4 ! misho     600: static SLJIT_INLINE sljit_si emit_restore_flags(struct sljit_compiler *compiler, sljit_si keep_flags)
1.1       misho     601: {
1.1.1.4 ! misho     602:        sljit_ub *inst;
1.1       misho     603: 
                    604: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     605:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
        !           606:        FAIL_IF(!inst);
1.1       misho     607:        INC_SIZE(5);
1.1.1.4 ! misho     608:        *inst++ = POPF;
1.1       misho     609: #else
1.1.1.4 ! misho     610:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 6);
        !           611:        FAIL_IF(!inst);
1.1       misho     612:        INC_SIZE(6);
1.1.1.4 ! misho     613:        *inst++ = POPF;
        !           614:        *inst++ = REX_W;
1.1       misho     615: #endif
1.1.1.4 ! misho     616:        *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */
        !           617:        *inst++ = 0x64;
        !           618:        *inst++ = 0x24;
        !           619:        *inst++ = (sljit_ub)-(sljit_sb)sizeof(sljit_sw);
1.1       misho     620:        compiler->flags_saved = keep_flags;
                    621:        return SLJIT_SUCCESS;
                    622: }
                    623: 
                    624: #ifdef _WIN32
                    625: #include <malloc.h>
                    626: 
1.1.1.4 ! misho     627: static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size)
1.1       misho     628: {
1.1.1.3   misho     629:        /* Workaround for calling the internal _chkstk() function on Windows.
                    630:        This function touches all 4k pages belongs to the requested stack space,
                    631:        which size is passed in local_size. This is necessary on Windows where
                    632:        the stack can only grow in 4k steps. However, this function just burn
1.1.1.4 ! misho     633:        CPU cycles if the stack is large enough. However, you don't know it in
        !           634:        advance, so it must always be called. I think this is a bad design in
        !           635:        general even if it has some reasons. */
        !           636:        *(sljit_si*)alloca(local_size) = 0;
1.1       misho     637: }
1.1.1.3   misho     638: 
1.1       misho     639: #endif
                    640: 
                    641: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                    642: #include "sljitNativeX86_32.c"
                    643: #else
                    644: #include "sljitNativeX86_64.c"
                    645: #endif
                    646: 
1.1.1.4 ! misho     647: static sljit_si emit_mov(struct sljit_compiler *compiler,
        !           648:        sljit_si dst, sljit_sw dstw,
        !           649:        sljit_si src, sljit_sw srcw)
1.1       misho     650: {
1.1.1.4 ! misho     651:        sljit_ub* inst;
1.1       misho     652: 
                    653:        if (dst == SLJIT_UNUSED) {
                    654:                /* No destination, doesn't need to setup flags. */
                    655:                if (src & SLJIT_MEM) {
1.1.1.4 ! misho     656:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
        !           657:                        FAIL_IF(!inst);
        !           658:                        *inst = MOV_r_rm;
1.1       misho     659:                }
                    660:                return SLJIT_SUCCESS;
                    661:        }
1.1.1.4 ! misho     662:        if (src <= TMP_REGISTER) {
        !           663:                inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
        !           664:                FAIL_IF(!inst);
        !           665:                *inst = MOV_rm_r;
1.1       misho     666:                return SLJIT_SUCCESS;
                    667:        }
                    668:        if (src & SLJIT_IMM) {
1.1.1.4 ! misho     669:                if (dst <= TMP_REGISTER) {
1.1       misho     670: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     671:                        return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
1.1       misho     672: #else
                    673:                        if (!compiler->mode32) {
                    674:                                if (NOT_HALFWORD(srcw))
                    675:                                        return emit_load_imm64(compiler, dst, srcw);
                    676:                        }
                    677:                        else
1.1.1.4 ! misho     678:                                return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, MOV_r_i32 + reg_lmap[dst], srcw);
1.1       misho     679: #endif
                    680:                }
                    681: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                    682:                if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
                    683:                        FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw));
1.1.1.4 ! misho     684:                        inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw);
        !           685:                        FAIL_IF(!inst);
        !           686:                        *inst = MOV_rm_r;
1.1       misho     687:                        return SLJIT_SUCCESS;
                    688:                }
                    689: #endif
1.1.1.4 ! misho     690:                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);
        !           691:                FAIL_IF(!inst);
        !           692:                *inst = MOV_rm_i32;
1.1       misho     693:                return SLJIT_SUCCESS;
                    694:        }
1.1.1.4 ! misho     695:        if (dst <= TMP_REGISTER) {
        !           696:                inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
        !           697:                FAIL_IF(!inst);
        !           698:                *inst = MOV_r_rm;
1.1       misho     699:                return SLJIT_SUCCESS;
                    700:        }
                    701: 
                    702:        /* Memory to memory move. Requires two instruction. */
1.1.1.4 ! misho     703:        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw);
        !           704:        FAIL_IF(!inst);
        !           705:        *inst = MOV_r_rm;
        !           706:        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
        !           707:        FAIL_IF(!inst);
        !           708:        *inst = MOV_rm_r;
1.1       misho     709:        return SLJIT_SUCCESS;
                    710: }
                    711: 
                    712: #define EMIT_MOV(compiler, dst, dstw, src, srcw) \
                    713:        FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
                    714: 
1.1.1.4 ! misho     715: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
1.1.1.2   misho     716: {
1.1.1.4 ! misho     717:        sljit_ub *inst;
1.1.1.2   misho     718: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho     719:        sljit_si size;
1.1.1.2   misho     720: #endif
                    721: 
                    722:        CHECK_ERROR();
                    723:        check_sljit_emit_op0(compiler, op);
                    724: 
                    725:        switch (GET_OPCODE(op)) {
                    726:        case SLJIT_BREAKPOINT:
1.1.1.4 ! misho     727:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !           728:                FAIL_IF(!inst);
1.1.1.2   misho     729:                INC_SIZE(1);
1.1.1.4 ! misho     730:                *inst = INT3;
1.1.1.2   misho     731:                break;
                    732:        case SLJIT_NOP:
1.1.1.4 ! misho     733:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !           734:                FAIL_IF(!inst);
1.1.1.2   misho     735:                INC_SIZE(1);
1.1.1.4 ! misho     736:                *inst = NOP;
1.1.1.2   misho     737:                break;
                    738:        case SLJIT_UMUL:
                    739:        case SLJIT_SMUL:
                    740:        case SLJIT_UDIV:
                    741:        case SLJIT_SDIV:
                    742:                compiler->flags_saved = 0;
                    743: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                    744: #ifdef _WIN64
                    745:                SLJIT_COMPILE_ASSERT(
1.1.1.4 ! misho     746:                        reg_map[SLJIT_SCRATCH_REG1] == 0
        !           747:                        && reg_map[SLJIT_SCRATCH_REG2] == 2
1.1.1.2   misho     748:                        && reg_map[TMP_REGISTER] > 7,
                    749:                        invalid_register_assignment_for_div_mul);
                    750: #else
                    751:                SLJIT_COMPILE_ASSERT(
1.1.1.4 ! misho     752:                        reg_map[SLJIT_SCRATCH_REG1] == 0
        !           753:                        && reg_map[SLJIT_SCRATCH_REG2] < 7
1.1.1.2   misho     754:                        && reg_map[TMP_REGISTER] == 2,
                    755:                        invalid_register_assignment_for_div_mul);
                    756: #endif
                    757:                compiler->mode32 = op & SLJIT_INT_OP;
                    758: #endif
                    759: 
                    760:                op = GET_OPCODE(op);
                    761:                if (op == SLJIT_UDIV) {
                    762: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
1.1.1.4 ! misho     763:                        EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
        !           764:                        inst = emit_x86_instruction(compiler, 1, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0);
1.1.1.2   misho     765: #else
1.1.1.4 ! misho     766:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
1.1.1.2   misho     767: #endif
1.1.1.4 ! misho     768:                        FAIL_IF(!inst);
        !           769:                        *inst = XOR_r_rm;
1.1.1.2   misho     770:                }
                    771: 
                    772:                if (op == SLJIT_SDIV) {
                    773: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
1.1.1.4 ! misho     774:                        EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_SCRATCH_REG2, 0);
1.1.1.2   misho     775: #endif
                    776: 
                    777: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     778:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !           779:                        FAIL_IF(!inst);
1.1.1.2   misho     780:                        INC_SIZE(1);
1.1.1.4 ! misho     781:                        *inst = CDQ;
1.1.1.2   misho     782: #else
                    783:                        if (compiler->mode32) {
1.1.1.4 ! misho     784:                                inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !           785:                                FAIL_IF(!inst);
1.1.1.2   misho     786:                                INC_SIZE(1);
1.1.1.4 ! misho     787:                                *inst = CDQ;
1.1.1.2   misho     788:                        } else {
1.1.1.4 ! misho     789:                                inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
        !           790:                                FAIL_IF(!inst);
1.1.1.2   misho     791:                                INC_SIZE(2);
1.1.1.4 ! misho     792:                                *inst++ = REX_W;
        !           793:                                *inst = CDQ;
1.1.1.2   misho     794:                        }
                    795: #endif
                    796:                }
                    797: 
                    798: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     799:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
        !           800:                FAIL_IF(!inst);
1.1.1.2   misho     801:                INC_SIZE(2);
1.1.1.4 ! misho     802:                *inst++ = GROUP_F7;
        !           803:                *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_SCRATCH_REG2]);
1.1.1.2   misho     804: #else
                    805: #ifdef _WIN64
                    806:                size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2;
                    807: #else
                    808:                size = (!compiler->mode32) ? 3 : 2;
                    809: #endif
1.1.1.4 ! misho     810:                inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
        !           811:                FAIL_IF(!inst);
1.1.1.2   misho     812:                INC_SIZE(size);
                    813: #ifdef _WIN64
                    814:                if (!compiler->mode32)
1.1.1.4 ! misho     815:                        *inst++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0);
1.1.1.2   misho     816:                else if (op >= SLJIT_UDIV)
1.1.1.4 ! misho     817:                        *inst++ = REX_B;
        !           818:                *inst++ = GROUP_F7;
        !           819:                *inst = MOD_REG | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_SCRATCH_REG2]);
1.1.1.2   misho     820: #else
                    821:                if (!compiler->mode32)
1.1.1.4 ! misho     822:                        *inst++ = REX_W;
        !           823:                *inst++ = GROUP_F7;
        !           824:                *inst = MOD_REG | reg_map[SLJIT_SCRATCH_REG2];
1.1.1.2   misho     825: #endif
                    826: #endif
                    827:                switch (op) {
                    828:                case SLJIT_UMUL:
1.1.1.4 ! misho     829:                        *inst |= MUL;
1.1.1.2   misho     830:                        break;
                    831:                case SLJIT_SMUL:
1.1.1.4 ! misho     832:                        *inst |= IMUL;
1.1.1.2   misho     833:                        break;
                    834:                case SLJIT_UDIV:
1.1.1.4 ! misho     835:                        *inst |= DIV;
1.1.1.2   misho     836:                        break;
                    837:                case SLJIT_SDIV:
1.1.1.4 ! misho     838:                        *inst |= IDIV;
1.1.1.2   misho     839:                        break;
                    840:                }
                    841: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
1.1.1.4 ! misho     842:                EMIT_MOV(compiler, SLJIT_SCRATCH_REG2, 0, TMP_REGISTER, 0);
1.1.1.2   misho     843: #endif
                    844:                break;
                    845:        }
                    846: 
                    847:        return SLJIT_SUCCESS;
                    848: }
                    849: 
1.1       misho     850: #define ENCODE_PREFIX(prefix) \
                    851:        do { \
1.1.1.4 ! misho     852:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
        !           853:                FAIL_IF(!inst); \
        !           854:                INC_SIZE(1); \
        !           855:                *inst = (prefix); \
1.1       misho     856:        } while (0)
                    857: 
1.1.1.4 ! misho     858: static sljit_si emit_mov_byte(struct sljit_compiler *compiler, sljit_si sign,
        !           859:        sljit_si dst, sljit_sw dstw,
        !           860:        sljit_si src, sljit_sw srcw)
1.1       misho     861: {
1.1.1.4 ! misho     862:        sljit_ub* inst;
        !           863:        sljit_si dst_r;
1.1       misho     864: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     865:        sljit_si work_r;
1.1       misho     866: #endif
                    867: 
                    868: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                    869:        compiler->mode32 = 0;
                    870: #endif
                    871: 
                    872:        if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
                    873:                return SLJIT_SUCCESS; /* Empty instruction. */
                    874: 
                    875:        if (src & SLJIT_IMM) {
1.1.1.4 ! misho     876:                if (dst <= TMP_REGISTER) {
1.1       misho     877: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     878:                        return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
1.1       misho     879: #else
1.1.1.4 ! misho     880:                        inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
        !           881:                        FAIL_IF(!inst);
        !           882:                        *inst = MOV_rm_i32;
        !           883:                        return SLJIT_SUCCESS;
1.1       misho     884: #endif
                    885:                }
1.1.1.4 ! misho     886:                inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);
        !           887:                FAIL_IF(!inst);
        !           888:                *inst = MOV_rm8_i8;
1.1       misho     889:                return SLJIT_SUCCESS;
                    890:        }
                    891: 
1.1.1.4 ! misho     892:        dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
1.1       misho     893: 
1.1.1.4 ! misho     894:        if ((dst & SLJIT_MEM) && src <= TMP_REGISTER) {
1.1       misho     895: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                    896:                if (reg_map[src] >= 4) {
                    897:                        SLJIT_ASSERT(dst_r == TMP_REGISTER);
                    898:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
                    899:                } else
                    900:                        dst_r = src;
                    901: #else
                    902:                dst_r = src;
                    903: #endif
                    904:        }
                    905: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho     906:        else if (src <= TMP_REGISTER && reg_map[src] >= 4) {
1.1       misho     907:                /* src, dst are registers. */
1.1.1.4 ! misho     908:                SLJIT_ASSERT(dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REGISTER);
1.1       misho     909:                if (reg_map[dst] < 4) {
                    910:                        if (dst != src)
                    911:                                EMIT_MOV(compiler, dst, 0, src, 0);
1.1.1.4 ! misho     912:                        inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0);
        !           913:                        FAIL_IF(!inst);
        !           914:                        *inst++ = GROUP_0F;
        !           915:                        *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;
1.1       misho     916:                }
                    917:                else {
                    918:                        if (dst != src)
                    919:                                EMIT_MOV(compiler, dst, 0, src, 0);
                    920:                        if (sign) {
                    921:                                /* shl reg, 24 */
1.1.1.4 ! misho     922:                                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
        !           923:                                FAIL_IF(!inst);
        !           924:                                *inst |= SHL;
        !           925:                                /* sar reg, 24 */
        !           926:                                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0);
        !           927:                                FAIL_IF(!inst);
        !           928:                                *inst |= SAR;
1.1       misho     929:                        }
                    930:                        else {
1.1.1.4 ! misho     931:                                inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);
        !           932:                                FAIL_IF(!inst);
        !           933:                                *(inst + 1) |= AND;
1.1       misho     934:                        }
                    935:                }
                    936:                return SLJIT_SUCCESS;
                    937:        }
                    938: #endif
                    939:        else {
                    940:                /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
1.1.1.4 ! misho     941:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
        !           942:                FAIL_IF(!inst);
        !           943:                *inst++ = GROUP_0F;
        !           944:                *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8;
1.1       misho     945:        }
                    946: 
                    947:        if (dst & SLJIT_MEM) {
                    948: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                    949:                if (dst_r == TMP_REGISTER) {
                    950:                        /* Find a non-used register, whose reg_map[src] < 4. */
1.1.1.4 ! misho     951:                        if ((dst & 0xf) == SLJIT_SCRATCH_REG1) {
        !           952:                                if ((dst & 0xf0) == (SLJIT_SCRATCH_REG2 << 4))
        !           953:                                        work_r = SLJIT_SCRATCH_REG3;
1.1       misho     954:                                else
1.1.1.4 ! misho     955:                                        work_r = SLJIT_SCRATCH_REG2;
1.1       misho     956:                        }
                    957:                        else {
1.1.1.4 ! misho     958:                                if ((dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
        !           959:                                        work_r = SLJIT_SCRATCH_REG1;
        !           960:                                else if ((dst & 0xf) == SLJIT_SCRATCH_REG2)
        !           961:                                        work_r = SLJIT_SCRATCH_REG3;
1.1       misho     962:                                else
1.1.1.4 ! misho     963:                                        work_r = SLJIT_SCRATCH_REG2;
1.1       misho     964:                        }
                    965: 
1.1.1.4 ! misho     966:                        if (work_r == SLJIT_SCRATCH_REG1) {
        !           967:                                ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
1.1       misho     968:                        }
                    969:                        else {
1.1.1.4 ! misho     970:                                inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
        !           971:                                FAIL_IF(!inst);
        !           972:                                *inst = XCHG_r_rm;
1.1       misho     973:                        }
                    974: 
1.1.1.4 ! misho     975:                        inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw);
        !           976:                        FAIL_IF(!inst);
        !           977:                        *inst = MOV_rm8_r8;
1.1       misho     978: 
1.1.1.4 ! misho     979:                        if (work_r == SLJIT_SCRATCH_REG1) {
        !           980:                                ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REGISTER]);
1.1       misho     981:                        }
                    982:                        else {
1.1.1.4 ! misho     983:                                inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
        !           984:                                FAIL_IF(!inst);
        !           985:                                *inst = XCHG_r_rm;
1.1       misho     986:                        }
                    987:                }
                    988:                else {
1.1.1.4 ! misho     989:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
        !           990:                        FAIL_IF(!inst);
        !           991:                        *inst = MOV_rm8_r8;
1.1       misho     992:                }
                    993: #else
1.1.1.4 ! misho     994:                inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);
        !           995:                FAIL_IF(!inst);
        !           996:                *inst = MOV_rm8_r8;
1.1       misho     997: #endif
                    998:        }
                    999: 
                   1000:        return SLJIT_SUCCESS;
                   1001: }
                   1002: 
1.1.1.4 ! misho    1003: static sljit_si emit_mov_half(struct sljit_compiler *compiler, sljit_si sign,
        !          1004:        sljit_si dst, sljit_sw dstw,
        !          1005:        sljit_si src, sljit_sw srcw)
1.1       misho    1006: {
1.1.1.4 ! misho    1007:        sljit_ub* inst;
        !          1008:        sljit_si dst_r;
1.1       misho    1009: 
                   1010: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1011:        compiler->mode32 = 0;
                   1012: #endif
                   1013: 
                   1014:        if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
                   1015:                return SLJIT_SUCCESS; /* Empty instruction. */
                   1016: 
                   1017:        if (src & SLJIT_IMM) {
1.1.1.4 ! misho    1018:                if (dst <= TMP_REGISTER) {
1.1       misho    1019: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1020:                        return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
1.1       misho    1021: #else
1.1.1.4 ! misho    1022:                        inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
        !          1023:                        FAIL_IF(!inst);
        !          1024:                        *inst = MOV_rm_i32;
        !          1025:                        return SLJIT_SUCCESS;
1.1       misho    1026: #endif
                   1027:                }
1.1.1.4 ! misho    1028:                inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);
        !          1029:                FAIL_IF(!inst);
        !          1030:                *inst = MOV_rm_i32;
1.1       misho    1031:                return SLJIT_SUCCESS;
                   1032:        }
                   1033: 
1.1.1.4 ! misho    1034:        dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
1.1       misho    1035: 
1.1.1.4 ! misho    1036:        if ((dst & SLJIT_MEM) && src <= TMP_REGISTER)
1.1       misho    1037:                dst_r = src;
                   1038:        else {
1.1.1.4 ! misho    1039:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw);
        !          1040:                FAIL_IF(!inst);
        !          1041:                *inst++ = GROUP_0F;
        !          1042:                *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16;
1.1       misho    1043:        }
                   1044: 
                   1045:        if (dst & SLJIT_MEM) {
1.1.1.4 ! misho    1046:                inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);
        !          1047:                FAIL_IF(!inst);
        !          1048:                *inst = MOV_rm_r;
1.1       misho    1049:        }
                   1050: 
                   1051:        return SLJIT_SUCCESS;
                   1052: }
                   1053: 
1.1.1.4 ! misho    1054: static sljit_si emit_unary(struct sljit_compiler *compiler, sljit_ub opcode,
        !          1055:        sljit_si dst, sljit_sw dstw,
        !          1056:        sljit_si src, sljit_sw srcw)
1.1       misho    1057: {
1.1.1.4 ! misho    1058:        sljit_ub* inst;
1.1       misho    1059: 
                   1060:        if (dst == SLJIT_UNUSED) {
                   1061:                EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
1.1.1.4 ! misho    1062:                inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
        !          1063:                FAIL_IF(!inst);
        !          1064:                *inst++ = GROUP_F7;
        !          1065:                *inst |= opcode;
1.1       misho    1066:                return SLJIT_SUCCESS;
                   1067:        }
                   1068:        if (dst == src && dstw == srcw) {
                   1069:                /* Same input and output */
1.1.1.4 ! misho    1070:                inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
        !          1071:                FAIL_IF(!inst);
        !          1072:                *inst++ = GROUP_F7;
        !          1073:                *inst |= opcode;
1.1       misho    1074:                return SLJIT_SUCCESS;
                   1075:        }
1.1.1.4 ! misho    1076:        if (dst <= TMP_REGISTER) {
1.1       misho    1077:                EMIT_MOV(compiler, dst, 0, src, srcw);
1.1.1.4 ! misho    1078:                inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
        !          1079:                FAIL_IF(!inst);
        !          1080:                *inst++ = GROUP_F7;
        !          1081:                *inst |= opcode;
1.1       misho    1082:                return SLJIT_SUCCESS;
                   1083:        }
                   1084:        EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
1.1.1.4 ! misho    1085:        inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
        !          1086:        FAIL_IF(!inst);
        !          1087:        *inst++ = GROUP_F7;
        !          1088:        *inst |= opcode;
1.1       misho    1089:        EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   1090:        return SLJIT_SUCCESS;
                   1091: }
                   1092: 
1.1.1.4 ! misho    1093: static sljit_si emit_not_with_flags(struct sljit_compiler *compiler,
        !          1094:        sljit_si dst, sljit_sw dstw,
        !          1095:        sljit_si src, sljit_sw srcw)
1.1       misho    1096: {
1.1.1.4 ! misho    1097:        sljit_ub* inst;
1.1       misho    1098: 
                   1099:        if (dst == SLJIT_UNUSED) {
                   1100:                EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
1.1.1.4 ! misho    1101:                inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
        !          1102:                FAIL_IF(!inst);
        !          1103:                *inst++ = GROUP_F7;
        !          1104:                *inst |= NOT_rm;
        !          1105:                inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
        !          1106:                FAIL_IF(!inst);
        !          1107:                *inst = OR_r_rm;
1.1       misho    1108:                return SLJIT_SUCCESS;
                   1109:        }
1.1.1.4 ! misho    1110:        if (dst <= TMP_REGISTER) {
1.1       misho    1111:                EMIT_MOV(compiler, dst, 0, src, srcw);
1.1.1.4 ! misho    1112:                inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
        !          1113:                FAIL_IF(!inst);
        !          1114:                *inst++ = GROUP_F7;
        !          1115:                *inst |= NOT_rm;
        !          1116:                inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);
        !          1117:                FAIL_IF(!inst);
        !          1118:                *inst = OR_r_rm;
1.1       misho    1119:                return SLJIT_SUCCESS;
                   1120:        }
                   1121:        EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
1.1.1.4 ! misho    1122:        inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
        !          1123:        FAIL_IF(!inst);
        !          1124:        *inst++ = GROUP_F7;
        !          1125:        *inst |= NOT_rm;
        !          1126:        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0);
        !          1127:        FAIL_IF(!inst);
        !          1128:        *inst = OR_r_rm;
1.1       misho    1129:        EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   1130:        return SLJIT_SUCCESS;
                   1131: }
                   1132: 
1.1.1.4 ! misho    1133: static sljit_si emit_clz(struct sljit_compiler *compiler, sljit_si op_flags,
        !          1134:        sljit_si dst, sljit_sw dstw,
        !          1135:        sljit_si src, sljit_sw srcw)
1.1       misho    1136: {
1.1.1.4 ! misho    1137:        sljit_ub* inst;
        !          1138:        sljit_si dst_r;
1.1       misho    1139: 
1.1.1.4 ! misho    1140:        SLJIT_UNUSED_ARG(op_flags);
1.1       misho    1141:        if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
                   1142:                /* Just set the zero flag. */
                   1143:                EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw);
1.1.1.4 ! misho    1144:                inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0);
        !          1145:                FAIL_IF(!inst);
        !          1146:                *inst++ = GROUP_F7;
        !          1147:                *inst |= NOT_rm;
1.1       misho    1148: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1149:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0);
1.1       misho    1150: #else
1.1.1.4 ! misho    1151:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0);
1.1       misho    1152: #endif
1.1.1.4 ! misho    1153:                FAIL_IF(!inst);
        !          1154:                *inst |= SHR;
1.1       misho    1155:                return SLJIT_SUCCESS;
                   1156:        }
                   1157: 
                   1158:        if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
1.1.1.4 ! misho    1159:                EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, srcw);
1.1       misho    1160:                src = TMP_REGISTER;
                   1161:                srcw = 0;
                   1162:        }
                   1163: 
1.1.1.4 ! misho    1164:        inst = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw);
        !          1165:        FAIL_IF(!inst);
        !          1166:        *inst++ = GROUP_0F;
        !          1167:        *inst = BSR_r_rm;
1.1       misho    1168: 
                   1169: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1170:        if (dst <= TMP_REGISTER)
1.1       misho    1171:                dst_r = dst;
                   1172:        else {
                   1173:                /* Find an unused temporary register. */
1.1.1.4 ! misho    1174:                if ((dst & 0xf) != SLJIT_SCRATCH_REG1 && (dst & 0xf0) != (SLJIT_SCRATCH_REG1 << 4))
        !          1175:                        dst_r = SLJIT_SCRATCH_REG1;
        !          1176:                else if ((dst & 0xf) != SLJIT_SCRATCH_REG2 && (dst & 0xf0) != (SLJIT_SCRATCH_REG2 << 4))
        !          1177:                        dst_r = SLJIT_SCRATCH_REG2;
1.1       misho    1178:                else
1.1.1.4 ! misho    1179:                        dst_r = SLJIT_SCRATCH_REG3;
1.1       misho    1180:                EMIT_MOV(compiler, dst, dstw, dst_r, 0);
                   1181:        }
                   1182:        EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31);
                   1183: #else
1.1.1.4 ! misho    1184:        dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REG2;
1.1       misho    1185:        compiler->mode32 = 0;
1.1.1.4 ! misho    1186:        EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 64 + 63 : 32 + 31);
        !          1187:        compiler->mode32 = op_flags & SLJIT_INT_OP;
1.1       misho    1188: #endif
                   1189: 
1.1.1.4 ! misho    1190:        if (cpu_has_cmov == -1)
        !          1191:                get_cpu_features();
1.1       misho    1192: 
1.1.1.4 ! misho    1193:        if (cpu_has_cmov) {
        !          1194:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0);
        !          1195:                FAIL_IF(!inst);
        !          1196:                *inst++ = GROUP_0F;
        !          1197:                *inst = CMOVNE_r_rm;
        !          1198:        } else {
1.1       misho    1199: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1200:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
        !          1201:                FAIL_IF(!inst);
        !          1202:                INC_SIZE(4);
        !          1203: 
        !          1204:                *inst++ = JE_i8;
        !          1205:                *inst++ = 2;
        !          1206:                *inst++ = MOV_r_rm;
        !          1207:                *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REGISTER];
1.1       misho    1208: #else
1.1.1.4 ! misho    1209:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
        !          1210:                FAIL_IF(!inst);
        !          1211:                INC_SIZE(5);
        !          1212: 
        !          1213:                *inst++ = JE_i8;
        !          1214:                *inst++ = 3;
        !          1215:                *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REGISTER] >= 8 ? REX_B : 0);
        !          1216:                *inst++ = MOV_r_rm;
        !          1217:                *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REGISTER];
1.1       misho    1218: #endif
1.1.1.4 ! misho    1219:        }
        !          1220: 
        !          1221: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
        !          1222:        inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
        !          1223: #else
        !          1224:        inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_INT_OP) ? 63 : 31, dst_r, 0);
        !          1225: #endif
        !          1226:        FAIL_IF(!inst);
        !          1227:        *(inst + 1) |= XOR;
1.1       misho    1228: 
                   1229: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1230:        if (dst & SLJIT_MEM) {
1.1.1.4 ! misho    1231:                inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
        !          1232:                FAIL_IF(!inst);
        !          1233:                *inst = XCHG_r_rm;
1.1       misho    1234:        }
                   1235: #else
                   1236:        if (dst & SLJIT_MEM)
                   1237:                EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0);
                   1238: #endif
                   1239:        return SLJIT_SUCCESS;
                   1240: }
                   1241: 
1.1.1.4 ! misho    1242: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
        !          1243:        sljit_si dst, sljit_sw dstw,
        !          1244:        sljit_si src, sljit_sw srcw)
        !          1245: {
        !          1246:        sljit_ub* inst;
        !          1247:        sljit_si update = 0;
        !          1248:        sljit_si op_flags = GET_ALL_FLAGS(op);
1.1       misho    1249: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1250:        sljit_si dst_is_ereg = 0;
        !          1251:        sljit_si src_is_ereg = 0;
1.1       misho    1252: #else
1.1.1.4 ! misho    1253: #      define src_is_ereg 0
1.1       misho    1254: #endif
                   1255: 
                   1256:        CHECK_ERROR();
                   1257:        check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
1.1.1.3   misho    1258:        ADJUST_LOCAL_OFFSET(dst, dstw);
                   1259:        ADJUST_LOCAL_OFFSET(src, srcw);
1.1       misho    1260: 
1.1.1.3   misho    1261:        CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
                   1262:        CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
1.1       misho    1263: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1264:        compiler->mode32 = op_flags & SLJIT_INT_OP;
1.1       misho    1265: #endif
                   1266: 
1.1.1.4 ! misho    1267:        op = GET_OPCODE(op);
        !          1268:        if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
1.1       misho    1269: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1270:                compiler->mode32 = 0;
                   1271: #endif
                   1272: 
1.1.1.4 ! misho    1273:                if (op_flags & SLJIT_INT_OP) {
        !          1274:                        if (src <= TMP_REGISTER && src == dst) {
        !          1275:                                if (!TYPE_CAST_NEEDED(op))
        !          1276:                                        return SLJIT_SUCCESS;
        !          1277:                        }
        !          1278: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        !          1279:                        if (op == SLJIT_MOV_SI && (src & SLJIT_MEM))
        !          1280:                                op = SLJIT_MOV_UI;
        !          1281:                        if (op == SLJIT_MOVU_SI && (src & SLJIT_MEM))
        !          1282:                                op = SLJIT_MOVU_UI;
        !          1283:                        if (op == SLJIT_MOV_UI && (src & SLJIT_IMM))
        !          1284:                                op = SLJIT_MOV_SI;
        !          1285:                        if (op == SLJIT_MOVU_UI && (src & SLJIT_IMM))
        !          1286:                                op = SLJIT_MOVU_SI;
        !          1287: #endif
        !          1288:                }
        !          1289: 
        !          1290:                SLJIT_COMPILE_ASSERT(SLJIT_MOV + 8 == SLJIT_MOVU, movu_offset);
1.1       misho    1291:                if (op >= SLJIT_MOVU) {
                   1292:                        update = 1;
1.1.1.4 ! misho    1293:                        op -= 8;
1.1       misho    1294:                }
                   1295: 
                   1296:                if (src & SLJIT_IMM) {
                   1297:                        switch (op) {
                   1298:                        case SLJIT_MOV_UB:
1.1.1.4 ! misho    1299:                                srcw = (sljit_ub)srcw;
1.1       misho    1300:                                break;
                   1301:                        case SLJIT_MOV_SB:
1.1.1.4 ! misho    1302:                                srcw = (sljit_sb)srcw;
1.1       misho    1303:                                break;
                   1304:                        case SLJIT_MOV_UH:
1.1.1.4 ! misho    1305:                                srcw = (sljit_uh)srcw;
1.1       misho    1306:                                break;
                   1307:                        case SLJIT_MOV_SH:
1.1.1.4 ! misho    1308:                                srcw = (sljit_sh)srcw;
1.1       misho    1309:                                break;
                   1310: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1311:                        case SLJIT_MOV_UI:
1.1.1.4 ! misho    1312:                                srcw = (sljit_ui)srcw;
1.1       misho    1313:                                break;
                   1314:                        case SLJIT_MOV_SI:
1.1.1.4 ! misho    1315:                                srcw = (sljit_si)srcw;
1.1       misho    1316:                                break;
                   1317: #endif
                   1318:                        }
                   1319: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1320:                        if (SLJIT_UNLIKELY(dst_is_ereg))
                   1321:                                return emit_mov(compiler, dst, dstw, src, srcw);
                   1322: #endif
                   1323:                }
                   1324: 
                   1325:                if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & 0xf) && (srcw != 0 || (src & 0xf0) != 0)) {
1.1.1.4 ! misho    1326:                        inst = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw);
        !          1327:                        FAIL_IF(!inst);
        !          1328:                        *inst = LEA_r_m;
1.1       misho    1329:                        src &= SLJIT_MEM | 0xf;
                   1330:                        srcw = 0;
                   1331:                }
                   1332: 
                   1333: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    1334:                if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
1.1       misho    1335:                        SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG));
                   1336:                        dst = TMP_REGISTER;
                   1337:                }
                   1338: #endif
                   1339: 
                   1340:                switch (op) {
                   1341:                case SLJIT_MOV:
1.1.1.4 ! misho    1342:                case SLJIT_MOV_P:
1.1       misho    1343: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1344:                case SLJIT_MOV_UI:
                   1345:                case SLJIT_MOV_SI:
                   1346: #endif
                   1347:                        FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
                   1348:                        break;
                   1349:                case SLJIT_MOV_UB:
1.1.1.4 ! misho    1350:                        FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));
1.1       misho    1351:                        break;
                   1352:                case SLJIT_MOV_SB:
1.1.1.4 ! misho    1353:                        FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));
1.1       misho    1354:                        break;
                   1355:                case SLJIT_MOV_UH:
1.1.1.4 ! misho    1356:                        FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));
1.1       misho    1357:                        break;
                   1358:                case SLJIT_MOV_SH:
1.1.1.4 ! misho    1359:                        FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw));
1.1       misho    1360:                        break;
                   1361: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1362:                case SLJIT_MOV_UI:
1.1.1.4 ! misho    1363:                        FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));
1.1       misho    1364:                        break;
                   1365:                case SLJIT_MOV_SI:
1.1.1.4 ! misho    1366:                        FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));
1.1       misho    1367:                        break;
                   1368: #endif
                   1369:                }
                   1370: 
                   1371: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1372:                if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REGISTER)
                   1373:                        return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REGISTER, 0);
                   1374: #endif
                   1375: 
                   1376:                if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & 0xf) && (dstw != 0 || (dst & 0xf0) != 0)) {
1.1.1.4 ! misho    1377:                        inst = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw);
        !          1378:                        FAIL_IF(!inst);
        !          1379:                        *inst = LEA_r_m;
1.1       misho    1380:                }
                   1381:                return SLJIT_SUCCESS;
                   1382:        }
                   1383: 
1.1.1.4 ! misho    1384:        if (SLJIT_UNLIKELY(GET_FLAGS(op_flags)))
1.1       misho    1385:                compiler->flags_saved = 0;
                   1386: 
1.1.1.4 ! misho    1387:        switch (op) {
1.1       misho    1388:        case SLJIT_NOT:
1.1.1.4 ! misho    1389:                if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_E))
1.1       misho    1390:                        return emit_not_with_flags(compiler, dst, dstw, src, srcw);
1.1.1.4 ! misho    1391:                return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);
1.1       misho    1392: 
                   1393:        case SLJIT_NEG:
1.1.1.4 ! misho    1394:                if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
1.1       misho    1395:                        FAIL_IF(emit_save_flags(compiler));
1.1.1.4 ! misho    1396:                return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);
1.1       misho    1397: 
                   1398:        case SLJIT_CLZ:
1.1.1.4 ! misho    1399:                if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
1.1       misho    1400:                        FAIL_IF(emit_save_flags(compiler));
1.1.1.4 ! misho    1401:                return emit_clz(compiler, op_flags, dst, dstw, src, srcw);
1.1       misho    1402:        }
                   1403: 
                   1404:        return SLJIT_SUCCESS;
                   1405: 
                   1406: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1407: #      undef src_is_ereg
1.1       misho    1408: #endif
                   1409: }
                   1410: 
                   1411: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1412: 
1.1.1.4 ! misho    1413: #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
1.1       misho    1414:        if (IS_HALFWORD(immw) || compiler->mode32) { \
1.1.1.4 ! misho    1415:                inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
        !          1416:                FAIL_IF(!inst); \
        !          1417:                *(inst + 1) |= (op_imm); \
1.1       misho    1418:        } \
                   1419:        else { \
                   1420:                FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
1.1.1.4 ! misho    1421:                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
        !          1422:                FAIL_IF(!inst); \
        !          1423:                *inst = (op_mr); \
1.1       misho    1424:        }
                   1425: 
1.1.1.4 ! misho    1426: #define BINARY_EAX_IMM(op_eax_imm, immw) \
        !          1427:        FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
1.1       misho    1428: 
                   1429: #else
                   1430: 
1.1.1.4 ! misho    1431: #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
        !          1432:        inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
        !          1433:        FAIL_IF(!inst); \
        !          1434:        *(inst + 1) |= (op_imm);
1.1       misho    1435: 
1.1.1.4 ! misho    1436: #define BINARY_EAX_IMM(op_eax_imm, immw) \
        !          1437:        FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
1.1       misho    1438: 
                   1439: #endif
                   1440: 
1.1.1.4 ! misho    1441: static sljit_si emit_cum_binary(struct sljit_compiler *compiler,
1.1       misho    1442:        sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
1.1.1.4 ! misho    1443:        sljit_si dst, sljit_sw dstw,
        !          1444:        sljit_si src1, sljit_sw src1w,
        !          1445:        sljit_si src2, sljit_sw src2w)
1.1       misho    1446: {
1.1.1.4 ! misho    1447:        sljit_ub* inst;
1.1       misho    1448: 
                   1449:        if (dst == SLJIT_UNUSED) {
                   1450:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1451:                if (src2 & SLJIT_IMM) {
                   1452:                        BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
                   1453:                }
                   1454:                else {
1.1.1.4 ! misho    1455:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1456:                        FAIL_IF(!inst);
        !          1457:                        *inst = op_rm;
1.1       misho    1458:                }
                   1459:                return SLJIT_SUCCESS;
                   1460:        }
                   1461: 
                   1462:        if (dst == src1 && dstw == src1w) {
                   1463:                if (src2 & SLJIT_IMM) {
                   1464: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1465:                        if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
1.1       misho    1466: #else
1.1.1.4 ! misho    1467:                        if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
1.1       misho    1468: #endif
                   1469:                                BINARY_EAX_IMM(op_eax_imm, src2w);
                   1470:                        }
                   1471:                        else {
                   1472:                                BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
                   1473:                        }
                   1474:                }
1.1.1.4 ! misho    1475:                else if (dst <= TMP_REGISTER) {
        !          1476:                        inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
        !          1477:                        FAIL_IF(!inst);
        !          1478:                        *inst = op_rm;
        !          1479:                }
        !          1480:                else if (src2 <= TMP_REGISTER) {
        !          1481:                        /* Special exception for sljit_emit_op_flags. */
        !          1482:                        inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
        !          1483:                        FAIL_IF(!inst);
        !          1484:                        *inst = op_mr;
1.1       misho    1485:                }
                   1486:                else {
                   1487:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
1.1.1.4 ! misho    1488:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
        !          1489:                        FAIL_IF(!inst);
        !          1490:                        *inst = op_mr;
1.1       misho    1491:                }
                   1492:                return SLJIT_SUCCESS;
                   1493:        }
                   1494: 
                   1495:        /* Only for cumulative operations. */
                   1496:        if (dst == src2 && dstw == src2w) {
                   1497:                if (src1 & SLJIT_IMM) {
                   1498: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1499:                        if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
1.1       misho    1500: #else
1.1.1.4 ! misho    1501:                        if ((dst == SLJIT_SCRATCH_REG1) && (src1w > 127 || src1w < -128)) {
1.1       misho    1502: #endif
                   1503:                                BINARY_EAX_IMM(op_eax_imm, src1w);
                   1504:                        }
                   1505:                        else {
                   1506:                                BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);
                   1507:                        }
                   1508:                }
1.1.1.4 ! misho    1509:                else if (dst <= TMP_REGISTER) {
        !          1510:                        inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
        !          1511:                        FAIL_IF(!inst);
        !          1512:                        *inst = op_rm;
        !          1513:                }
        !          1514:                else if (src1 <= TMP_REGISTER) {
        !          1515:                        inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
        !          1516:                        FAIL_IF(!inst);
        !          1517:                        *inst = op_mr;
1.1       misho    1518:                }
                   1519:                else {
                   1520:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1.1.4 ! misho    1521:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
        !          1522:                        FAIL_IF(!inst);
        !          1523:                        *inst = op_mr;
1.1       misho    1524:                }
                   1525:                return SLJIT_SUCCESS;
                   1526:        }
                   1527: 
                   1528:        /* General version. */
1.1.1.4 ! misho    1529:        if (dst <= TMP_REGISTER) {
1.1       misho    1530:                EMIT_MOV(compiler, dst, 0, src1, src1w);
                   1531:                if (src2 & SLJIT_IMM) {
                   1532:                        BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
                   1533:                }
                   1534:                else {
1.1.1.4 ! misho    1535:                        inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
        !          1536:                        FAIL_IF(!inst);
        !          1537:                        *inst = op_rm;
1.1       misho    1538:                }
                   1539:        }
                   1540:        else {
                   1541:                /* This version requires less memory writing. */
                   1542:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1543:                if (src2 & SLJIT_IMM) {
                   1544:                        BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
                   1545:                }
                   1546:                else {
1.1.1.4 ! misho    1547:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1548:                        FAIL_IF(!inst);
        !          1549:                        *inst = op_rm;
1.1       misho    1550:                }
                   1551:                EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   1552:        }
                   1553: 
                   1554:        return SLJIT_SUCCESS;
                   1555: }
                   1556: 
1.1.1.4 ! misho    1557: static sljit_si emit_non_cum_binary(struct sljit_compiler *compiler,
1.1       misho    1558:        sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm,
1.1.1.4 ! misho    1559:        sljit_si dst, sljit_sw dstw,
        !          1560:        sljit_si src1, sljit_sw src1w,
        !          1561:        sljit_si src2, sljit_sw src2w)
1.1       misho    1562: {
1.1.1.4 ! misho    1563:        sljit_ub* inst;
1.1       misho    1564: 
                   1565:        if (dst == SLJIT_UNUSED) {
                   1566:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1567:                if (src2 & SLJIT_IMM) {
                   1568:                        BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
                   1569:                }
                   1570:                else {
1.1.1.4 ! misho    1571:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1572:                        FAIL_IF(!inst);
        !          1573:                        *inst = op_rm;
1.1       misho    1574:                }
                   1575:                return SLJIT_SUCCESS;
                   1576:        }
                   1577: 
                   1578:        if (dst == src1 && dstw == src1w) {
                   1579:                if (src2 & SLJIT_IMM) {
                   1580: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1581:                        if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
1.1       misho    1582: #else
1.1.1.4 ! misho    1583:                        if ((dst == SLJIT_SCRATCH_REG1) && (src2w > 127 || src2w < -128)) {
1.1       misho    1584: #endif
                   1585:                                BINARY_EAX_IMM(op_eax_imm, src2w);
                   1586:                        }
                   1587:                        else {
                   1588:                                BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
                   1589:                        }
                   1590:                }
1.1.1.4 ! misho    1591:                else if (dst <= TMP_REGISTER) {
        !          1592:                        inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
        !          1593:                        FAIL_IF(!inst);
        !          1594:                        *inst = op_rm;
        !          1595:                }
        !          1596:                else if (src2 <= TMP_REGISTER) {
        !          1597:                        inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
        !          1598:                        FAIL_IF(!inst);
        !          1599:                        *inst = op_mr;
1.1       misho    1600:                }
                   1601:                else {
                   1602:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w);
1.1.1.4 ! misho    1603:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw);
        !          1604:                        FAIL_IF(!inst);
        !          1605:                        *inst = op_mr;
1.1       misho    1606:                }
                   1607:                return SLJIT_SUCCESS;
                   1608:        }
                   1609: 
                   1610:        /* General version. */
1.1.1.4 ! misho    1611:        if (dst <= TMP_REGISTER && dst != src2) {
1.1       misho    1612:                EMIT_MOV(compiler, dst, 0, src1, src1w);
                   1613:                if (src2 & SLJIT_IMM) {
                   1614:                        BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
                   1615:                }
                   1616:                else {
1.1.1.4 ! misho    1617:                        inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
        !          1618:                        FAIL_IF(!inst);
        !          1619:                        *inst = op_rm;
1.1       misho    1620:                }
                   1621:        }
                   1622:        else {
                   1623:                /* This version requires less memory writing. */
                   1624:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1625:                if (src2 & SLJIT_IMM) {
                   1626:                        BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0);
                   1627:                }
                   1628:                else {
1.1.1.4 ! misho    1629:                        inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1630:                        FAIL_IF(!inst);
        !          1631:                        *inst = op_rm;
1.1       misho    1632:                }
                   1633:                EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   1634:        }
                   1635: 
                   1636:        return SLJIT_SUCCESS;
                   1637: }
                   1638: 
1.1.1.4 ! misho    1639: static sljit_si emit_mul(struct sljit_compiler *compiler,
        !          1640:        sljit_si dst, sljit_sw dstw,
        !          1641:        sljit_si src1, sljit_sw src1w,
        !          1642:        sljit_si src2, sljit_sw src2w)
1.1       misho    1643: {
1.1.1.4 ! misho    1644:        sljit_ub* inst;
        !          1645:        sljit_si dst_r;
1.1       misho    1646: 
1.1.1.4 ! misho    1647:        dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
1.1       misho    1648: 
                   1649:        /* Register destination. */
                   1650:        if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
1.1.1.4 ! misho    1651:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
        !          1652:                FAIL_IF(!inst);
        !          1653:                *inst++ = GROUP_0F;
        !          1654:                *inst = IMUL_r_rm;
1.1       misho    1655:        }
                   1656:        else if (dst_r == src2 && !(src1 & SLJIT_IMM)) {
1.1.1.4 ! misho    1657:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w);
        !          1658:                FAIL_IF(!inst);
        !          1659:                *inst++ = GROUP_0F;
        !          1660:                *inst = IMUL_r_rm;
1.1       misho    1661:        }
                   1662:        else if (src1 & SLJIT_IMM) {
                   1663:                if (src2 & SLJIT_IMM) {
                   1664:                        EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);
                   1665:                        src2 = dst_r;
                   1666:                        src2w = 0;
                   1667:                }
                   1668: 
                   1669:                if (src1w <= 127 && src1w >= -128) {
1.1.1.4 ! misho    1670:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
        !          1671:                        FAIL_IF(!inst);
        !          1672:                        *inst = IMUL_r_rm_i8;
        !          1673:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !          1674:                        FAIL_IF(!inst);
        !          1675:                        INC_SIZE(1);
        !          1676:                        *inst = (sljit_sb)src1w;
1.1       misho    1677:                }
                   1678: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1679:                else {
1.1.1.4 ! misho    1680:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
        !          1681:                        FAIL_IF(!inst);
        !          1682:                        *inst = IMUL_r_rm_i32;
        !          1683:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
        !          1684:                        FAIL_IF(!inst);
        !          1685:                        INC_SIZE(4);
        !          1686:                        *(sljit_sw*)inst = src1w;
1.1       misho    1687:                }
                   1688: #else
                   1689:                else if (IS_HALFWORD(src1w)) {
1.1.1.4 ! misho    1690:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
        !          1691:                        FAIL_IF(!inst);
        !          1692:                        *inst = IMUL_r_rm_i32;
        !          1693:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
        !          1694:                        FAIL_IF(!inst);
        !          1695:                        INC_SIZE(4);
        !          1696:                        *(sljit_si*)inst = (sljit_si)src1w;
1.1       misho    1697:                }
                   1698:                else {
                   1699:                        EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
                   1700:                        if (dst_r != src2)
                   1701:                                EMIT_MOV(compiler, dst_r, 0, src2, src2w);
1.1.1.4 ! misho    1702:                        inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
        !          1703:                        FAIL_IF(!inst);
        !          1704:                        *inst++ = GROUP_0F;
        !          1705:                        *inst = IMUL_r_rm;
1.1       misho    1706:                }
                   1707: #endif
                   1708:        }
                   1709:        else if (src2 & SLJIT_IMM) {
                   1710:                /* Note: src1 is NOT immediate. */
                   1711: 
                   1712:                if (src2w <= 127 && src2w >= -128) {
1.1.1.4 ! misho    1713:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
        !          1714:                        FAIL_IF(!inst);
        !          1715:                        *inst = IMUL_r_rm_i8;
        !          1716:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
        !          1717:                        FAIL_IF(!inst);
        !          1718:                        INC_SIZE(1);
        !          1719:                        *inst = (sljit_sb)src2w;
1.1       misho    1720:                }
                   1721: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   1722:                else {
1.1.1.4 ! misho    1723:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
        !          1724:                        FAIL_IF(!inst);
        !          1725:                        *inst = IMUL_r_rm_i32;
        !          1726:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
        !          1727:                        FAIL_IF(!inst);
        !          1728:                        INC_SIZE(4);
        !          1729:                        *(sljit_sw*)inst = src2w;
1.1       misho    1730:                }
                   1731: #else
                   1732:                else if (IS_HALFWORD(src2w)) {
1.1.1.4 ! misho    1733:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
        !          1734:                        FAIL_IF(!inst);
        !          1735:                        *inst = IMUL_r_rm_i32;
        !          1736:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
        !          1737:                        FAIL_IF(!inst);
        !          1738:                        INC_SIZE(4);
        !          1739:                        *(sljit_si*)inst = (sljit_si)src2w;
1.1       misho    1740:                }
                   1741:                else {
                   1742:                        EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
                   1743:                        if (dst_r != src1)
                   1744:                                EMIT_MOV(compiler, dst_r, 0, src1, src1w);
1.1.1.4 ! misho    1745:                        inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
        !          1746:                        FAIL_IF(!inst);
        !          1747:                        *inst++ = GROUP_0F;
        !          1748:                        *inst = IMUL_r_rm;
1.1       misho    1749:                }
                   1750: #endif
                   1751:        }
                   1752:        else {
                   1753:                /* Neither argument is immediate. */
                   1754:                if (ADDRESSING_DEPENDS_ON(src2, dst_r))
                   1755:                        dst_r = TMP_REGISTER;
                   1756:                EMIT_MOV(compiler, dst_r, 0, src1, src1w);
1.1.1.4 ! misho    1757:                inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w);
        !          1758:                FAIL_IF(!inst);
        !          1759:                *inst++ = GROUP_0F;
        !          1760:                *inst = IMUL_r_rm;
1.1       misho    1761:        }
                   1762: 
                   1763:        if (dst_r == TMP_REGISTER)
                   1764:                EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   1765: 
                   1766:        return SLJIT_SUCCESS;
                   1767: }
                   1768: 
1.1.1.4 ! misho    1769: static sljit_si emit_lea_binary(struct sljit_compiler *compiler, sljit_si keep_flags,
        !          1770:        sljit_si dst, sljit_sw dstw,
        !          1771:        sljit_si src1, sljit_sw src1w,
        !          1772:        sljit_si src2, sljit_sw src2w)
1.1       misho    1773: {
1.1.1.4 ! misho    1774:        sljit_ub* inst;
        !          1775:        sljit_si dst_r, done = 0;
1.1       misho    1776: 
                   1777:        /* These cases better be left to handled by normal way. */
1.1.1.4 ! misho    1778:        if (!keep_flags) {
        !          1779:                if (dst == src1 && dstw == src1w)
        !          1780:                        return SLJIT_ERR_UNSUPPORTED;
        !          1781:                if (dst == src2 && dstw == src2w)
        !          1782:                        return SLJIT_ERR_UNSUPPORTED;
        !          1783:        }
        !          1784: 
        !          1785:        dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
        !          1786: 
        !          1787:        if (src1 <= TMP_REGISTER) {
        !          1788:                if (src2 <= TMP_REGISTER || src2 == TMP_REGISTER) {
        !          1789:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
        !          1790:                        FAIL_IF(!inst);
        !          1791:                        *inst = LEA_r_m;
1.1.1.3   misho    1792:                        done = 1;
1.1       misho    1793:                }
                   1794: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1795:                if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) {
1.1.1.4 ! misho    1796:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_si)src2w);
1.1       misho    1797: #else
                   1798:                if (src2 & SLJIT_IMM) {
1.1.1.4 ! misho    1799:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
1.1       misho    1800: #endif
1.1.1.4 ! misho    1801:                        FAIL_IF(!inst);
        !          1802:                        *inst = LEA_r_m;
1.1       misho    1803:                        done = 1;
                   1804:                }
                   1805:        }
1.1.1.4 ! misho    1806:        else if (src2 <= TMP_REGISTER) {
1.1       misho    1807: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1808:                if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) {
1.1.1.4 ! misho    1809:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_si)src1w);
1.1       misho    1810: #else
                   1811:                if (src1 & SLJIT_IMM) {
1.1.1.4 ! misho    1812:                        inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
1.1       misho    1813: #endif
1.1.1.4 ! misho    1814:                        FAIL_IF(!inst);
        !          1815:                        *inst = LEA_r_m;
1.1       misho    1816:                        done = 1;
                   1817:                }
                   1818:        }
                   1819: 
                   1820:        if (done) {
                   1821:                if (dst_r == TMP_REGISTER)
                   1822:                        return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
                   1823:                return SLJIT_SUCCESS;
                   1824:        }
                   1825:        return SLJIT_ERR_UNSUPPORTED;
                   1826: }
                   1827: 
1.1.1.4 ! misho    1828: static sljit_si emit_cmp_binary(struct sljit_compiler *compiler,
        !          1829:        sljit_si src1, sljit_sw src1w,
        !          1830:        sljit_si src2, sljit_sw src2w)
1.1       misho    1831: {
1.1.1.4 ! misho    1832:        sljit_ub* inst;
1.1       misho    1833: 
                   1834: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1835:        if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
1.1       misho    1836: #else
1.1.1.4 ! misho    1837:        if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
1.1       misho    1838: #endif
1.1.1.4 ! misho    1839:                BINARY_EAX_IMM(CMP_EAX_i32, src2w);
1.1       misho    1840:                return SLJIT_SUCCESS;
                   1841:        }
                   1842: 
1.1.1.4 ! misho    1843:        if (src1 <= TMP_REGISTER) {
1.1       misho    1844:                if (src2 & SLJIT_IMM) {
1.1.1.4 ! misho    1845:                        BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);
1.1       misho    1846:                }
                   1847:                else {
1.1.1.4 ! misho    1848:                        inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
        !          1849:                        FAIL_IF(!inst);
        !          1850:                        *inst = CMP_r_rm;
1.1       misho    1851:                }
                   1852:                return SLJIT_SUCCESS;
                   1853:        }
                   1854: 
1.1.1.4 ! misho    1855:        if (src2 <= TMP_REGISTER && !(src1 & SLJIT_IMM)) {
        !          1856:                inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
        !          1857:                FAIL_IF(!inst);
        !          1858:                *inst = CMP_rm_r;
1.1       misho    1859:                return SLJIT_SUCCESS;
                   1860:        }
                   1861: 
                   1862:        if (src2 & SLJIT_IMM) {
                   1863:                if (src1 & SLJIT_IMM) {
                   1864:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1865:                        src1 = TMP_REGISTER;
                   1866:                        src1w = 0;
                   1867:                }
1.1.1.4 ! misho    1868:                BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);
1.1       misho    1869:        }
                   1870:        else {
                   1871:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1.1.4 ! misho    1872:                inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1873:                FAIL_IF(!inst);
        !          1874:                *inst = CMP_r_rm;
1.1       misho    1875:        }
                   1876:        return SLJIT_SUCCESS;
                   1877: }
                   1878: 
1.1.1.4 ! misho    1879: static sljit_si emit_test_binary(struct sljit_compiler *compiler,
        !          1880:        sljit_si src1, sljit_sw src1w,
        !          1881:        sljit_si src2, sljit_sw src2w)
1.1       misho    1882: {
1.1.1.4 ! misho    1883:        sljit_ub* inst;
1.1       misho    1884: 
                   1885: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1886:        if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
1.1       misho    1887: #else
1.1.1.4 ! misho    1888:        if (src1 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) {
1.1       misho    1889: #endif
1.1.1.4 ! misho    1890:                BINARY_EAX_IMM(TEST_EAX_i32, src2w);
1.1       misho    1891:                return SLJIT_SUCCESS;
                   1892:        }
                   1893: 
                   1894: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    1895:        if (src2 == SLJIT_SCRATCH_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
1.1       misho    1896: #else
1.1.1.4 ! misho    1897:        if (src2 == SLJIT_SCRATCH_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) {
1.1       misho    1898: #endif
1.1.1.4 ! misho    1899:                BINARY_EAX_IMM(TEST_EAX_i32, src1w);
1.1       misho    1900:                return SLJIT_SUCCESS;
                   1901:        }
                   1902: 
1.1.1.4 ! misho    1903:        if (src1 <= TMP_REGISTER) {
1.1       misho    1904:                if (src2 & SLJIT_IMM) {
                   1905: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1906:                        if (IS_HALFWORD(src2w) || compiler->mode32) {
1.1.1.4 ! misho    1907:                                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
        !          1908:                                FAIL_IF(!inst);
        !          1909:                                *inst = GROUP_F7;
1.1       misho    1910:                        }
                   1911:                        else {
                   1912:                                FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
1.1.1.4 ! misho    1913:                                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
        !          1914:                                FAIL_IF(!inst);
        !          1915:                                *inst = TEST_rm_r;
1.1       misho    1916:                        }
                   1917: #else
1.1.1.4 ! misho    1918:                        inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
        !          1919:                        FAIL_IF(!inst);
        !          1920:                        *inst = GROUP_F7;
1.1       misho    1921: #endif
                   1922:                }
                   1923:                else {
1.1.1.4 ! misho    1924:                        inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
        !          1925:                        FAIL_IF(!inst);
        !          1926:                        *inst = TEST_rm_r;
1.1       misho    1927:                }
                   1928:                return SLJIT_SUCCESS;
                   1929:        }
                   1930: 
1.1.1.4 ! misho    1931:        if (src2 <= TMP_REGISTER) {
1.1       misho    1932:                if (src1 & SLJIT_IMM) {
                   1933: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1934:                        if (IS_HALFWORD(src1w) || compiler->mode32) {
1.1.1.4 ! misho    1935:                                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
        !          1936:                                FAIL_IF(!inst);
        !          1937:                                *inst = GROUP_F7;
1.1       misho    1938:                        }
                   1939:                        else {
                   1940:                                FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
1.1.1.4 ! misho    1941:                                inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
        !          1942:                                FAIL_IF(!inst);
        !          1943:                                *inst = TEST_rm_r;
1.1       misho    1944:                        }
                   1945: #else
1.1.1.4 ! misho    1946:                        inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
        !          1947:                        FAIL_IF(!inst);
        !          1948:                        *inst = GROUP_F7;
1.1       misho    1949: #endif
                   1950:                }
                   1951:                else {
1.1.1.4 ! misho    1952:                        inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
        !          1953:                        FAIL_IF(!inst);
        !          1954:                        *inst = TEST_rm_r;
1.1       misho    1955:                }
                   1956:                return SLJIT_SUCCESS;
                   1957:        }
                   1958: 
                   1959:        EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   1960:        if (src2 & SLJIT_IMM) {
                   1961: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   1962:                if (IS_HALFWORD(src2w) || compiler->mode32) {
1.1.1.4 ! misho    1963:                        inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
        !          1964:                        FAIL_IF(!inst);
        !          1965:                        *inst = GROUP_F7;
1.1       misho    1966:                }
                   1967:                else {
                   1968:                        FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
1.1.1.4 ! misho    1969:                        inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0);
        !          1970:                        FAIL_IF(!inst);
        !          1971:                        *inst = TEST_rm_r;
1.1       misho    1972:                }
                   1973: #else
1.1.1.4 ! misho    1974:                inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0);
        !          1975:                FAIL_IF(!inst);
        !          1976:                *inst = GROUP_F7;
1.1       misho    1977: #endif
                   1978:        }
                   1979:        else {
1.1.1.4 ! misho    1980:                inst = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w);
        !          1981:                FAIL_IF(!inst);
        !          1982:                *inst = TEST_rm_r;
1.1       misho    1983:        }
                   1984:        return SLJIT_SUCCESS;
                   1985: }
                   1986: 
1.1.1.4 ! misho    1987: static sljit_si emit_shift(struct sljit_compiler *compiler,
1.1       misho    1988:        sljit_ub mode,
1.1.1.4 ! misho    1989:        sljit_si dst, sljit_sw dstw,
        !          1990:        sljit_si src1, sljit_sw src1w,
        !          1991:        sljit_si src2, sljit_sw src2w)
1.1       misho    1992: {
1.1.1.4 ! misho    1993:        sljit_ub* inst;
1.1       misho    1994: 
                   1995:        if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) {
                   1996:                if (dst == src1 && dstw == src1w) {
1.1.1.4 ! misho    1997:                        inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);
        !          1998:                        FAIL_IF(!inst);
        !          1999:                        *inst |= mode;
1.1       misho    2000:                        return SLJIT_SUCCESS;
                   2001:                }
                   2002:                if (dst == SLJIT_UNUSED) {
                   2003:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1.1.4 ! misho    2004:                        inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
        !          2005:                        FAIL_IF(!inst);
        !          2006:                        *inst |= mode;
1.1       misho    2007:                        return SLJIT_SUCCESS;
                   2008:                }
                   2009:                if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
                   2010:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1.1.4 ! misho    2011:                        inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
        !          2012:                        FAIL_IF(!inst);
        !          2013:                        *inst |= mode;
1.1       misho    2014:                        EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
                   2015:                        return SLJIT_SUCCESS;
                   2016:                }
1.1.1.4 ! misho    2017:                if (dst <= TMP_REGISTER) {
1.1       misho    2018:                        EMIT_MOV(compiler, dst, 0, src1, src1w);
1.1.1.4 ! misho    2019:                        inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
        !          2020:                        FAIL_IF(!inst);
        !          2021:                        *inst |= mode;
1.1       misho    2022:                        return SLJIT_SUCCESS;
                   2023:                }
                   2024: 
                   2025:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1.1.4 ! misho    2026:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0);
        !          2027:                FAIL_IF(!inst);
        !          2028:                *inst |= mode;
1.1       misho    2029:                EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   2030:                return SLJIT_SUCCESS;
                   2031:        }
                   2032: 
                   2033:        if (dst == SLJIT_PREF_SHIFT_REG) {
                   2034:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
                   2035:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
1.1.1.4 ! misho    2036:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
        !          2037:                FAIL_IF(!inst);
        !          2038:                *inst |= mode;
1.1       misho    2039:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
                   2040:        }
1.1.1.4 ! misho    2041:        else if (dst <= TMP_REGISTER && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
1.1       misho    2042:                if (src1 != dst)
                   2043:                        EMIT_MOV(compiler, dst, 0, src1, src1w);
                   2044:                EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_PREF_SHIFT_REG, 0);
                   2045:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
1.1.1.4 ! misho    2046:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
        !          2047:                FAIL_IF(!inst);
        !          2048:                *inst |= mode;
1.1       misho    2049:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
                   2050:        }
                   2051:        else {
1.1.1.2   misho    2052:                /* This case is really difficult, since ecx itself may used for
                   2053:                   addressing, and we must ensure to work even in that case. */
                   2054:                EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w);
1.1       misho    2055: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2056:                EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
                   2057: #else
1.1.1.3   misho    2058:                /* [esp+0] contains the flags. */
1.1.1.4 ! misho    2059:                EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0);
1.1       misho    2060: #endif
                   2061:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
1.1.1.4 ! misho    2062:                inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0);
        !          2063:                FAIL_IF(!inst);
        !          2064:                *inst |= mode;
1.1       misho    2065: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2066:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
                   2067: #else
1.1.1.4 ! misho    2068:                EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_sw));
1.1       misho    2069: #endif
                   2070:                EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0);
                   2071:        }
                   2072: 
                   2073:        return SLJIT_SUCCESS;
                   2074: }
                   2075: 
1.1.1.4 ! misho    2076: static sljit_si emit_shift_with_flags(struct sljit_compiler *compiler,
        !          2077:        sljit_ub mode, sljit_si set_flags,
        !          2078:        sljit_si dst, sljit_sw dstw,
        !          2079:        sljit_si src1, sljit_sw src1w,
        !          2080:        sljit_si src2, sljit_sw src2w)
1.1.1.2   misho    2081: {
                   2082:        /* The CPU does not set flags if the shift count is 0. */
                   2083:        if (src2 & SLJIT_IMM) {
                   2084: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2085:                if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0))
                   2086:                        return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
                   2087: #else
                   2088:                if ((src2w & 0x1f) != 0)
                   2089:                        return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
                   2090: #endif
                   2091:                if (!set_flags)
                   2092:                        return emit_mov(compiler, dst, dstw, src1, src1w);
                   2093:                /* OR dst, src, 0 */
1.1.1.4 ! misho    2094:                return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
1.1.1.2   misho    2095:                        dst, dstw, src1, src1w, SLJIT_IMM, 0);
                   2096:        }
                   2097: 
                   2098:        if (!set_flags)
                   2099:                return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
                   2100: 
1.1.1.4 ! misho    2101:        if (!(dst <= TMP_REGISTER))
1.1.1.2   misho    2102:                FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
                   2103: 
                   2104:        FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w));
                   2105: 
1.1.1.4 ! misho    2106:        if (dst <= TMP_REGISTER)
1.1.1.2   misho    2107:                return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
                   2108:        return SLJIT_SUCCESS;
                   2109: }
                   2110: 
1.1.1.4 ! misho    2111: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
        !          2112:        sljit_si dst, sljit_sw dstw,
        !          2113:        sljit_si src1, sljit_sw src1w,
        !          2114:        sljit_si src2, sljit_sw src2w)
1.1       misho    2115: {
                   2116:        CHECK_ERROR();
                   2117:        check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
1.1.1.3   misho    2118:        ADJUST_LOCAL_OFFSET(dst, dstw);
                   2119:        ADJUST_LOCAL_OFFSET(src1, src1w);
                   2120:        ADJUST_LOCAL_OFFSET(src2, src2w);
1.1       misho    2121: 
                   2122:        CHECK_EXTRA_REGS(dst, dstw, (void)0);
                   2123:        CHECK_EXTRA_REGS(src1, src1w, (void)0);
                   2124:        CHECK_EXTRA_REGS(src2, src2w, (void)0);
1.1.1.3   misho    2125: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2126:        compiler->mode32 = op & SLJIT_INT_OP;
                   2127: #endif
1.1       misho    2128: 
                   2129:        if (GET_OPCODE(op) >= SLJIT_MUL) {
                   2130:                if (SLJIT_UNLIKELY(GET_FLAGS(op)))
                   2131:                        compiler->flags_saved = 0;
                   2132:                else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
                   2133:                        FAIL_IF(emit_save_flags(compiler));
                   2134:        }
                   2135: 
                   2136:        switch (GET_OPCODE(op)) {
                   2137:        case SLJIT_ADD:
                   2138:                if (!GET_FLAGS(op)) {
1.1.1.4 ! misho    2139:                        if (emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
1.1       misho    2140:                                return compiler->error;
1.1.1.3   misho    2141:                }
1.1       misho    2142:                else
                   2143:                        compiler->flags_saved = 0;
                   2144:                if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
                   2145:                        FAIL_IF(emit_save_flags(compiler));
1.1.1.4 ! misho    2146:                return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
1.1       misho    2147:                        dst, dstw, src1, src1w, src2, src2w);
                   2148:        case SLJIT_ADDC:
                   2149:                if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
                   2150:                        FAIL_IF(emit_restore_flags(compiler, 1));
                   2151:                else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
                   2152:                        FAIL_IF(emit_save_flags(compiler));
                   2153:                if (SLJIT_UNLIKELY(GET_FLAGS(op)))
                   2154:                        compiler->flags_saved = 0;
1.1.1.4 ! misho    2155:                return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32,
1.1       misho    2156:                        dst, dstw, src1, src1w, src2, src2w);
                   2157:        case SLJIT_SUB:
                   2158:                if (!GET_FLAGS(op)) {
1.1.1.4 ! misho    2159:                        if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
1.1       misho    2160:                                return compiler->error;
                   2161:                }
                   2162:                else
                   2163:                        compiler->flags_saved = 0;
                   2164:                if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved)
                   2165:                        FAIL_IF(emit_save_flags(compiler));
                   2166:                if (dst == SLJIT_UNUSED)
                   2167:                        return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
1.1.1.4 ! misho    2168:                return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
1.1       misho    2169:                        dst, dstw, src1, src1w, src2, src2w);
                   2170:        case SLJIT_SUBC:
                   2171:                if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */
                   2172:                        FAIL_IF(emit_restore_flags(compiler, 1));
                   2173:                else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS))
                   2174:                        FAIL_IF(emit_save_flags(compiler));
                   2175:                if (SLJIT_UNLIKELY(GET_FLAGS(op)))
                   2176:                        compiler->flags_saved = 0;
1.1.1.4 ! misho    2177:                return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32,
1.1       misho    2178:                        dst, dstw, src1, src1w, src2, src2w);
                   2179:        case SLJIT_MUL:
                   2180:                return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
                   2181:        case SLJIT_AND:
                   2182:                if (dst == SLJIT_UNUSED)
                   2183:                        return emit_test_binary(compiler, src1, src1w, src2, src2w);
1.1.1.4 ! misho    2184:                return emit_cum_binary(compiler, AND_r_rm, AND_rm_r, AND, AND_EAX_i32,
1.1       misho    2185:                        dst, dstw, src1, src1w, src2, src2w);
                   2186:        case SLJIT_OR:
1.1.1.4 ! misho    2187:                return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32,
1.1       misho    2188:                        dst, dstw, src1, src1w, src2, src2w);
                   2189:        case SLJIT_XOR:
1.1.1.4 ! misho    2190:                return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32,
1.1       misho    2191:                        dst, dstw, src1, src1w, src2, src2w);
                   2192:        case SLJIT_SHL:
1.1.1.4 ! misho    2193:                return emit_shift_with_flags(compiler, SHL, GET_FLAGS(op),
1.1       misho    2194:                        dst, dstw, src1, src1w, src2, src2w);
                   2195:        case SLJIT_LSHR:
1.1.1.4 ! misho    2196:                return emit_shift_with_flags(compiler, SHR, GET_FLAGS(op),
1.1       misho    2197:                        dst, dstw, src1, src1w, src2, src2w);
                   2198:        case SLJIT_ASHR:
1.1.1.4 ! misho    2199:                return emit_shift_with_flags(compiler, SAR, GET_FLAGS(op),
1.1       misho    2200:                        dst, dstw, src1, src1w, src2, src2w);
                   2201:        }
                   2202: 
                   2203:        return SLJIT_SUCCESS;
                   2204: }
                   2205: 
1.1.1.4 ! misho    2206: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
1.1.1.2   misho    2207: {
                   2208:        check_sljit_get_register_index(reg);
                   2209: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   2210:        if (reg == SLJIT_TEMPORARY_EREG1 || reg == SLJIT_TEMPORARY_EREG2
                   2211:                        || reg == SLJIT_SAVED_EREG1 || reg == SLJIT_SAVED_EREG2)
                   2212:                return -1;
                   2213: #endif
                   2214:        return reg_map[reg];
                   2215: }
                   2216: 
1.1.1.4 ! misho    2217: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg)
        !          2218: {
        !          2219:        check_sljit_get_float_register_index(reg);
        !          2220:        return reg;
        !          2221: }
        !          2222: 
        !          2223: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
        !          2224:        void *instruction, sljit_si size)
1.1.1.2   misho    2225: {
1.1.1.4 ! misho    2226:        sljit_ub *inst;
1.1.1.2   misho    2227: 
                   2228:        CHECK_ERROR();
                   2229:        check_sljit_emit_op_custom(compiler, instruction, size);
                   2230:        SLJIT_ASSERT(size > 0 && size < 16);
                   2231: 
1.1.1.4 ! misho    2232:        inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
        !          2233:        FAIL_IF(!inst);
1.1.1.2   misho    2234:        INC_SIZE(size);
1.1.1.4 ! misho    2235:        SLJIT_MEMMOVE(inst, instruction, size);
1.1.1.2   misho    2236:        return SLJIT_SUCCESS;
                   2237: }
                   2238: 
1.1       misho    2239: /* --------------------------------------------------------------------- */
                   2240: /*  Floating point operators                                             */
                   2241: /* --------------------------------------------------------------------- */
                   2242: 
                   2243: #if (defined SLJIT_SSE2 && SLJIT_SSE2)
                   2244: 
                   2245: /* Alignment + 2 * 16 bytes. */
1.1.1.4 ! misho    2246: static sljit_si sse2_data[3 + (4 + 4) * 2];
        !          2247: static sljit_si *sse2_buffer;
1.1       misho    2248: 
1.1.1.4 ! misho    2249: static void init_compiler(void)
1.1       misho    2250: {
1.1.1.4 ! misho    2251:        sse2_buffer = (sljit_si*)(((sljit_uw)sse2_data + 15) & ~0xf);
        !          2252:        /* Single precision constants. */
        !          2253:        sse2_buffer[0] = 0x80000000;
        !          2254:        sse2_buffer[4] = 0x7fffffff;
        !          2255:        /* Double precision constants. */
        !          2256:        sse2_buffer[8] = 0;
        !          2257:        sse2_buffer[9] = 0x80000000;
        !          2258:        sse2_buffer[12] = 0xffffffff;
        !          2259:        sse2_buffer[13] = 0x7fffffff;
1.1.1.3   misho    2260: }
                   2261: 
                   2262: #endif
                   2263: 
1.1.1.4 ! misho    2264: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
1.1.1.3   misho    2265: {
                   2266: #if (defined SLJIT_SSE2 && SLJIT_SSE2)
                   2267: #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
1.1.1.4 ! misho    2268:        if (cpu_has_sse2 == -1)
        !          2269:                get_cpu_features();
        !          2270:        return cpu_has_sse2;
        !          2271: #else /* SLJIT_DETECT_SSE2 */
1.1.1.3   misho    2272:        return 1;
1.1.1.4 ! misho    2273: #endif /* SLJIT_DETECT_SSE2 */
        !          2274: #else /* SLJIT_SSE2 */
1.1.1.3   misho    2275:        return 0;
1.1       misho    2276: #endif
                   2277: }
                   2278: 
                   2279: #if (defined SLJIT_SSE2 && SLJIT_SSE2)
                   2280: 
1.1.1.4 ! misho    2281: static sljit_si emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode,
        !          2282:        sljit_si single, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
1.1       misho    2283: {
1.1.1.4 ! misho    2284:        sljit_ub *inst;
1.1       misho    2285: 
1.1.1.4 ! misho    2286:        inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
        !          2287:        FAIL_IF(!inst);
        !          2288:        *inst++ = GROUP_0F;
        !          2289:        *inst = opcode;
1.1       misho    2290:        return SLJIT_SUCCESS;
                   2291: }
                   2292: 
1.1.1.4 ! misho    2293: static sljit_si emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode,
        !          2294:        sljit_si pref66, sljit_si xmm1, sljit_si xmm2, sljit_sw xmm2w)
1.1       misho    2295: {
1.1.1.4 ! misho    2296:        sljit_ub *inst;
1.1       misho    2297: 
1.1.1.4 ! misho    2298:        inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w);
        !          2299:        FAIL_IF(!inst);
        !          2300:        *inst++ = GROUP_0F;
        !          2301:        *inst = opcode;
1.1       misho    2302:        return SLJIT_SUCCESS;
                   2303: }
                   2304: 
1.1.1.4 ! misho    2305: static SLJIT_INLINE sljit_si emit_sse2_load(struct sljit_compiler *compiler,
        !          2306:        sljit_si single, sljit_si dst, sljit_si src, sljit_sw srcw)
1.1       misho    2307: {
1.1.1.4 ! misho    2308:        return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw);
1.1       misho    2309: }
                   2310: 
1.1.1.4 ! misho    2311: static SLJIT_INLINE sljit_si emit_sse2_store(struct sljit_compiler *compiler,
        !          2312:        sljit_si single, sljit_si dst, sljit_sw dstw, sljit_si src)
1.1       misho    2313: {
1.1.1.4 ! misho    2314:        return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw);
1.1       misho    2315: }
                   2316: 
1.1.1.4 ! misho    2317: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
        !          2318:        sljit_si dst, sljit_sw dstw,
        !          2319:        sljit_si src, sljit_sw srcw)
1.1       misho    2320: {
1.1.1.4 ! misho    2321:        sljit_si dst_r;
1.1       misho    2322: 
                   2323:        CHECK_ERROR();
                   2324:        check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
                   2325: 
                   2326: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2327:        compiler->mode32 = 1;
                   2328: #endif
                   2329: 
1.1.1.4 ! misho    2330:        if (GET_OPCODE(op) == SLJIT_CMPD) {
1.1       misho    2331:                compiler->flags_saved = 0;
1.1.1.4 ! misho    2332:                if (dst <= SLJIT_FLOAT_REG6)
1.1       misho    2333:                        dst_r = dst;
                   2334:                else {
                   2335:                        dst_r = TMP_FREG;
1.1.1.4 ! misho    2336:                        FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, dst, dstw));
1.1       misho    2337:                }
1.1.1.4 ! misho    2338:                return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_SINGLE_OP), dst_r, src, srcw);
1.1       misho    2339:        }
                   2340: 
1.1.1.4 ! misho    2341:        if (op == SLJIT_MOVD) {
        !          2342:                if (dst <= SLJIT_FLOAT_REG6)
        !          2343:                        return emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst, src, srcw);
        !          2344:                if (src <= SLJIT_FLOAT_REG6)
        !          2345:                        return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, src);
        !          2346:                FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src, srcw));
        !          2347:                return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
1.1       misho    2348:        }
                   2349: 
1.1.1.4 ! misho    2350:        if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG6) {
1.1       misho    2351:                dst_r = dst;
                   2352:                if (dst != src)
1.1.1.4 ! misho    2353:                        FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
1.1       misho    2354:        }
                   2355:        else {
                   2356:                dst_r = TMP_FREG;
1.1.1.4 ! misho    2357:                FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src, srcw));
1.1       misho    2358:        }
                   2359: 
1.1.1.4 ! misho    2360:        switch (GET_OPCODE(op)) {
        !          2361:        case SLJIT_NEGD:
        !          2362:                FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer : sse2_buffer + 8)));
1.1       misho    2363:                break;
                   2364: 
1.1.1.4 ! misho    2365:        case SLJIT_ABSD:
        !          2366:                FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_SINGLE_OP ? sse2_buffer + 4 : sse2_buffer + 12)));
1.1       misho    2367:                break;
                   2368:        }
                   2369: 
                   2370:        if (dst_r == TMP_FREG)
1.1.1.4 ! misho    2371:                return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
1.1       misho    2372:        return SLJIT_SUCCESS;
                   2373: }
                   2374: 
1.1.1.4 ! misho    2375: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
        !          2376:        sljit_si dst, sljit_sw dstw,
        !          2377:        sljit_si src1, sljit_sw src1w,
        !          2378:        sljit_si src2, sljit_sw src2w)
1.1       misho    2379: {
1.1.1.4 ! misho    2380:        sljit_si dst_r;
1.1       misho    2381: 
                   2382:        CHECK_ERROR();
                   2383:        check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
                   2384: 
                   2385: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2386:        compiler->mode32 = 1;
                   2387: #endif
                   2388: 
1.1.1.4 ! misho    2389:        if (dst <= SLJIT_FLOAT_REG6) {
1.1       misho    2390:                dst_r = dst;
                   2391:                if (dst == src1)
                   2392:                        ; /* Do nothing here. */
1.1.1.4 ! misho    2393:                else if (dst == src2 && (op == SLJIT_ADDD || op == SLJIT_MULD)) {
1.1       misho    2394:                        /* Swap arguments. */
                   2395:                        src2 = src1;
                   2396:                        src2w = src1w;
                   2397:                }
                   2398:                else if (dst != src2)
1.1.1.4 ! misho    2399:                        FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, dst_r, src1, src1w));
1.1       misho    2400:                else {
                   2401:                        dst_r = TMP_FREG;
1.1.1.4 ! misho    2402:                        FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
1.1       misho    2403:                }
                   2404:        }
                   2405:        else {
                   2406:                dst_r = TMP_FREG;
1.1.1.4 ! misho    2407:                FAIL_IF(emit_sse2_load(compiler, op & SLJIT_SINGLE_OP, TMP_FREG, src1, src1w));
1.1       misho    2408:        }
                   2409: 
1.1.1.4 ! misho    2410:        switch (GET_OPCODE(op)) {
        !          2411:        case SLJIT_ADDD:
        !          2412:                FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
1.1       misho    2413:                break;
                   2414: 
1.1.1.4 ! misho    2415:        case SLJIT_SUBD:
        !          2416:                FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
1.1       misho    2417:                break;
                   2418: 
1.1.1.4 ! misho    2419:        case SLJIT_MULD:
        !          2420:                FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
1.1       misho    2421:                break;
                   2422: 
1.1.1.4 ! misho    2423:        case SLJIT_DIVD:
        !          2424:                FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_SINGLE_OP, dst_r, src2, src2w));
1.1       misho    2425:                break;
                   2426:        }
                   2427: 
                   2428:        if (dst_r == TMP_FREG)
1.1.1.4 ! misho    2429:                return emit_sse2_store(compiler, op & SLJIT_SINGLE_OP, dst, dstw, TMP_FREG);
1.1       misho    2430:        return SLJIT_SUCCESS;
                   2431: }
                   2432: 
1.1.1.3   misho    2433: #else
1.1       misho    2434: 
1.1.1.4 ! misho    2435: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
        !          2436:        sljit_si dst, sljit_sw dstw,
        !          2437:        sljit_si src, sljit_sw srcw)
1.1       misho    2438: {
                   2439:        CHECK_ERROR();
1.1.1.3   misho    2440:        /* Should cause an assertion fail. */
1.1       misho    2441:        check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw);
1.1.1.3   misho    2442:        compiler->error = SLJIT_ERR_UNSUPPORTED;
                   2443:        return SLJIT_ERR_UNSUPPORTED;
1.1       misho    2444: }
                   2445: 
1.1.1.4 ! misho    2446: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
        !          2447:        sljit_si dst, sljit_sw dstw,
        !          2448:        sljit_si src1, sljit_sw src1w,
        !          2449:        sljit_si src2, sljit_sw src2w)
1.1       misho    2450: {
                   2451:        CHECK_ERROR();
1.1.1.3   misho    2452:        /* Should cause an assertion fail. */
1.1       misho    2453:        check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
1.1.1.3   misho    2454:        compiler->error = SLJIT_ERR_UNSUPPORTED;
                   2455:        return SLJIT_ERR_UNSUPPORTED;
1.1       misho    2456: }
                   2457: 
                   2458: #endif
                   2459: 
                   2460: /* --------------------------------------------------------------------- */
                   2461: /*  Conditional instructions                                             */
                   2462: /* --------------------------------------------------------------------- */
                   2463: 
                   2464: SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
                   2465: {
1.1.1.4 ! misho    2466:        sljit_ub *inst;
1.1       misho    2467:        struct sljit_label *label;
                   2468: 
                   2469:        CHECK_ERROR_PTR();
                   2470:        check_sljit_emit_label(compiler);
                   2471: 
                   2472:        /* We should restore the flags before the label,
                   2473:           since other taken jumps has their own flags as well. */
                   2474:        if (SLJIT_UNLIKELY(compiler->flags_saved))
                   2475:                PTR_FAIL_IF(emit_restore_flags(compiler, 0));
                   2476: 
                   2477:        if (compiler->last_label && compiler->last_label->size == compiler->size)
                   2478:                return compiler->last_label;
                   2479: 
                   2480:        label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
                   2481:        PTR_FAIL_IF(!label);
                   2482:        set_label(label, compiler);
                   2483: 
1.1.1.4 ! misho    2484:        inst = (sljit_ub*)ensure_buf(compiler, 2);
        !          2485:        PTR_FAIL_IF(!inst);
1.1       misho    2486: 
1.1.1.4 ! misho    2487:        *inst++ = 0;
        !          2488:        *inst++ = 0;
1.1       misho    2489: 
                   2490:        return label;
                   2491: }
                   2492: 
1.1.1.4 ! misho    2493: SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
1.1       misho    2494: {
1.1.1.4 ! misho    2495:        sljit_ub *inst;
1.1       misho    2496:        struct sljit_jump *jump;
                   2497: 
                   2498:        CHECK_ERROR_PTR();
                   2499:        check_sljit_emit_jump(compiler, type);
                   2500: 
                   2501:        if (SLJIT_UNLIKELY(compiler->flags_saved)) {
                   2502:                if ((type & 0xff) <= SLJIT_JUMP)
                   2503:                        PTR_FAIL_IF(emit_restore_flags(compiler, 0));
                   2504:                compiler->flags_saved = 0;
                   2505:        }
                   2506: 
                   2507:        jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
                   2508:        PTR_FAIL_IF_NULL(jump);
                   2509:        set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
                   2510:        type &= 0xff;
                   2511: 
                   2512:        if (type >= SLJIT_CALL1)
                   2513:                PTR_FAIL_IF(call_with_args(compiler, type));
                   2514: 
                   2515:        /* Worst case size. */
                   2516: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   2517:        compiler->size += (type >= SLJIT_JUMP) ? 5 : 6;
                   2518: #else
                   2519:        compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3);
                   2520: #endif
                   2521: 
1.1.1.4 ! misho    2522:        inst = (sljit_ub*)ensure_buf(compiler, 2);
        !          2523:        PTR_FAIL_IF_NULL(inst);
1.1       misho    2524: 
1.1.1.4 ! misho    2525:        *inst++ = 0;
        !          2526:        *inst++ = type + 4;
1.1       misho    2527:        return jump;
                   2528: }
                   2529: 
1.1.1.4 ! misho    2530: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw)
1.1       misho    2531: {
1.1.1.4 ! misho    2532:        sljit_ub *inst;
1.1       misho    2533:        struct sljit_jump *jump;
                   2534: 
                   2535:        CHECK_ERROR();
                   2536:        check_sljit_emit_ijump(compiler, type, src, srcw);
1.1.1.3   misho    2537:        ADJUST_LOCAL_OFFSET(src, srcw);
1.1       misho    2538: 
                   2539:        CHECK_EXTRA_REGS(src, srcw, (void)0);
1.1.1.3   misho    2540: 
1.1       misho    2541:        if (SLJIT_UNLIKELY(compiler->flags_saved)) {
                   2542:                if (type <= SLJIT_JUMP)
                   2543:                        FAIL_IF(emit_restore_flags(compiler, 0));
                   2544:                compiler->flags_saved = 0;
                   2545:        }
                   2546: 
                   2547:        if (type >= SLJIT_CALL1) {
                   2548: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   2549: #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
1.1.1.4 ! misho    2550:                if (src == SLJIT_SCRATCH_REG3) {
1.1       misho    2551:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
                   2552:                        src = TMP_REGISTER;
                   2553:                }
1.1.1.3   misho    2554:                if (src == SLJIT_MEM1(SLJIT_LOCALS_REG) && type >= SLJIT_CALL3)
1.1.1.4 ! misho    2555:                        srcw += sizeof(sljit_sw);
1.1       misho    2556: #endif
                   2557: #endif
                   2558: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
1.1.1.4 ! misho    2559:                if (src == SLJIT_SCRATCH_REG3) {
1.1       misho    2560:                        EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0);
                   2561:                        src = TMP_REGISTER;
                   2562:                }
                   2563: #endif
                   2564:                FAIL_IF(call_with_args(compiler, type));
                   2565:        }
                   2566: 
                   2567:        if (src == SLJIT_IMM) {
                   2568:                jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
                   2569:                FAIL_IF_NULL(jump);
                   2570:                set_jump(jump, compiler, JUMP_ADDR);
                   2571:                jump->u.target = srcw;
                   2572: 
                   2573:                /* Worst case size. */
                   2574: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
                   2575:                compiler->size += 5;
                   2576: #else
                   2577:                compiler->size += 10 + 3;
                   2578: #endif
                   2579: 
1.1.1.4 ! misho    2580:                inst = (sljit_ub*)ensure_buf(compiler, 2);
        !          2581:                FAIL_IF_NULL(inst);
1.1       misho    2582: 
1.1.1.4 ! misho    2583:                *inst++ = 0;
        !          2584:                *inst++ = type + 4;
1.1       misho    2585:        }
                   2586:        else {
                   2587: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2588:                /* REX_W is not necessary (src is not immediate). */
                   2589:                compiler->mode32 = 1;
                   2590: #endif
1.1.1.4 ! misho    2591:                inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
        !          2592:                FAIL_IF(!inst);
        !          2593:                *inst++ = GROUP_FF;
        !          2594:                *inst |= (type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm;
1.1       misho    2595:        }
                   2596:        return SLJIT_SUCCESS;
                   2597: }
                   2598: 
1.1.1.4 ! misho    2599: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
        !          2600:        sljit_si dst, sljit_sw dstw,
        !          2601:        sljit_si src, sljit_sw srcw,
        !          2602:        sljit_si type)
1.1       misho    2603: {
1.1.1.4 ! misho    2604:        sljit_ub *inst;
1.1       misho    2605:        sljit_ub cond_set = 0;
                   2606: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    2607:        sljit_si reg;
        !          2608: #else
        !          2609:        /* CHECK_EXTRA_REGS migh overwrite these values. */
        !          2610:        sljit_si dst_save = dst;
        !          2611:        sljit_sw dstw_save = dstw;
1.1       misho    2612: #endif
                   2613: 
                   2614:        CHECK_ERROR();
1.1.1.4 ! misho    2615:        check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
1.1       misho    2616: 
                   2617:        if (dst == SLJIT_UNUSED)
                   2618:                return SLJIT_SUCCESS;
                   2619: 
1.1.1.3   misho    2620:        ADJUST_LOCAL_OFFSET(dst, dstw);
1.1       misho    2621:        CHECK_EXTRA_REGS(dst, dstw, (void)0);
                   2622:        if (SLJIT_UNLIKELY(compiler->flags_saved))
1.1.1.3   misho    2623:                FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS));
1.1       misho    2624: 
1.1.1.4 ! misho    2625:        /* setcc = jcc + 0x10. */
        !          2626:        cond_set = get_jump_code(type) + 0x10;
1.1       misho    2627: 
1.1.1.4 ! misho    2628: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
        !          2629:        if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src) {
        !          2630:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 3);
        !          2631:                FAIL_IF(!inst);
        !          2632:                INC_SIZE(4 + 3);
        !          2633:                /* Set low register to conditional flag. */
        !          2634:                *inst++ = (reg_map[TMP_REGISTER] <= 7) ? REX : REX_B;
        !          2635:                *inst++ = GROUP_0F;
        !          2636:                *inst++ = cond_set;
        !          2637:                *inst++ = MOD_REG | reg_lmap[TMP_REGISTER];
        !          2638:                *inst++ = REX | (reg_map[TMP_REGISTER] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B);
        !          2639:                *inst++ = OR_rm8_r8;
        !          2640:                *inst++ = MOD_REG | (reg_lmap[TMP_REGISTER] << 3) | reg_lmap[dst];
        !          2641:                return SLJIT_SUCCESS;
1.1       misho    2642:        }
                   2643: 
1.1.1.4 ! misho    2644:        reg = (op == SLJIT_MOV && dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
1.1       misho    2645: 
1.1.1.4 ! misho    2646:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4);
        !          2647:        FAIL_IF(!inst);
1.1       misho    2648:        INC_SIZE(4 + 4);
                   2649:        /* Set low register to conditional flag. */
1.1.1.4 ! misho    2650:        *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;
        !          2651:        *inst++ = GROUP_0F;
        !          2652:        *inst++ = cond_set;
        !          2653:        *inst++ = MOD_REG | reg_lmap[reg];
        !          2654:        *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
        !          2655:        *inst++ = GROUP_0F;
        !          2656:        *inst++ = MOVZX_r_rm8;
        !          2657:        *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
        !          2658: 
        !          2659:        if (reg != TMP_REGISTER)
        !          2660:                return SLJIT_SUCCESS;
        !          2661: 
        !          2662:        if (GET_OPCODE(op) < SLJIT_ADD) {
        !          2663:                compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
        !          2664:                return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
        !          2665:        }
1.1       misho    2666: #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
1.1.1.4 ! misho    2667:        compiler->skip_checks = 1;
1.1       misho    2668: #endif
1.1.1.4 ! misho    2669:        return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0);
        !          2670: #else /* SLJIT_CONFIG_X86_64 */
        !          2671:        if (GET_OPCODE(op) < SLJIT_ADD && dst <= TMP_REGISTER) {
        !          2672:                if (reg_map[dst] <= 4) {
        !          2673:                        /* Low byte is accessible. */
        !          2674:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3);
        !          2675:                        FAIL_IF(!inst);
1.1       misho    2676:                        INC_SIZE(3 + 3);
                   2677:                        /* Set low byte to conditional flag. */
1.1.1.4 ! misho    2678:                        *inst++ = GROUP_0F;
        !          2679:                        *inst++ = cond_set;
        !          2680:                        *inst++ = MOD_REG | reg_map[dst];
        !          2681: 
        !          2682:                        *inst++ = GROUP_0F;
        !          2683:                        *inst++ = MOVZX_r_rm8;
        !          2684:                        *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst];
        !          2685:                        return SLJIT_SUCCESS;
1.1       misho    2686:                }
                   2687: 
1.1.1.4 ! misho    2688:                /* Low byte is not accessible. */
        !          2689:                if (cpu_has_cmov == -1)
        !          2690:                        get_cpu_features();
        !          2691: 
        !          2692:                if (cpu_has_cmov) {
        !          2693:                        EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_IMM, 1);
        !          2694:                        /* a xor reg, reg operation would overwrite the flags. */
        !          2695:                        EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0);
1.1       misho    2696: 
1.1.1.4 ! misho    2697:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 3);
        !          2698:                        FAIL_IF(!inst);
1.1       misho    2699:                        INC_SIZE(3);
                   2700: 
1.1.1.4 ! misho    2701:                        *inst++ = GROUP_0F;
        !          2702:                        /* cmovcc = setcc - 0x50. */
        !          2703:                        *inst++ = cond_set - 0x50;
        !          2704:                        *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REGISTER];
        !          2705:                        return SLJIT_SUCCESS;
1.1       misho    2706:                }
1.1.1.4 ! misho    2707: 
        !          2708:                inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
        !          2709:                FAIL_IF(!inst);
        !          2710:                INC_SIZE(1 + 3 + 3 + 1);
        !          2711:                *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2712:                /* Set al to conditional flag. */
        !          2713:                *inst++ = GROUP_0F;
        !          2714:                *inst++ = cond_set;
        !          2715:                *inst++ = MOD_REG | 0 /* eax */;
        !          2716: 
        !          2717:                *inst++ = GROUP_0F;
        !          2718:                *inst++ = MOVZX_r_rm8;
        !          2719:                *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */;
        !          2720:                *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2721:                return SLJIT_SUCCESS;
        !          2722:        }
        !          2723: 
        !          2724:        if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && dst <= TMP_REGISTER && dst == src && reg_map[dst] <= 4) {
        !          2725:                SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] == 0, scratch_reg1_must_be_eax);
        !          2726:                if (dst != SLJIT_SCRATCH_REG1) {
        !          2727:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1);
        !          2728:                        FAIL_IF(!inst);
        !          2729:                        INC_SIZE(1 + 3 + 2 + 1);
        !          2730:                        /* Set low register to conditional flag. */
        !          2731:                        *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2732:                        *inst++ = GROUP_0F;
        !          2733:                        *inst++ = cond_set;
        !          2734:                        *inst++ = MOD_REG | 0 /* eax */;
        !          2735:                        *inst++ = OR_rm8_r8;
        !          2736:                        *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst];
        !          2737:                        *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2738:                }
        !          2739:                else {
        !          2740:                        inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);
        !          2741:                        FAIL_IF(!inst);
        !          2742:                        INC_SIZE(2 + 3 + 2 + 2);
        !          2743:                        /* Set low register to conditional flag. */
        !          2744:                        *inst++ = XCHG_r_rm;
        !          2745:                        *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REGISTER];
        !          2746:                        *inst++ = GROUP_0F;
        !          2747:                        *inst++ = cond_set;
        !          2748:                        *inst++ = MOD_REG | 1 /* ecx */;
        !          2749:                        *inst++ = OR_rm8_r8;
        !          2750:                        *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */;
        !          2751:                        *inst++ = XCHG_r_rm;
        !          2752:                        *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REGISTER];
        !          2753:                }
        !          2754:                return SLJIT_SUCCESS;
        !          2755:        }
        !          2756: 
        !          2757:        /* Set TMP_REGISTER to the bit. */
        !          2758:        inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
        !          2759:        FAIL_IF(!inst);
        !          2760:        INC_SIZE(1 + 3 + 3 + 1);
        !          2761:        *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2762:        /* Set al to conditional flag. */
        !          2763:        *inst++ = GROUP_0F;
        !          2764:        *inst++ = cond_set;
        !          2765:        *inst++ = MOD_REG | 0 /* eax */;
        !          2766: 
        !          2767:        *inst++ = GROUP_0F;
        !          2768:        *inst++ = MOVZX_r_rm8;
        !          2769:        *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;
        !          2770: 
        !          2771:        *inst++ = XCHG_EAX_r + reg_map[TMP_REGISTER];
        !          2772: 
        !          2773:        if (GET_OPCODE(op) < SLJIT_ADD)
        !          2774:                return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0);
        !          2775: 
1.1       misho    2776: #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
1.1.1.4 ! misho    2777:        compiler->skip_checks = 1;
1.1       misho    2778: #endif
1.1.1.4 ! misho    2779:        return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0);
        !          2780: #endif /* SLJIT_CONFIG_X86_64 */
1.1       misho    2781: }
                   2782: 
1.1.1.4 ! misho    2783: SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
1.1.1.3   misho    2784: {
                   2785:        CHECK_ERROR();
                   2786:        check_sljit_get_local_base(compiler, dst, dstw, offset);
                   2787:        ADJUST_LOCAL_OFFSET(dst, dstw);
                   2788: 
                   2789:        CHECK_EXTRA_REGS(dst, dstw, (void)0);
                   2790: 
                   2791: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2792:        compiler->mode32 = 0;
                   2793: #endif
                   2794: 
                   2795:        ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset);
                   2796: 
                   2797: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2798:        if (NOT_HALFWORD(offset)) {
                   2799:                FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, offset));
                   2800: #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
1.1.1.4 ! misho    2801:                SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED);
1.1.1.3   misho    2802:                return compiler->error;
                   2803: #else
1.1.1.4 ! misho    2804:                return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0);
1.1.1.3   misho    2805: #endif
                   2806:        }
                   2807: #endif
                   2808: 
                   2809:        if (offset != 0)
1.1.1.4 ! misho    2810:                return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset);
1.1.1.3   misho    2811:        return emit_mov(compiler, dst, dstw, SLJIT_LOCALS_REG, 0);
                   2812: }
                   2813: 
1.1.1.4 ! misho    2814: SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
1.1       misho    2815: {
1.1.1.4 ! misho    2816:        sljit_ub *inst;
1.1       misho    2817:        struct sljit_const *const_;
                   2818: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1.1.1.4 ! misho    2819:        sljit_si reg;
1.1       misho    2820: #endif
                   2821: 
                   2822:        CHECK_ERROR_PTR();
                   2823:        check_sljit_emit_const(compiler, dst, dstw, init_value);
1.1.1.3   misho    2824:        ADJUST_LOCAL_OFFSET(dst, dstw);
1.1       misho    2825: 
                   2826:        CHECK_EXTRA_REGS(dst, dstw, (void)0);
                   2827: 
                   2828:        const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
                   2829:        PTR_FAIL_IF(!const_);
                   2830:        set_const(const_, compiler);
                   2831: 
                   2832: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2833:        compiler->mode32 = 0;
1.1.1.4 ! misho    2834:        reg = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
1.1       misho    2835: 
                   2836:        if (emit_load_imm64(compiler, reg, init_value))
                   2837:                return NULL;
                   2838: #else
                   2839:        if (dst == SLJIT_UNUSED)
                   2840:                dst = TMP_REGISTER;
                   2841: 
                   2842:        if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
                   2843:                return NULL;
                   2844: #endif
                   2845: 
1.1.1.4 ! misho    2846:        inst = (sljit_ub*)ensure_buf(compiler, 2);
        !          2847:        PTR_FAIL_IF(!inst);
1.1       misho    2848: 
1.1.1.4 ! misho    2849:        *inst++ = 0;
        !          2850:        *inst++ = 1;
1.1       misho    2851: 
                   2852: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
                   2853:        if (reg == TMP_REGISTER && dst != SLJIT_UNUSED)
                   2854:                if (emit_mov(compiler, dst, dstw, TMP_REGISTER, 0))
                   2855:                        return NULL;
                   2856: #endif
                   2857: 
                   2858:        return const_;
                   2859: }
                   2860: 
                   2861: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
                   2862: {
                   2863: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1.1.1.4 ! misho    2864:        *(sljit_sw*)addr = new_addr - (addr + 4);
1.1       misho    2865: #else
                   2866:        *(sljit_uw*)addr = new_addr;
                   2867: #endif
                   2868: }
                   2869: 
1.1.1.4 ! misho    2870: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
1.1       misho    2871: {
1.1.1.4 ! misho    2872:        *(sljit_sw*)addr = new_constant;
1.1       misho    2873: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>