pavone@467: /* pavone@467: Copyright 2013 Michael Pavone pavone@484: This file is part of BlastEm. pavone@467: BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. pavone@467: */ pavone@14: #include "gen_x86.h" pavone@567: #include "mem.h" pavone@792: #include "util.h" pavone@14: #include pavone@14: #include pavone@343: #include pavone@656: #include pavone@656: #include pavone@14: pavone@14: #define REX_RM_FIELD 0x1 pavone@14: #define REX_SIB_FIELD 0x2 pavone@14: #define REX_REG_FIELD 0x4 pavone@14: #define REX_QUAD 0x8 pavone@14: pavone@14: #define OP_ADD 0x00 pavone@14: #define OP_OR 0x08 pavone@14: #define PRE_2BYTE 0x0F pavone@14: #define OP_ADC 0x10 pavone@14: #define OP_SBB 0x18 pavone@14: #define OP_AND 0x20 pavone@14: #define OP_SUB 0x28 pavone@14: #define OP_XOR 0x30 pavone@14: #define OP_CMP 0x38 pavone@14: #define PRE_REX 0x40 pavone@14: #define OP_PUSH 0x50 pavone@14: #define OP_POP 0x58 pavone@81: #define OP_MOVSXD 0x63 pavone@14: #define PRE_SIZE 0x66 pavone@14: #define OP_JCC 0x70 pavone@14: #define OP_IMMED_ARITH 0x80 pavone@484: #define OP_TEST 0x84 pavone@241: #define OP_XCHG 0x86 pavone@14: #define OP_MOV 0x88 pavone@593: #define PRE_XOP 0x8F pavone@241: #define OP_XCHG_AX 0x90 pavone@151: #define OP_CDQ 0x99 pavone@14: #define OP_PUSHF 0x9C pavone@14: #define OP_POPF 0x9D pavone@14: #define OP_MOV_I8R 0xB0 pavone@14: #define OP_MOV_IR 0xB8 pavone@49: #define OP_SHIFTROT_IR 0xC0 pavone@14: #define OP_RETN 0xC3 pavone@15: #define OP_MOV_IEA 0xC6 pavone@49: #define OP_SHIFTROT_1 0xD0 pavone@51: #define OP_SHIFTROT_CL 0xD2 pavone@207: #define OP_LOOP 0xE2 pavone@14: #define OP_CALL 0xE8 pavone@18: #define OP_JMP 0xE9 pavone@18: #define OP_JMP_BYTE 0xEB pavone@82: #define OP_NOT_NEG 0xF6 pavone@81: #define OP_SINGLE_EA 0xFF pavone@14: pavone@14: #define OP2_JCC 0x80 pavone@14: #define OP2_SETCC 0x90 pavone@61: #define OP2_BT 0xA3 pavone@123: #define OP2_BTS 0xAB pavone@151: #define OP2_IMUL 0xAF pavone@123: #define OP2_BTR 0xB3 pavone@61: #define OP2_BTX_I 0xBA pavone@123: #define OP2_BTC 0xBB pavone@81: #define OP2_MOVSX 0xBE pavone@151: #define OP2_MOVZX 0xB6 pavone@14: pavone@14: #define OP_EX_ADDI 0x0 pavone@14: #define OP_EX_ORI 0x1 pavone@14: #define OP_EX_ADCI 0x2 pavone@14: #define OP_EX_SBBI 0x3 pavone@14: #define OP_EX_ANDI 0x4 pavone@14: #define OP_EX_SUBI 0x5 pavone@14: #define OP_EX_XORI 0x6 pavone@14: #define OP_EX_CMPI 0x7 pavone@14: pavone@49: #define OP_EX_ROL 0x0 pavone@49: #define OP_EX_ROR 0x1 pavone@49: #define OP_EX_RCL 0x2 pavone@49: #define OP_EX_RCR 0x3 pavone@49: #define OP_EX_SHL 0x4 pavone@49: #define OP_EX_SHR 0x5 pavone@49: #define OP_EX_SAL 0x6 //identical to SHL pavone@49: #define OP_EX_SAR 0x7 pavone@49: pavone@61: #define OP_EX_BT 0x4 pavone@61: #define OP_EX_BTS 0x5 pavone@61: #define OP_EX_BTR 0x6 pavone@61: #define OP_EX_BTC 0x7 pavone@61: pavone@82: #define OP_EX_TEST_I 0x0 pavone@82: #define OP_EX_NOT 0x2 pavone@82: #define OP_EX_NEG 0x3 pavone@151: #define OP_EX_MUL 0x4 pavone@151: #define OP_EX_IMUL 0x5 pavone@151: #define OP_EX_DIV 0x6 pavone@151: #define OP_EX_IDIV 0x7 pavone@82: pavone@81: #define OP_EX_INC 0x0 pavone@81: #define OP_EX_DEC 0x1 pavone@81: #define OP_EX_CALL_EA 0x2 pavone@81: #define OP_EX_JMP_EA 0x4 pavone@81: #define OP_EX_PUSH_EA 0x6 pavone@81: pavone@14: #define BIT_IMMED_RAX 0x4 pavone@14: #define BIT_DIR 0x2 pavone@14: #define BIT_SIZE 0x1 pavone@14: pavone@14: pavone@14: enum { pavone@14: X86_RAX = 0, pavone@14: X86_RCX, pavone@14: X86_RDX, pavone@14: X86_RBX, pavone@14: X86_RSP, pavone@14: X86_RBP, pavone@14: X86_RSI, pavone@14: X86_RDI, pavone@14: X86_AH=4, pavone@14: X86_CH, pavone@14: X86_DH, pavone@14: X86_BH, pavone@14: X86_R8=0, pavone@14: X86_R9, pavone@14: X86_R10, pavone@14: X86_R11, pavone@14: X86_R12, pavone@14: X86_R13, pavone@14: X86_R14, pavone@14: X86_R15 pavone@14: } x86_regs_enc; pavone@14: pavone@728: char * x86_reg_names[] = { pavone@728: #ifdef X86_64 pavone@728: "rax", pavone@728: "rcx", pavone@728: "rdx", pavone@728: "rbx", pavone@728: "rsp", pavone@728: "rbp", pavone@728: "rsi", pavone@728: "rdi", pavone@728: #else pavone@728: "eax", pavone@728: "ecx", pavone@728: "edx", pavone@728: "ebx", pavone@728: "esp", pavone@728: "ebp", pavone@728: "esi", pavone@728: "edi", pavone@728: #endif pavone@728: "ah", pavone@728: "ch", pavone@728: "dh", pavone@728: "bh", pavone@728: "r8", pavone@728: "r9", pavone@728: "r10", pavone@728: "r11", pavone@728: "r12", pavone@728: "r13", pavone@728: "r14", pavone@728: "r15", pavone@728: }; pavone@728: pavone@728: char * x86_sizes[] = { pavone@728: "b", "w", "d", "q" pavone@728: }; pavone@728: pavone@567: void jmp_nocheck(code_info *code, code_ptr dest) pavone@14: { pavone@567: code_ptr out = code->cur; pavone@567: ptrdiff_t disp = dest-(out+2); pavone@567: if (disp <= 0x7F && disp >= -0x80) { pavone@567: *(out++) = OP_JMP_BYTE; pavone@567: *(out++) = disp; pavone@567: } else { pavone@567: disp = dest-(out+5); pavone@567: if (disp <= 0x7FFFFFFF && disp >= -2147483648) { pavone@567: *(out++) = OP_JMP; pavone@567: *(out++) = disp; pavone@567: disp >>= 8; pavone@567: *(out++) = disp; pavone@567: disp >>= 8; pavone@567: *(out++) = disp; pavone@567: disp >>= 8; pavone@567: *(out++) = disp; pavone@567: } else { pavone@792: fatal_error("jmp: %p - %p = %l which is out of range of a 32-bit displacementX\n", dest, out + 6, (long)disp); pavone@567: } pavone@567: } pavone@567: code->cur = out; pavone@567: } pavone@567: pavone@567: void check_alloc_code(code_info *code, uint32_t inst_size) pavone@567: { pavone@567: if (code->cur + inst_size > code->last) { pavone@567: size_t size = CODE_ALLOC_SIZE; pavone@567: code_ptr next_code = alloc_code(&size); pavone@567: if (!next_code) { pavone@792: fatal_error("Failed to allocate memory for generated code\n"); pavone@567: } pavone@567: if (next_code != code->last + RESERVE_WORDS) { pavone@567: //new chunk is not contiguous with the current one pavone@567: jmp_nocheck(code, next_code); pavone@567: code->cur = next_code; pavone@567: code->last = next_code + size/sizeof(RESERVE_WORDS); pavone@567: } pavone@567: code->last = next_code + size/sizeof(code_word) - RESERVE_WORDS; pavone@567: } pavone@567: } pavone@567: pavone@567: void x86_rr_sizedir(code_info *code, uint16_t opcode, uint8_t src, uint8_t dst, uint8_t size) pavone@567: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@14: uint8_t tmp; pavone@14: if (size == SZ_W) { pavone@14: *(out++) = PRE_SIZE; pavone@14: } pavone@14: if (size == SZ_B && dst >= RSP && dst <= RDI) { pavone@14: opcode |= BIT_DIR; pavone@14: tmp = dst; pavone@14: dst = src; pavone@194: src = tmp; pavone@14: } pavone@14: if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { pavone@728: #ifdef X86_64 pavone@14: *out = PRE_REX; pavone@267: if (src >= AH && src <= BH || dst >= AH && dst <= BH) { pavone@792: fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); pavone@267: } pavone@14: if (size == SZ_Q) { pavone@14: *out |= REX_QUAD; pavone@14: } pavone@14: if (src >= R8) { pavone@14: *out |= REX_REG_FIELD; pavone@14: src -= (R8 - X86_R8); pavone@14: } pavone@14: if (dst >= R8) { pavone@14: *out |= REX_RM_FIELD; pavone@14: dst -= (R8 - X86_R8); pavone@14: } pavone@14: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, src: %s, dst: %s, size: %s\n", opcode, x86_reg_names[src], x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@14: } pavone@14: if (size == SZ_B) { pavone@14: if (src >= AH && src <= BH) { pavone@14: src -= (AH-X86_AH); pavone@14: } pavone@14: if (dst >= AH && dst <= BH) { pavone@14: dst -= (AH-X86_AH); pavone@14: } pavone@14: } else { pavone@14: opcode |= BIT_SIZE; pavone@14: } pavone@151: if (opcode >= 0x100) { pavone@151: *(out++) = opcode >> 8; pavone@151: *(out++) = opcode; pavone@151: } else { pavone@151: *(out++) = opcode; pavone@151: } pavone@14: *(out++) = MODE_REG_DIRECT | dst | (src << 3); pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void x86_rrdisp_sizedir(code_info *code, uint16_t opcode, uint8_t reg, uint8_t base, int32_t disp, uint8_t size, uint8_t dir) pavone@14: { pavone@567: check_alloc_code(code, 10); pavone@567: code_ptr out = code->cur; pavone@343: //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix pavone@343: uint8_t tmp; pavone@343: if (size == SZ_W) { pavone@343: *(out++) = PRE_SIZE; pavone@343: } pavone@343: if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { pavone@728: #ifdef X86_64 pavone@343: *out = PRE_REX; pavone@343: if (reg >= AH && reg <= BH) { pavone@792: fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); pavone@343: } pavone@343: if (size == SZ_Q) { pavone@343: *out |= REX_QUAD; pavone@343: } pavone@343: if (reg >= R8) { pavone@343: *out |= REX_REG_FIELD; pavone@343: reg -= (R8 - X86_R8); pavone@343: } pavone@343: if (base >= R8) { pavone@343: *out |= REX_RM_FIELD; pavone@343: base -= (R8 - X86_R8); pavone@343: } pavone@343: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); pavone@728: #endif pavone@343: } pavone@343: if (size == SZ_B) { pavone@343: if (reg >= AH && reg <= BH) { pavone@343: reg -= (AH-X86_AH); pavone@343: } pavone@343: } else { pavone@343: opcode |= BIT_SIZE; pavone@343: } pavone@343: opcode |= dir; pavone@343: if (opcode >= 0x100) { pavone@343: *(out++) = opcode >> 8; pavone@343: *(out++) = opcode; pavone@343: } else { pavone@343: *(out++) = opcode; pavone@343: } pavone@567: if (disp < 128 && disp >= -128) { pavone@682: *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3); pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | base | (reg << 3); pavone@567: } pavone@343: if (base == RSP) { pavone@343: //add SIB byte, with no index and RSP as base pavone@343: *(out++) = (RSP << 3) | RSP; pavone@343: } pavone@343: *(out++) = disp; pavone@567: if (disp >= 128 || disp < -128) { pavone@343: *(out++) = disp >> 8; pavone@343: *(out++) = disp >> 16; pavone@343: *(out++) = disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@343: } pavone@343: pavone@567: void x86_rrind_sizedir(code_info *code, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t size, uint8_t dir) pavone@14: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@14: //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix pavone@14: uint8_t tmp; pavone@14: if (size == SZ_W) { pavone@14: *(out++) = PRE_SIZE; pavone@14: } pavone@14: if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { pavone@728: #ifdef X86_64 pavone@14: *out = PRE_REX; pavone@267: if (reg >= AH && reg <= BH) { pavone@792: fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); pavone@267: } pavone@14: if (size == SZ_Q) { pavone@14: *out |= REX_QUAD; pavone@14: } pavone@14: if (reg >= R8) { pavone@14: *out |= REX_REG_FIELD; pavone@14: reg -= (R8 - X86_R8); pavone@14: } pavone@14: if (base >= R8) { pavone@14: *out |= REX_RM_FIELD; pavone@14: base -= (R8 - X86_R8); pavone@14: } pavone@14: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); pavone@728: #endif pavone@14: } pavone@14: if (size == SZ_B) { pavone@14: if (reg >= AH && reg <= BH) { pavone@14: reg -= (AH-X86_AH); pavone@14: } pavone@14: } else { pavone@14: opcode |= BIT_SIZE; pavone@14: } pavone@14: *(out++) = opcode | dir; pavone@603: if (base == RBP) { pavone@603: //add a dummy 8-bit displacement since MODE_REG_INDIRECT with pavone@603: //an R/M field of RBP selects RIP, relative addressing pavone@603: *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3); pavone@603: *(out++) = 0; pavone@603: } else { pavone@14: *(out++) = MODE_REG_INDIRECT | base | (reg << 3); pavone@18: if (base == RSP) { pavone@18: //add SIB byte, with no index and RSP as base pavone@18: *(out++) = (RSP << 3) | RSP; pavone@18: } pavone@18: } pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void x86_rrindex_sizedir(code_info *code, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t index, uint8_t scale, uint8_t size, uint8_t dir) pavone@343: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@343: //TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix pavone@343: uint8_t tmp; pavone@343: if (size == SZ_W) { pavone@343: *(out++) = PRE_SIZE; pavone@343: } pavone@343: if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { pavone@728: #ifdef X86_64 pavone@343: *out = PRE_REX; pavone@343: if (reg >= AH && reg <= BH) { pavone@792: fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); pavone@343: } pavone@343: if (size == SZ_Q) { pavone@343: *out |= REX_QUAD; pavone@343: } pavone@343: if (reg >= R8) { pavone@343: *out |= REX_REG_FIELD; pavone@343: reg -= (R8 - X86_R8); pavone@343: } pavone@343: if (base >= R8) { pavone@343: *out |= REX_RM_FIELD; pavone@343: base -= (R8 - X86_R8); pavone@343: } pavone@343: if (index >= R8) { pavone@343: *out |= REX_SIB_FIELD; pavone@343: index -= (R8 - X86_R8); pavone@343: } pavone@343: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); pavone@728: #endif pavone@343: } pavone@343: if (size == SZ_B) { pavone@343: if (reg >= AH && reg <= BH) { pavone@343: reg -= (AH-X86_AH); pavone@343: } pavone@343: } else { pavone@343: opcode |= BIT_SIZE; pavone@343: } pavone@343: *(out++) = opcode | dir; pavone@560: *(out++) = MODE_REG_INDIRECT | RSP | (reg << 3); pavone@560: if (scale == 4) { pavone@567: scale = 2; pavone@567: } else if(scale == 8) { pavone@682: scale = 3; pavone@567: } else { pavone@567: scale--; pavone@343: } pavone@560: *(out++) = scale << 6 | (index << 3) | base; pavone@567: code->cur = out; pavone@343: } pavone@343: pavone@567: void x86_r_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, uint8_t size) pavone@82: { pavone@567: check_alloc_code(code, 4); pavone@567: code_ptr out = code->cur; pavone@82: uint8_t tmp; pavone@82: if (size == SZ_W) { pavone@82: *(out++) = PRE_SIZE; pavone@82: } pavone@82: if (size == SZ_Q || dst >= R8) { pavone@728: #ifdef X86_64 pavone@82: *out = PRE_REX; pavone@267: if (dst >= AH && dst <= BH) { pavone@792: fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); pavone@267: } pavone@82: if (size == SZ_Q) { pavone@82: *out |= REX_QUAD; pavone@82: } pavone@82: if (dst >= R8) { pavone@82: *out |= REX_RM_FIELD; pavone@82: dst -= (R8 - X86_R8); pavone@82: } pavone@82: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@82: } pavone@82: if (size == SZ_B) { pavone@82: if (dst >= AH && dst <= BH) { pavone@82: dst -= (AH-X86_AH); pavone@82: } pavone@82: } else { pavone@82: opcode |= BIT_SIZE; pavone@82: } pavone@82: *(out++) = opcode; pavone@82: *(out++) = MODE_REG_DIRECT | dst | (opex << 3); pavone@567: code->cur = out; pavone@82: } pavone@82: pavone@567: void x86_rdisp_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, int32_t disp, uint8_t size) pavone@82: { pavone@567: check_alloc_code(code, 7); pavone@567: code_ptr out = code->cur; pavone@82: uint8_t tmp; pavone@82: if (size == SZ_W) { pavone@82: *(out++) = PRE_SIZE; pavone@82: } pavone@82: if (size == SZ_Q || dst >= R8) { pavone@728: #ifdef X86_64 pavone@82: *out = PRE_REX; pavone@82: if (size == SZ_Q) { pavone@82: *out |= REX_QUAD; pavone@82: } pavone@82: if (dst >= R8) { pavone@82: *out |= REX_RM_FIELD; pavone@82: dst -= (R8 - X86_R8); pavone@82: } pavone@82: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@82: } pavone@82: if (size != SZ_B) { pavone@82: opcode |= BIT_SIZE; pavone@82: } pavone@82: *(out++) = opcode; pavone@567: if (disp < 128 && disp >= -128) { pavone@82: *(out++) = MODE_REG_DISPLACE8 | dst | (opex << 3); pavone@82: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst | (opex << 3); pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@82: } pavone@82: pavone@567: void x86_ir(code_info *code, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst, uint8_t size) pavone@14: { pavone@567: check_alloc_code(code, 8); pavone@567: code_ptr out = code->cur; pavone@15: uint8_t sign_extend = 0; pavone@484: if (opcode != OP_NOT_NEG && (size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) { pavone@15: sign_extend = 1; pavone@15: opcode |= BIT_DIR; pavone@15: } pavone@15: if (size == SZ_W) { pavone@15: *(out++) = PRE_SIZE; pavone@15: } pavone@15: if (dst == RAX && !sign_extend) { pavone@15: if (size != SZ_B) { pavone@15: al_opcode |= BIT_SIZE; pavone@15: if (size == SZ_Q) { pavone@728: #ifdef X86_64 pavone@15: *out = PRE_REX | REX_QUAD; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, size: %s\n", al_opcode, x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@15: } pavone@15: } pavone@14: *(out++) = al_opcode | BIT_IMMED_RAX; pavone@14: } else { pavone@15: if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { pavone@728: #ifdef X86_64 pavone@15: *out = PRE_REX; pavone@15: if (size == SZ_Q) { pavone@15: *out |= REX_QUAD; pavone@15: } pavone@15: if (dst >= R8) { pavone@15: *out |= REX_RM_FIELD; pavone@15: dst -= (R8 - X86_R8); pavone@15: } pavone@15: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@15: } pavone@14: if (dst >= AH && dst <= BH) { pavone@14: dst -= (AH-X86_AH); pavone@15: } pavone@15: if (size != SZ_B) { pavone@15: opcode |= BIT_SIZE; pavone@14: } pavone@14: *(out++) = opcode; pavone@14: *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); pavone@14: } pavone@14: *(out++) = val; pavone@15: if (size != SZ_B && !sign_extend) { pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: if (size != SZ_W) { pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: } pavone@15: } pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void x86_irdisp(code_info *code, uint8_t opcode, uint8_t op_ex, int32_t val, uint8_t dst, int32_t disp, uint8_t size) pavone@18: { pavone@567: check_alloc_code(code, 12); pavone@567: code_ptr out = code->cur; pavone@420: uint8_t sign_extend = 0; pavone@420: if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) { pavone@420: sign_extend = 1; pavone@420: opcode |= BIT_DIR; pavone@420: } pavone@420: if (size == SZ_W) { pavone@420: *(out++) = PRE_SIZE; pavone@420: } pavone@420: pavone@420: if (size == SZ_Q || dst >= R8) { pavone@728: #ifdef X86_64 pavone@420: *out = PRE_REX; pavone@420: if (size == SZ_Q) { pavone@420: *out |= REX_QUAD; pavone@420: } pavone@420: if (dst >= R8) { pavone@420: *out |= REX_RM_FIELD; pavone@420: dst -= (R8 - X86_R8); pavone@420: } pavone@420: out++; pavone@728: #else pavone@792: fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); pavone@728: #endif pavone@420: } pavone@420: if (size != SZ_B) { pavone@420: opcode |= BIT_SIZE; pavone@420: } pavone@420: *(out++) = opcode; pavone@567: if (disp < 128 && disp >= -128) { pavone@682: *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3); pavone@682: *(out++) = disp; pavone@567: } else { pavone@420: *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3); pavone@420: *(out++) = disp; pavone@420: disp >>= 8; pavone@420: *(out++) = disp; pavone@420: disp >>= 8; pavone@420: *(out++) = disp; pavone@420: disp >>= 8; pavone@420: *(out++) = disp; pavone@567: } pavone@420: *(out++) = val; pavone@420: if (size != SZ_B && !sign_extend) { pavone@420: val >>= 8; pavone@420: *(out++) = val; pavone@420: if (size != SZ_W) { pavone@420: val >>= 8; pavone@420: *(out++) = val; pavone@420: val >>= 8; pavone@420: *(out++) = val; pavone@420: } pavone@420: } pavone@567: code->cur = out; pavone@420: } pavone@420: pavone@567: void x86_shiftrot_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@49: if (size == SZ_W) { pavone@49: *(out++) = PRE_SIZE; pavone@49: } pavone@49: if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { pavone@49: *out = PRE_REX; pavone@49: if (size == SZ_Q) { pavone@49: *out |= REX_QUAD; pavone@49: } pavone@49: if (dst >= R8) { pavone@49: *out |= REX_RM_FIELD; pavone@49: dst -= (R8 - X86_R8); pavone@49: } pavone@49: out++; pavone@49: } pavone@49: if (dst >= AH && dst <= BH) { pavone@49: dst -= (AH-X86_AH); pavone@49: } pavone@49: pavone@49: *(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE); pavone@49: *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); pavone@49: if (val != 1) { pavone@49: *(out++) = val; pavone@49: } pavone@567: code->cur = out; pavone@49: } pavone@49: pavone@567: void x86_shiftrot_irdisp(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, int32_t disp, uint8_t size) pavone@49: { pavone@567: check_alloc_code(code, 9); pavone@567: code_ptr out = code->cur; pavone@49: if (size == SZ_W) { pavone@49: *(out++) = PRE_SIZE; pavone@49: } pavone@349: if (size == SZ_Q || dst >= R8) { pavone@49: *out = PRE_REX; pavone@49: if (size == SZ_Q) { pavone@49: *out |= REX_QUAD; pavone@49: } pavone@49: if (dst >= R8) { pavone@49: *out |= REX_RM_FIELD; pavone@49: dst -= (R8 - X86_R8); pavone@49: } pavone@49: out++; pavone@49: } pavone@49: if (dst >= AH && dst <= BH) { pavone@49: dst -= (AH-X86_AH); pavone@49: } pavone@49: pavone@49: *(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE); pavone@567: if (disp < 128 && disp >= -128) { pavone@49: *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3); pavone@49: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3); pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@49: if (val != 1) { pavone@49: *(out++) = val; pavone@49: } pavone@567: code->cur = out; pavone@49: } pavone@49: pavone@567: void x86_shiftrot_clr(code_info *code, uint8_t op_ex, uint8_t dst, uint8_t size) pavone@51: { pavone@567: check_alloc_code(code, 4); pavone@567: code_ptr out = code->cur; pavone@51: if (size == SZ_W) { pavone@51: *(out++) = PRE_SIZE; pavone@51: } pavone@51: if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { pavone@51: *out = PRE_REX; pavone@51: if (size == SZ_Q) { pavone@51: *out |= REX_QUAD; pavone@51: } pavone@51: if (dst >= R8) { pavone@51: *out |= REX_RM_FIELD; pavone@51: dst -= (R8 - X86_R8); pavone@51: } pavone@51: out++; pavone@51: } pavone@51: if (dst >= AH && dst <= BH) { pavone@51: dst -= (AH-X86_AH); pavone@51: } pavone@51: pavone@51: *(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE); pavone@51: *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); pavone@567: code->cur = out; pavone@51: } pavone@51: pavone@567: void x86_shiftrot_clrdisp(code_info *code, uint8_t op_ex, uint8_t dst, int32_t disp, uint8_t size) pavone@51: { pavone@567: check_alloc_code(code, 8); pavone@567: code_ptr out = code->cur; pavone@51: if (size == SZ_W) { pavone@51: *(out++) = PRE_SIZE; pavone@51: } pavone@349: if (size == SZ_Q || dst >= R8) { pavone@51: *out = PRE_REX; pavone@51: if (size == SZ_Q) { pavone@51: *out |= REX_QUAD; pavone@51: } pavone@51: if (dst >= R8) { pavone@51: *out |= REX_RM_FIELD; pavone@51: dst -= (R8 - X86_R8); pavone@51: } pavone@51: out++; pavone@51: } pavone@51: if (dst >= AH && dst <= BH) { pavone@51: dst -= (AH-X86_AH); pavone@51: } pavone@51: pavone@51: *(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE); pavone@567: if (disp < 128 && disp >= -128) { pavone@51: *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3); pavone@51: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3); pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@51: } pavone@567: code->cur = out; pavone@49: } pavone@49: pavone@567: void rol_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_ROL, val, dst, size); pavone@49: } pavone@49: pavone@567: void ror_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_ROR, val, dst, size); pavone@49: } pavone@49: pavone@567: void rcl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_RCL, val, dst, size); pavone@49: } pavone@49: pavone@567: void rcr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_RCR, val, dst, size); pavone@49: } pavone@49: pavone@567: void shl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_SHL, val, dst, size); pavone@49: } pavone@49: pavone@567: void shr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_SHR, val, dst, size); pavone@49: } pavone@49: pavone@567: void sar_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_ir(code, OP_EX_SAR, val, dst, size); pavone@49: } pavone@49: pavone@567: void rol_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_ROL, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void ror_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_ROR, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void rcl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_RCL, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void rcr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_RCR, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void shl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_SHL, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void shr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@49: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_SHR, val, dst_base, disp, size); pavone@49: } pavone@49: pavone@567: void sar_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_irdisp(code, OP_EX_SAR, val, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void rol_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_ROL, dst, size); pavone@51: } pavone@51: pavone@567: void ror_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_ROR, dst, size); pavone@51: } pavone@51: pavone@567: void rcl_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_RCL, dst, size); pavone@51: } pavone@51: pavone@567: void rcr_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_RCR, dst, size); pavone@51: } pavone@51: pavone@567: void shl_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_SHL, dst, size); pavone@51: } pavone@51: pavone@567: void shr_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_SHR, dst, size); pavone@51: } pavone@51: pavone@567: void sar_clr(code_info *code, uint8_t dst, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clr(code, OP_EX_SAR, dst, size); pavone@51: } pavone@51: pavone@567: void rol_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_ROL, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void ror_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_ROR, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void rcl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_RCL, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void rcr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_RCR, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void shl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@51: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_SHL, dst_base, disp, size); pavone@51: } pavone@51: pavone@567: void shr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@14: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_SHR, dst_base, disp, size); pavone@14: } pavone@14: pavone@567: void sar_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@14: { pavone@567: x86_shiftrot_clrdisp(code, OP_EX_SAR, dst_base, disp, size); pavone@14: } pavone@14: pavone@567: void add_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_rr_sizedir(code, OP_ADD, src, dst, size); pavone@18: } pavone@18: pavone@567: void add_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@420: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size); pavone@420: } pavone@420: pavone@567: void add_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADDI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void add_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_ADD, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void add_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_rrdisp_sizedir(code, OP_ADD, dst, src_base, disp, size, BIT_DIR); pavone@146: } pavone@146: pavone@567: void adc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_rr_sizedir(code, OP_ADC, src, dst, size); pavone@146: } pavone@146: pavone@567: void adc_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_ADCI, OP_ADC, val, dst, size); pavone@146: } pavone@146: pavone@567: void adc_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@146: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADCI, val, dst_base, disp, size); pavone@146: } pavone@146: pavone@567: void adc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@146: { pavone@567: x86_rrdisp_sizedir(code, OP_ADC, src, dst_base, disp, size, 0); pavone@146: } pavone@146: pavone@567: void adc_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_ADC, dst, src_base, disp, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void or_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_rr_sizedir(code, OP_OR, src, dst, size); pavone@567: } pavone@567: void or_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@567: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size); pavone@18: } pavone@18: pavone@567: void or_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ORI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void or_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_OR, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void or_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_OR, dst, src_base, disp, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void and_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rr_sizedir(code, OP_AND, src, dst, size); pavone@14: } pavone@14: pavone@567: void and_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size); pavone@18: } pavone@18: pavone@567: void and_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ANDI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void and_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_AND, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void and_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_AND, dst, src_base, disp, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void xor_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rr_sizedir(code, OP_XOR, src, dst, size); pavone@14: } pavone@14: pavone@567: void xor_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size); pavone@18: } pavone@18: pavone@567: void xor_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_XORI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void xor_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_XOR, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void xor_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_XOR, dst, src_base, disp, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void sub_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rr_sizedir(code, OP_SUB, src, dst, size); pavone@14: } pavone@14: pavone@567: void sub_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size); pavone@18: } pavone@18: pavone@567: void sub_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SUBI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void sub_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_SUB, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void sub_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_rrdisp_sizedir(code, OP_SUB, dst, src_base, disp, size, BIT_DIR); pavone@146: } pavone@146: pavone@567: void sbb_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_rr_sizedir(code, OP_SBB, src, dst, size); pavone@146: } pavone@146: pavone@567: void sbb_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@146: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_SBBI, OP_SBB, val, dst, size); pavone@146: } pavone@146: pavone@567: void sbb_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@146: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SBBI, val, dst_base, disp, size); pavone@146: } pavone@146: pavone@567: void sbb_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@146: { pavone@567: x86_rrdisp_sizedir(code, OP_SBB, src, dst_base, disp, size, 0); pavone@146: } pavone@146: pavone@567: void sbb_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_SBB, dst, src_base, disp, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void cmp_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rr_sizedir(code, OP_CMP, src, dst, size); pavone@14: } pavone@14: pavone@567: void cmp_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@18: { pavone@567: x86_ir(code, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size); pavone@18: } pavone@18: pavone@567: void cmp_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_irdisp(code, OP_IMMED_ARITH, OP_EX_CMPI, val, dst_base, disp, size); pavone@18: } pavone@18: pavone@567: void cmp_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@18: { pavone@567: x86_rrdisp_sizedir(code, OP_CMP, src, dst_base, disp, size, 0); pavone@18: } pavone@18: pavone@567: void cmp_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@484: { pavone@567: x86_rrdisp_sizedir(code, OP_CMP, dst, src_base, disp, size, BIT_DIR); pavone@484: } pavone@484: pavone@567: void test_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@484: { pavone@567: x86_rr_sizedir(code, OP_TEST, src, dst, size); pavone@484: } pavone@484: pavone@567: void test_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@484: { pavone@567: x86_ir(code, OP_NOT_NEG, OP_EX_TEST_I, OP_TEST, val, dst, size); pavone@484: } pavone@484: pavone@567: void test_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size) pavone@484: { pavone@567: x86_irdisp(code, OP_NOT_NEG, OP_EX_TEST_I, val, dst_base, disp, size); pavone@484: } pavone@484: pavone@567: void test_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@484: { pavone@567: x86_rrdisp_sizedir(code, OP_TEST, src, dst_base, disp, size, 0); pavone@484: } pavone@484: pavone@567: void test_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_rrdisp_sizedir(code, OP_TEST, dst, src_base, disp, size, BIT_DIR); pavone@151: } pavone@151: pavone@567: void imul_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_rr_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src, size); pavone@151: } pavone@151: pavone@567: void imul_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@82: { pavone@567: x86_rrdisp_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src_base, disp, size, 0); pavone@82: } pavone@82: pavone@567: void not_r(code_info *code, uint8_t dst, uint8_t size) pavone@82: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_NOT, dst, size); pavone@82: } pavone@82: pavone@567: void neg_r(code_info *code, uint8_t dst, uint8_t size) pavone@82: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_NEG, dst, size); pavone@82: } pavone@82: pavone@567: void not_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@82: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NOT, dst_base, disp, size); pavone@82: } pavone@82: pavone@567: void neg_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@151: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size); pavone@151: } pavone@151: pavone@567: void mul_r(code_info *code, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_MUL, dst, size); pavone@151: } pavone@151: pavone@567: void imul_r(code_info *code, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_IMUL, dst, size); pavone@151: } pavone@151: pavone@567: void div_r(code_info *code, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_DIV, dst, size); pavone@151: } pavone@151: pavone@567: void idiv_r(code_info *code, uint8_t dst, uint8_t size) pavone@151: { pavone@567: x86_r_size(code, OP_NOT_NEG, OP_EX_IDIV, dst, size); pavone@151: } pavone@151: pavone@567: void mul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@151: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_MUL, dst_base, disp, size); pavone@151: } pavone@151: pavone@567: void imul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@151: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IMUL, dst_base, disp, size); pavone@151: } pavone@151: pavone@567: void div_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@151: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_DIV, dst_base, disp, size); pavone@151: } pavone@151: pavone@567: void idiv_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size) pavone@14: { pavone@567: x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IDIV, dst_base, disp, size); pavone@14: } pavone@14: pavone@567: void mov_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rr_sizedir(code, OP_MOV, src, dst, size); pavone@14: } pavone@14: pavone@567: void mov_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size) pavone@14: { pavone@567: x86_rrdisp_sizedir(code, OP_MOV, src, dst_base, disp, size, 0); pavone@14: } pavone@14: pavone@567: void mov_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size) pavone@343: { pavone@567: x86_rrdisp_sizedir(code, OP_MOV, dst, src_base, disp, size, BIT_DIR); pavone@343: } pavone@343: pavone@567: void mov_rrind(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@343: { pavone@567: x86_rrind_sizedir(code, OP_MOV, src, dst, size, 0); pavone@343: } pavone@343: pavone@567: void mov_rindr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@14: { pavone@567: x86_rrind_sizedir(code, OP_MOV, dst, src, size, BIT_DIR); pavone@14: } pavone@14: pavone@567: void mov_rrindex(code_info *code, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size) pavone@14: { pavone@567: x86_rrindex_sizedir(code, OP_MOV, src, dst_base, dst_index, scale, size, 0); pavone@14: } pavone@14: pavone@567: void mov_rindexr(code_info *code, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size) pavone@343: { pavone@567: x86_rrindex_sizedir(code, OP_MOV, dst, src_base, src_index, scale, size, BIT_DIR); pavone@343: } pavone@343: pavone@567: void mov_ir(code_info *code, int64_t val, uint8_t dst, uint8_t size) pavone@343: { pavone@567: check_alloc_code(code, 14); pavone@567: code_ptr out = code->cur; pavone@15: uint8_t sign_extend = 0; pavone@15: if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) { pavone@15: sign_extend = 1; pavone@15: } pavone@15: if (size == SZ_W) { pavone@15: *(out++) = PRE_SIZE; pavone@14: } pavone@15: if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { pavone@15: *out = PRE_REX; pavone@15: if (size == SZ_Q) { pavone@15: *out |= REX_QUAD; pavone@15: } pavone@15: if (dst >= R8) { pavone@15: *out |= REX_RM_FIELD; pavone@15: dst -= (R8 - X86_R8); pavone@15: } pavone@15: out++; pavone@15: } pavone@15: if (dst >= AH && dst <= BH) { pavone@15: dst -= (AH-X86_AH); pavone@14: } pavone@15: if (size == SZ_B) { pavone@18: *(out++) = OP_MOV_I8R | dst; pavone@15: } else if (size == SZ_Q && sign_extend) { pavone@15: *(out++) = OP_MOV_IEA | BIT_SIZE; pavone@15: *(out++) = MODE_REG_DIRECT | dst; pavone@15: } else { pavone@18: *(out++) = OP_MOV_IR | dst; pavone@15: } pavone@14: *(out++) = val; pavone@15: if (size != SZ_B) { pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: if (size != SZ_W) { pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: if (size == SZ_Q && !sign_extend) { pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: val >>= 8; pavone@15: *(out++) = val; pavone@15: } pavone@15: } pavone@14: } pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void mov_irdisp(code_info *code, int32_t val, uint8_t dst, int32_t disp, uint8_t size) pavone@18: { pavone@567: check_alloc_code(code, 12); pavone@567: code_ptr out = code->cur; pavone@18: if (size == SZ_W) { pavone@18: *(out++) = PRE_SIZE; pavone@18: } pavone@349: if (size == SZ_Q || dst >= R8) { pavone@18: *out = PRE_REX; pavone@18: if (size == SZ_Q) { pavone@18: *out |= REX_QUAD; pavone@18: } pavone@18: if (dst >= R8) { pavone@18: *out |= REX_RM_FIELD; pavone@18: dst -= (R8 - X86_R8); pavone@18: } pavone@18: out++; pavone@18: } pavone@18: if (dst >= AH && dst <= BH) { pavone@18: dst -= (AH-X86_AH); pavone@18: } pavone@18: *(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE); pavone@567: if (disp < 128 && disp >= -128) { pavone@18: *(out++) = MODE_REG_DISPLACE8 | dst; pavone@18: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst; pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@18: pavone@18: *(out++) = val; pavone@18: if (size != SZ_B) { pavone@18: val >>= 8; pavone@18: *(out++) = val; pavone@18: if (size != SZ_W) { pavone@18: val >>= 8; pavone@18: *(out++) = val; pavone@18: val >>= 8; pavone@18: *(out++) = val; pavone@18: } pavone@18: } pavone@567: code->cur = out; pavone@18: } pavone@18: pavone@567: void mov_irind(code_info *code, int32_t val, uint8_t dst, uint8_t size) pavone@71: { pavone@567: check_alloc_code(code, 8); pavone@567: code_ptr out = code->cur; pavone@71: if (size == SZ_W) { pavone@71: *(out++) = PRE_SIZE; pavone@71: } pavone@71: if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { pavone@71: *out = PRE_REX; pavone@71: if (size == SZ_Q) { pavone@71: *out |= REX_QUAD; pavone@71: } pavone@71: if (dst >= R8) { pavone@71: *out |= REX_RM_FIELD; pavone@71: dst -= (R8 - X86_R8); pavone@71: } pavone@71: out++; pavone@71: } pavone@71: if (dst >= AH && dst <= BH) { pavone@71: dst -= (AH-X86_AH); pavone@71: } pavone@71: *(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE); pavone@71: *(out++) = MODE_REG_INDIRECT | dst; pavone@71: pavone@71: *(out++) = val; pavone@71: if (size != SZ_B) { pavone@71: val >>= 8; pavone@71: *(out++) = val; pavone@71: if (size != SZ_W) { pavone@71: val >>= 8; pavone@71: *(out++) = val; pavone@71: val >>= 8; pavone@71: *(out++) = val; pavone@71: } pavone@71: } pavone@567: code->cur = out; pavone@71: } pavone@71: pavone@567: void movsx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size) pavone@81: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@81: if (size == SZ_W) { pavone@81: *(out++) = PRE_SIZE; pavone@81: } pavone@81: if (size == SZ_Q || dst >= R8 || src >= R8) { pavone@81: *out = PRE_REX; pavone@81: if (size == SZ_Q) { pavone@81: *out |= REX_QUAD; pavone@81: } pavone@81: if (src >= R8) { pavone@125: *out |= REX_RM_FIELD; pavone@81: src -= (R8 - X86_R8); pavone@81: } pavone@81: if (dst >= R8) { pavone@125: *out |= REX_REG_FIELD; pavone@81: dst -= (R8 - X86_R8); pavone@81: } pavone@81: out++; pavone@81: } pavone@81: if (src_size == SZ_D) { pavone@81: *(out++) = OP_MOVSXD; pavone@81: } else { pavone@81: *(out++) = PRE_2BYTE; pavone@81: *(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE); pavone@81: } pavone@81: *(out++) = MODE_REG_DIRECT | src | (dst << 3); pavone@567: code->cur = out; pavone@81: } pavone@81: pavone@567: void movsx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size) pavone@81: { pavone@567: check_alloc_code(code, 12); pavone@567: code_ptr out = code->cur; pavone@81: if (size == SZ_W) { pavone@81: *(out++) = PRE_SIZE; pavone@81: } pavone@81: if (size == SZ_Q || dst >= R8 || src >= R8) { pavone@81: *out = PRE_REX; pavone@81: if (size == SZ_Q) { pavone@81: *out |= REX_QUAD; pavone@81: } pavone@81: if (src >= R8) { pavone@125: *out |= REX_RM_FIELD; pavone@81: src -= (R8 - X86_R8); pavone@81: } pavone@81: if (dst >= R8) { pavone@125: *out |= REX_REG_FIELD; pavone@81: dst -= (R8 - X86_R8); pavone@81: } pavone@81: out++; pavone@81: } pavone@81: if (src_size == SZ_D) { pavone@81: *(out++) = OP_MOVSXD; pavone@81: } else { pavone@81: *(out++) = PRE_2BYTE; pavone@81: *(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE); pavone@81: } pavone@567: if (disp < 128 && disp >= -128) { pavone@81: *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3); pavone@81: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | src | (dst << 3); pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@81: } pavone@81: pavone@567: void movzx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size) pavone@151: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@151: if (size == SZ_W) { pavone@151: *(out++) = PRE_SIZE; pavone@151: } pavone@151: if (size == SZ_Q || dst >= R8 || src >= R8) { pavone@151: *out = PRE_REX; pavone@151: if (size == SZ_Q) { pavone@151: *out |= REX_QUAD; pavone@151: } pavone@151: if (src >= R8) { pavone@151: *out |= REX_RM_FIELD; pavone@151: src -= (R8 - X86_R8); pavone@151: } pavone@151: if (dst >= R8) { pavone@151: *out |= REX_REG_FIELD; pavone@151: dst -= (R8 - X86_R8); pavone@151: } pavone@151: out++; pavone@151: } pavone@151: *(out++) = PRE_2BYTE; pavone@151: *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE); pavone@151: *(out++) = MODE_REG_DIRECT | src | (dst << 3); pavone@567: code->cur = out; pavone@151: } pavone@151: pavone@567: void movzx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size) pavone@151: { pavone@567: check_alloc_code(code, 9); pavone@567: code_ptr out = code->cur; pavone@151: if (size == SZ_W) { pavone@151: *(out++) = PRE_SIZE; pavone@151: } pavone@151: if (size == SZ_Q || dst >= R8 || src >= R8) { pavone@151: *out = PRE_REX; pavone@151: if (size == SZ_Q) { pavone@151: *out |= REX_QUAD; pavone@151: } pavone@151: if (src >= R8) { pavone@151: *out |= REX_RM_FIELD; pavone@151: src -= (R8 - X86_R8); pavone@151: } pavone@151: if (dst >= R8) { pavone@151: *out |= REX_REG_FIELD; pavone@151: dst -= (R8 - X86_R8); pavone@151: } pavone@151: out++; pavone@151: } pavone@151: *(out++) = PRE_2BYTE; pavone@151: *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE); pavone@567: if (disp < 128 && disp >= -128) { pavone@151: *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3); pavone@151: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | src | (dst << 3); pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@151: } pavone@151: pavone@567: void xchg_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@241: { pavone@567: check_alloc_code(code, 4); pavone@567: code_ptr out = code->cur; pavone@241: //TODO: Use OP_XCHG_AX when one of the registers is AX, EAX or RAX pavone@241: uint8_t tmp; pavone@241: if (size == SZ_W) { pavone@241: *(out++) = PRE_SIZE; pavone@241: } pavone@241: if (size == SZ_B && dst >= RSP && dst <= RDI) { pavone@241: tmp = dst; pavone@241: dst = src; pavone@241: src = tmp; pavone@241: } pavone@241: if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { pavone@241: *out = PRE_REX; pavone@241: if (size == SZ_Q) { pavone@241: *out |= REX_QUAD; pavone@241: } pavone@241: if (src >= R8) { pavone@241: *out |= REX_REG_FIELD; pavone@241: src -= (R8 - X86_R8); pavone@241: } pavone@241: if (dst >= R8) { pavone@241: *out |= REX_RM_FIELD; pavone@241: dst -= (R8 - X86_R8); pavone@241: } pavone@241: out++; pavone@241: } pavone@241: uint8_t opcode = OP_XCHG; pavone@241: if (size == SZ_B) { pavone@241: if (src >= AH && src <= BH) { pavone@241: src -= (AH-X86_AH); pavone@241: } pavone@241: if (dst >= AH && dst <= BH) { pavone@241: dst -= (AH-X86_AH); pavone@241: } pavone@241: } else { pavone@241: opcode |= BIT_SIZE; pavone@241: } pavone@241: *(out++) = opcode; pavone@241: *(out++) = MODE_REG_DIRECT | dst | (src << 3); pavone@567: code->cur = out; pavone@241: } pavone@241: pavone@567: void pushf(code_info *code) pavone@14: { pavone@567: check_alloc_code(code, 1); pavone@567: code_ptr out = code->cur; pavone@14: *(out++) = OP_PUSHF; pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void popf(code_info *code) pavone@14: { pavone@567: check_alloc_code(code, 1); pavone@567: code_ptr out = code->cur; pavone@14: *(out++) = OP_POPF; pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void push_r(code_info *code, uint8_t reg) pavone@14: { pavone@567: check_alloc_code(code, 2); pavone@567: code_ptr out = code->cur; pavone@14: if (reg >= R8) { pavone@14: *(out++) = PRE_REX | REX_RM_FIELD; pavone@14: reg -= R8 - X86_R8; pavone@14: } pavone@14: *(out++) = OP_PUSH | reg; pavone@567: code->cur = out; pavone@894: code->stack_off += sizeof(void *); pavone@14: } pavone@14: pavone@593: void push_rdisp(code_info *code, uint8_t base, int32_t disp) pavone@14: { pavone@593: //This instruction has no explicit size, so we pass SZ_B pavone@593: //to avoid any prefixes or bits being set pavone@593: x86_rdisp_size(code, OP_SINGLE_EA, OP_EX_PUSH_EA, base, disp, SZ_B); pavone@894: code->stack_off += sizeof(void *); pavone@593: } pavone@593: pavone@567: void pop_r(code_info *code, uint8_t reg) pavone@14: { pavone@567: check_alloc_code(code, 2); pavone@567: code_ptr out = code->cur; pavone@14: if (reg >= R8) { pavone@14: *(out++) = PRE_REX | REX_RM_FIELD; pavone@14: reg -= R8 - X86_R8; pavone@14: } pavone@14: *(out++) = OP_POP | reg; pavone@567: code->cur = out; pavone@894: code->stack_off -= sizeof(void *); pavone@14: } pavone@14: pavone@593: void pop_rind(code_info *code, uint8_t reg) pavone@14: { pavone@593: check_alloc_code(code, 3); pavone@593: code_ptr out = code->cur; pavone@593: if (reg >= R8) { pavone@593: *(out++) = PRE_REX | REX_RM_FIELD; pavone@593: reg -= R8 - X86_R8; pavone@593: } pavone@593: *(out++) = PRE_XOP; pavone@593: *(out++) = MODE_REG_INDIRECT | reg; pavone@593: code->cur = out; pavone@894: code->stack_off -= sizeof(void *); pavone@593: } pavone@593: pavone@567: void setcc_r(code_info *code, uint8_t cc, uint8_t dst) pavone@14: { pavone@567: check_alloc_code(code, 4); pavone@567: code_ptr out = code->cur; pavone@14: if (dst >= R8) { pavone@14: *(out++) = PRE_REX | REX_RM_FIELD; pavone@14: dst -= R8 - X86_R8; pavone@14: } else if (dst >= RSP && dst <= RDI) { pavone@14: *(out++) = PRE_REX; pavone@14: } else if (dst >= AH && dst <= BH) { pavone@14: dst -= AH - X86_AH; pavone@14: } pavone@14: *(out++) = PRE_2BYTE; pavone@14: *(out++) = OP2_SETCC | cc; pavone@14: *(out++) = MODE_REG_DIRECT | dst; pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void setcc_rind(code_info *code, uint8_t cc, uint8_t dst) pavone@14: { pavone@567: check_alloc_code(code, 4); pavone@567: code_ptr out = code->cur; pavone@14: if (dst >= R8) { pavone@14: *(out++) = PRE_REX | REX_RM_FIELD; pavone@14: dst -= R8 - X86_R8; pavone@14: } pavone@14: *(out++) = PRE_2BYTE; pavone@14: *(out++) = OP2_SETCC | cc; pavone@14: *(out++) = MODE_REG_INDIRECT | dst; pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void setcc_rdisp(code_info *code, uint8_t cc, uint8_t dst, int32_t disp) pavone@112: { pavone@567: check_alloc_code(code, 8); pavone@567: code_ptr out = code->cur; pavone@112: if (dst >= R8) { pavone@112: *(out++) = PRE_REX | REX_RM_FIELD; pavone@112: dst -= R8 - X86_R8; pavone@112: } pavone@112: *(out++) = PRE_2BYTE; pavone@112: *(out++) = OP2_SETCC | cc; pavone@567: if (disp < 128 && disp >= -128) { pavone@112: *(out++) = MODE_REG_DISPLACE8 | dst; pavone@112: *(out++) = disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst; pavone@567: *(out++) = disp; pavone@567: *(out++) = disp >> 8; pavone@567: *(out++) = disp >> 16; pavone@567: *(out++) = disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@112: } pavone@112: pavone@567: void bit_rr(code_info *code, uint8_t op2, uint8_t src, uint8_t dst, uint8_t size) pavone@61: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@61: if (size == SZ_W) { pavone@61: *(out++) = PRE_SIZE; pavone@61: } pavone@61: if (size == SZ_Q || src >= R8 || dst >= R8) { pavone@61: *out = PRE_REX; pavone@61: if (size == SZ_Q) { pavone@61: *out |= REX_QUAD; pavone@61: } pavone@61: if (src >= R8) { pavone@61: *out |= REX_REG_FIELD; pavone@61: src -= (R8 - X86_R8); pavone@61: } pavone@61: if (dst >= R8) { pavone@61: *out |= REX_RM_FIELD; pavone@61: dst -= (R8 - X86_R8); pavone@61: } pavone@61: out++; pavone@61: } pavone@61: *(out++) = PRE_2BYTE; pavone@123: *(out++) = op2; pavone@61: *(out++) = MODE_REG_DIRECT | dst | (src << 3); pavone@567: code->cur = out; pavone@61: } pavone@61: pavone@567: void bit_rrdisp(code_info *code, uint8_t op2, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@61: { pavone@567: check_alloc_code(code, 9); pavone@567: code_ptr out = code->cur; pavone@343: if (size == SZ_W) { pavone@343: *(out++) = PRE_SIZE; pavone@343: } pavone@343: if (size == SZ_Q || src >= R8 || dst_base >= R8) { pavone@343: *out = PRE_REX; pavone@343: if (size == SZ_Q) { pavone@343: *out |= REX_QUAD; pavone@343: } pavone@343: if (src >= R8) { pavone@343: *out |= REX_REG_FIELD; pavone@343: src -= (R8 - X86_R8); pavone@343: } pavone@343: if (dst_base >= R8) { pavone@343: *out |= REX_RM_FIELD; pavone@343: dst_base -= (R8 - X86_R8); pavone@343: } pavone@343: out++; pavone@343: } pavone@343: *(out++) = PRE_2BYTE; pavone@343: *(out++) = op2; pavone@567: if (dst_disp < 128 && dst_disp >= -128) { pavone@682: *(out++) = MODE_REG_DISPLACE8 | dst_base | (src << 3); pavone@682: *(out++) = dst_disp; pavone@567: } else { pavone@343: *(out++) = MODE_REG_DISPLACE32 | dst_base | (src << 3); pavone@343: *(out++) = dst_disp; pavone@343: *(out++) = dst_disp >> 8; pavone@343: *(out++) = dst_disp >> 16; pavone@343: *(out++) = dst_disp >> 24; pavone@567: } pavone@567: code->cur = out; pavone@343: } pavone@343: pavone@567: void bit_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size) pavone@61: { pavone@567: check_alloc_code(code, 6); pavone@567: code_ptr out = code->cur; pavone@61: if (size == SZ_W) { pavone@61: *(out++) = PRE_SIZE; pavone@61: } pavone@61: if (size == SZ_Q || dst >= R8) { pavone@61: *out = PRE_REX; pavone@61: if (size == SZ_Q) { pavone@61: *out |= REX_QUAD; pavone@61: } pavone@61: if (dst >= R8) { pavone@61: *out |= REX_RM_FIELD; pavone@61: dst -= (R8 - X86_R8); pavone@61: } pavone@61: out++; pavone@61: } pavone@61: *(out++) = PRE_2BYTE; pavone@61: *(out++) = OP2_BTX_I; pavone@123: *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3); pavone@61: *(out++) = val; pavone@567: code->cur = out; pavone@61: } pavone@61: pavone@567: void bit_irdisp(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@61: { pavone@567: check_alloc_code(code, 10); pavone@567: code_ptr out = code->cur; pavone@61: if (size == SZ_W) { pavone@61: *(out++) = PRE_SIZE; pavone@61: } pavone@61: if (size == SZ_Q || dst_base >= R8) { pavone@61: *out = PRE_REX; pavone@61: if (size == SZ_Q) { pavone@61: *out |= REX_QUAD; pavone@61: } pavone@61: if (dst_base >= R8) { pavone@61: *out |= REX_RM_FIELD; pavone@61: dst_base -= (R8 - X86_R8); pavone@61: } pavone@61: out++; pavone@61: } pavone@61: *(out++) = PRE_2BYTE; pavone@61: *(out++) = OP2_BTX_I; pavone@567: if (dst_disp < 128 && dst_disp >= -128) { pavone@123: *(out++) = MODE_REG_DISPLACE8 | dst_base | (op_ex << 3); pavone@61: *(out++) = dst_disp; pavone@567: } else { pavone@567: *(out++) = MODE_REG_DISPLACE32 | dst_base | (op_ex << 3); pavone@567: *(out++) = dst_disp; pavone@567: *(out++) = dst_disp >> 8; pavone@567: *(out++) = dst_disp >> 16; pavone@567: *(out++) = dst_disp >> 24; pavone@567: } pavone@61: *(out++) = val; pavone@567: code->cur = out; pavone@61: } pavone@61: pavone@567: void bt_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_rr(code, OP2_BT, src, dst, size); pavone@123: } pavone@123: pavone@567: void bt_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_rrdisp(code, OP2_BT, src, dst_base, dst_disp, size); pavone@343: } pavone@343: pavone@567: void bt_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_ir(code, OP_EX_BT, val, dst, size); pavone@123: } pavone@123: pavone@567: void bt_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_irdisp(code, OP_EX_BT, val, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void bts_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_rr(code, OP2_BTS, src, dst, size); pavone@123: } pavone@123: pavone@567: void bts_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_rrdisp(code, OP2_BTS, src, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void bts_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_ir(code, OP_EX_BTS, val, dst, size); pavone@123: } pavone@123: pavone@567: void bts_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_irdisp(code, OP_EX_BTS, val, dst_base, dst_disp, size); pavone@567: } pavone@567: pavone@567: void btr_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@567: { pavone@567: return bit_rr(code, OP2_BTR, src, dst, size); pavone@123: } pavone@123: pavone@567: void btr_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_rrdisp(code, OP2_BTR, src, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void btr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_ir(code, OP_EX_BTR, val, dst, size); pavone@123: } pavone@123: pavone@567: void btr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_irdisp(code, OP_EX_BTR, val, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void btc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_rr(code, OP2_BTC, src, dst, size); pavone@123: } pavone@123: pavone@567: void btc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_rrdisp(code, OP2_BTC, src, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void btc_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size) pavone@123: { pavone@567: return bit_ir(code, OP_EX_BTC, val, dst, size); pavone@123: } pavone@123: pavone@567: void btc_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size) pavone@123: { pavone@567: return bit_irdisp(code, OP_EX_BTC, val, dst_base, dst_disp, size); pavone@123: } pavone@123: pavone@567: void jcc(code_info *code, uint8_t cc, code_ptr dest) pavone@123: { pavone@567: check_alloc_code(code, 6); pavone@567: code_ptr out = code->cur; pavone@18: ptrdiff_t disp = dest-(out+2); pavone@14: if (disp <= 0x7F && disp >= -0x80) { pavone@14: *(out++) = OP_JCC | cc; pavone@14: *(out++) = disp; pavone@14: } else { pavone@18: disp = dest-(out+6); pavone@18: if (disp <= 0x7FFFFFFF && disp >= -2147483648) { pavone@18: *(out++) = PRE_2BYTE; pavone@18: *(out++) = OP2_JCC | cc; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: } else { pavone@792: fatal_error("jcc: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); pavone@18: } pavone@18: } pavone@567: code->cur = out; pavone@18: } pavone@18: pavone@567: void jmp(code_info *code, code_ptr dest) pavone@18: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@18: ptrdiff_t disp = dest-(out+2); pavone@18: if (disp <= 0x7F && disp >= -0x80) { pavone@18: *(out++) = OP_JMP_BYTE; pavone@14: *(out++) = disp; pavone@18: } else { pavone@18: disp = dest-(out+5); pavone@18: if (disp <= 0x7FFFFFFF && disp >= -2147483648) { pavone@18: *(out++) = OP_JMP; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: disp >>= 8; pavone@18: *(out++) = disp; pavone@18: } else { pavone@792: fatal_error("jmp: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); pavone@18: } pavone@14: } pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void jmp_r(code_info *code, uint8_t dst) pavone@81: { pavone@567: check_alloc_code(code, 3); pavone@567: code_ptr out = code->cur; pavone@235: if (dst >= R8) { pavone@235: dst -= R8 - X86_R8; pavone@235: *(out++) = PRE_REX | REX_RM_FIELD; pavone@235: } pavone@81: *(out++) = OP_SINGLE_EA; pavone@81: *(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3); pavone@567: code->cur = out; pavone@81: } pavone@81: pavone@593: void jmp_rind(code_info *code, uint8_t dst) pavone@14: { pavone@593: check_alloc_code(code, 3); pavone@593: code_ptr out = code->cur; pavone@593: if (dst >= R8) { pavone@593: dst -= R8 - X86_R8; pavone@593: *(out++) = PRE_REX | REX_RM_FIELD; pavone@593: } pavone@593: *(out++) = OP_SINGLE_EA; pavone@593: *(out++) = MODE_REG_INDIRECT | dst | (OP_EX_JMP_EA << 3); pavone@593: code->cur = out; pavone@593: } pavone@593: pavone@899: void call_noalign(code_info *code, code_ptr fun) pavone@14: { pavone@567: check_alloc_code(code, 5); pavone@567: code_ptr out = code->cur; pavone@14: ptrdiff_t disp = fun-(out+5); pavone@14: if (disp <= 0x7FFFFFFF && disp >= -2147483648) { pavone@14: *(out++) = OP_CALL; pavone@14: *(out++) = disp; pavone@14: disp >>= 8; pavone@14: *(out++) = disp; pavone@14: disp >>= 8; pavone@14: *(out++) = disp; pavone@14: disp >>= 8; pavone@14: *(out++) = disp; pavone@14: } else { pavone@18: //TODO: Implement far call??? pavone@792: fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp); pavone@14: } pavone@567: code->cur = out; pavone@899: } pavone@899: pavone@899: pavone@899: void call(code_info *code, code_ptr fun) pavone@899: { pavone@899: code->stack_off += sizeof(void *); pavone@899: int32_t adjust = 0; pavone@899: if (code->stack_off & 0xF) { pavone@899: adjust = 16 - (code->stack_off & 0xF); pavone@899: code->stack_off += adjust; pavone@899: sub_ir(code, adjust, RSP, SZ_PTR); pavone@899: } pavone@899: call_noalign(code, fun); pavone@894: if (adjust) { pavone@894: add_ir(code, adjust, RSP, SZ_PTR); pavone@894: } pavone@894: code->stack_off -= sizeof(void *) + adjust; pavone@14: } pavone@754: void call_raxfallback(code_info *code, code_ptr fun) pavone@754: { pavone@754: check_alloc_code(code, 5); pavone@754: code_ptr out = code->cur; pavone@754: ptrdiff_t disp = fun-(out+5); pavone@754: if (disp <= 0x7FFFFFFF && disp >= -2147483648) { pavone@754: *(out++) = OP_CALL; pavone@754: *(out++) = disp; pavone@754: disp >>= 8; pavone@754: *(out++) = disp; pavone@754: disp >>= 8; pavone@754: *(out++) = disp; pavone@754: disp >>= 8; pavone@754: *(out++) = disp; pavone@754: } else { pavone@755: mov_ir(code, (int64_t)fun, RAX, SZ_PTR); pavone@754: call_r(code, RAX); pavone@754: } pavone@754: code->cur = out; pavone@754: } pavone@754: pavone@567: void call_r(code_info *code, uint8_t dst) pavone@81: { pavone@894: code->stack_off += sizeof(void *); pavone@894: int32_t adjust = 0; pavone@894: if (code->stack_off & 0xF) { pavone@894: adjust = 16 - (code->stack_off & 0xF); pavone@894: code->stack_off += adjust; pavone@894: sub_ir(code, adjust, RSP, SZ_PTR); pavone@894: } pavone@567: check_alloc_code(code, 2); pavone@567: code_ptr out = code->cur; pavone@81: *(out++) = OP_SINGLE_EA; pavone@81: *(out++) = MODE_REG_DIRECT | dst | (OP_EX_CALL_EA << 3); pavone@567: code->cur = out; pavone@894: if (adjust) { pavone@894: add_ir(code, adjust, RSP, SZ_PTR); pavone@894: } pavone@894: code->stack_off -= sizeof(void *) + adjust; pavone@81: } pavone@81: pavone@567: void retn(code_info *code) pavone@14: { pavone@567: check_alloc_code(code, 1); pavone@567: code_ptr out = code->cur; pavone@14: *(out++) = OP_RETN; pavone@567: code->cur = out; pavone@14: } pavone@14: pavone@567: void cdq(code_info *code) pavone@151: { pavone@567: check_alloc_code(code, 1); pavone@567: code_ptr out = code->cur; pavone@151: *(out++) = OP_CDQ; pavone@567: code->cur = out; pavone@151: } pavone@14: pavone@567: void loop(code_info *code, code_ptr dst) pavone@207: { pavone@567: check_alloc_code(code, 2); pavone@567: code_ptr out = code->cur; pavone@207: ptrdiff_t disp = dst-(out+2); pavone@207: *(out++) = OP_LOOP; pavone@207: *(out++) = disp; pavone@567: code->cur = out; pavone@207: } pavone@567: pavone@656: uint32_t prep_args(code_info *code, uint32_t num_args, va_list args) pavone@656: { pavone@656: uint8_t *arg_arr = malloc(num_args); pavone@656: for (int i = 0; i < num_args; i ++) pavone@656: { pavone@656: arg_arr[i] = va_arg(args, int); pavone@656: } pavone@656: #ifdef X86_64 pavone@656: uint32_t stack_args = 0; pavone@656: uint8_t abi_regs[] = {RDI, RSI, RDX, RCX, R8, R9}; pavone@656: int8_t reg_swap[R15+1]; pavone@656: uint32_t usage = 0; pavone@656: memset(reg_swap, -1, sizeof(reg_swap)); pavone@656: for (int i = 0; i < num_args; i ++) pavone@656: { pavone@656: usage |= 1 << arg_arr[i]; pavone@656: } pavone@656: for (int i = 0; i < num_args; i ++) pavone@656: { pavone@656: uint8_t reg_arg = arg_arr[i]; pavone@656: if (i < sizeof(abi_regs)) { pavone@656: if (reg_swap[reg_arg] >= 0) { pavone@656: reg_arg = reg_swap[reg_arg]; pavone@656: } pavone@656: if (reg_arg != abi_regs[i]) { pavone@656: if (usage & (1 << abi_regs[i])) { pavone@656: xchg_rr(code, reg_arg, abi_regs[i], SZ_PTR); pavone@656: reg_swap[abi_regs[i]] = reg_arg; pavone@656: } else { pavone@656: mov_rr(code, reg_arg, abi_regs[i], SZ_PTR); pavone@656: } pavone@656: } pavone@656: } else { pavone@656: arg_arr[stack_args++] = reg_arg; pavone@656: } pavone@656: } pavone@656: #else pavone@656: #define stack_args num_args pavone@656: #endif pavone@901: uint32_t stack_off_call = code->stack_off + sizeof(void *) * (stack_args + 1); pavone@894: uint32_t adjust = 0; pavone@894: if (stack_off_call & 0xF) { pavone@894: adjust = 16 - (stack_off_call & 0xF); pavone@894: sub_ir(code, adjust, RSP, SZ_PTR); pavone@894: code->stack_off += adjust; pavone@894: } pavone@901: for (int i = stack_args -1; i >= 0; i--) pavone@901: { pavone@901: push_r(code, arg_arr[i]); pavone@901: } pavone@901: pavone@894: return stack_args * sizeof(void *) + adjust; pavone@207: } pavone@656: pavone@656: void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...) pavone@656: { pavone@656: va_list args; pavone@656: va_start(args, num_args); pavone@656: uint32_t adjust = prep_args(code, num_args, args); pavone@656: va_end(args); pavone@754: call_raxfallback(code, fun); pavone@656: if (adjust) { pavone@656: add_ir(code, adjust, RSP, SZ_PTR); pavone@894: code->stack_off -= adjust; pavone@656: } pavone@656: } pavone@894: /* pavone@656: void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...) pavone@656: { pavone@656: va_list args; pavone@656: va_start(args, num_args); pavone@656: uint32_t adjust = prep_args(code, num_args, args); pavone@656: va_end(args); pavone@656: #ifdef X86_64 pavone@656: test_ir(code, 8, RSP, SZ_PTR); //check stack alignment pavone@656: code_ptr do_adjust_rsp = code->cur + 1; pavone@656: jcc(code, CC_NZ, code->cur + 2); pavone@656: #endif pavone@754: call_raxfallback(code, fun); pavone@656: if (adjust) { pavone@656: add_ir(code, adjust, RSP, SZ_PTR); pavone@656: } pavone@656: #ifdef X86_64 pavone@656: code_ptr no_adjust_rsp = code->cur + 1; pavone@656: jmp(code, code->cur + 2); pavone@656: *do_adjust_rsp = code->cur - (do_adjust_rsp+1); pavone@656: sub_ir(code, 8, RSP, SZ_PTR); pavone@754: call_raxfallback(code, fun); pavone@656: add_ir(code, adjust + 8 , RSP, SZ_PTR); pavone@656: *no_adjust_rsp = code->cur - (no_adjust_rsp+1); pavone@656: #endif pavone@656: } pavone@894: */ pavone@665: void save_callee_save_regs(code_info *code) pavone@665: { pavone@665: push_r(code, RBX); pavone@665: push_r(code, RBP); pavone@665: #ifdef X86_64 pavone@665: push_r(code, R12); pavone@665: push_r(code, R13); pavone@665: push_r(code, R14); pavone@665: push_r(code, R15); pavone@665: #else pavone@665: push_r(code, RDI); pavone@665: push_r(code, RSI); pavone@665: #endif pavone@665: } pavone@665: pavone@665: void restore_callee_save_regs(code_info *code) pavone@665: { pavone@665: #ifdef X86_64 pavone@665: pop_r(code, R15); pavone@665: pop_r(code, R14); pavone@665: pop_r(code, R13); pavone@665: pop_r(code, R12); pavone@665: #else pavone@665: pop_r(code, RSI); pavone@665: pop_r(code, RDI); pavone@665: #endif pavone@665: pop_r(code, RBP); pavone@665: pop_r(code, RBX); pavone@665: } pavone@691: pavone@691: uint8_t has_modrm(uint8_t prefix, uint8_t opcode) pavone@691: { pavone@691: if (!prefix) { pavone@691: switch (opcode) pavone@691: { pavone@691: case OP_JMP: pavone@691: case OP_JMP_BYTE: pavone@691: case OP_JCC: pavone@691: case OP_CALL: pavone@691: case OP_RETN: pavone@691: case OP_LOOP: pavone@691: case OP_MOV_I8R: pavone@691: case OP_MOV_IR: pavone@691: case OP_PUSHF: pavone@691: case OP_POPF: pavone@691: case OP_PUSH: pavone@691: case OP_POP: pavone@691: case OP_CDQ: pavone@691: return 0; pavone@691: } pavone@691: } else if (prefix == PRE_2BYTE) { pavone@691: switch (opcode) pavone@691: { pavone@691: case OP2_JCC: pavone@691: return 0; pavone@691: } pavone@691: } pavone@691: return 1; pavone@691: } pavone@691: pavone@691: uint8_t has_sib(uint8_t mod_rm) pavone@691: { pavone@691: uint8_t mode = mod_rm & 0xC0; pavone@691: uint8_t rm = mod_rm & 3; pavone@691: pavone@691: return mode != MODE_REG_DIRECT && rm == RSP; pavone@691: } pavone@691: pavone@691: uint32_t x86_inst_size(code_ptr start) pavone@691: { pavone@691: code_ptr code = start; pavone@691: uint8_t cont = 1; pavone@691: uint8_t prefix = 0; pavone@691: uint8_t op_size = SZ_B; pavone@691: uint8_t main_op; pavone@691: pavone@691: while (cont) pavone@691: { pavone@691: if (*code == PRE_SIZE) { pavone@691: op_size = SZ_W; pavone@691: } else if (*code == PRE_REX) { pavone@691: if (*code & REX_QUAD) { pavone@691: op_size = SZ_Q; pavone@691: } pavone@755: } else if(*code == PRE_2BYTE || *code == PRE_XOP) { pavone@691: prefix = *code; pavone@691: } else { pavone@691: main_op = *code; pavone@691: cont = 0; pavone@691: } pavone@691: code++; pavone@691: } pavone@691: if (has_modrm(prefix, main_op)) { pavone@691: uint8_t mod_rm = *(code++); pavone@691: if (has_sib(mod_rm)) { pavone@692: //sib takes up a byte, but can't add any additional ones beyond that pavone@692: code++; pavone@692: } pavone@692: uint8_t mode = mod_rm & 0xC0; pavone@692: uint8_t rm = mod_rm & 3; pavone@692: if (mode == MODE_REG_DISPLACE8) { pavone@692: code++; pavone@692: } else if (mode == MODE_REG_DISPLACE32 || (mode == MODE_REG_INDIRECT && rm == RBP)) { pavone@692: code += 4; pavone@691: } pavone@691: } else { pavone@691: } pavone@691: pavone@691: return code-start; pavone@691: }