annotate gen_x86.c @ 989:d70000fdff0b

Implemented IR and undefined bits of info word for address error exception frames
author Michael Pavone <pavone@retrodev.com>
date Wed, 27 Apr 2016 21:39:17 -0700
parents dc71e32091d8
children cd6048e0397b
rev   line source
pavone@467 1 /*
pavone@467 2 Copyright 2013 Michael Pavone
pavone@484 3 This file is part of BlastEm.
pavone@467 4 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 5 */
pavone@14 6 #include "gen_x86.h"
pavone@567 7 #include "mem.h"
pavone@792 8 #include "util.h"
pavone@14 9 #include <stddef.h>
pavone@14 10 #include <stdio.h>
pavone@343 11 #include <stdlib.h>
pavone@656 12 #include <stdarg.h>
pavone@656 13 #include <string.h>
pavone@14 14
pavone@14 15 #define REX_RM_FIELD 0x1
pavone@14 16 #define REX_SIB_FIELD 0x2
pavone@14 17 #define REX_REG_FIELD 0x4
pavone@14 18 #define REX_QUAD 0x8
pavone@14 19
pavone@14 20 #define OP_ADD 0x00
pavone@14 21 #define OP_OR 0x08
pavone@14 22 #define PRE_2BYTE 0x0F
pavone@14 23 #define OP_ADC 0x10
pavone@14 24 #define OP_SBB 0x18
pavone@14 25 #define OP_AND 0x20
pavone@14 26 #define OP_SUB 0x28
pavone@14 27 #define OP_XOR 0x30
pavone@14 28 #define OP_CMP 0x38
pavone@14 29 #define PRE_REX 0x40
pavone@14 30 #define OP_PUSH 0x50
pavone@14 31 #define OP_POP 0x58
pavone@81 32 #define OP_MOVSXD 0x63
pavone@14 33 #define PRE_SIZE 0x66
pavone@14 34 #define OP_JCC 0x70
pavone@14 35 #define OP_IMMED_ARITH 0x80
pavone@484 36 #define OP_TEST 0x84
pavone@241 37 #define OP_XCHG 0x86
pavone@14 38 #define OP_MOV 0x88
pavone@593 39 #define PRE_XOP 0x8F
pavone@241 40 #define OP_XCHG_AX 0x90
pavone@151 41 #define OP_CDQ 0x99
pavone@14 42 #define OP_PUSHF 0x9C
pavone@14 43 #define OP_POPF 0x9D
pavone@14 44 #define OP_MOV_I8R 0xB0
pavone@14 45 #define OP_MOV_IR 0xB8
pavone@49 46 #define OP_SHIFTROT_IR 0xC0
pavone@14 47 #define OP_RETN 0xC3
pavone@15 48 #define OP_MOV_IEA 0xC6
pavone@49 49 #define OP_SHIFTROT_1 0xD0
pavone@51 50 #define OP_SHIFTROT_CL 0xD2
pavone@207 51 #define OP_LOOP 0xE2
pavone@14 52 #define OP_CALL 0xE8
pavone@18 53 #define OP_JMP 0xE9
pavone@18 54 #define OP_JMP_BYTE 0xEB
pavone@82 55 #define OP_NOT_NEG 0xF6
pavone@81 56 #define OP_SINGLE_EA 0xFF
pavone@14 57
pavone@14 58 #define OP2_JCC 0x80
pavone@14 59 #define OP2_SETCC 0x90
pavone@61 60 #define OP2_BT 0xA3
pavone@123 61 #define OP2_BTS 0xAB
pavone@151 62 #define OP2_IMUL 0xAF
pavone@123 63 #define OP2_BTR 0xB3
pavone@61 64 #define OP2_BTX_I 0xBA
pavone@123 65 #define OP2_BTC 0xBB
pavone@81 66 #define OP2_MOVSX 0xBE
pavone@151 67 #define OP2_MOVZX 0xB6
pavone@14 68
pavone@14 69 #define OP_EX_ADDI 0x0
pavone@14 70 #define OP_EX_ORI 0x1
pavone@14 71 #define OP_EX_ADCI 0x2
pavone@14 72 #define OP_EX_SBBI 0x3
pavone@14 73 #define OP_EX_ANDI 0x4
pavone@14 74 #define OP_EX_SUBI 0x5
pavone@14 75 #define OP_EX_XORI 0x6
pavone@14 76 #define OP_EX_CMPI 0x7
pavone@14 77
pavone@49 78 #define OP_EX_ROL 0x0
pavone@49 79 #define OP_EX_ROR 0x1
pavone@49 80 #define OP_EX_RCL 0x2
pavone@49 81 #define OP_EX_RCR 0x3
pavone@49 82 #define OP_EX_SHL 0x4
pavone@49 83 #define OP_EX_SHR 0x5
pavone@49 84 #define OP_EX_SAL 0x6 //identical to SHL
pavone@49 85 #define OP_EX_SAR 0x7
pavone@49 86
pavone@61 87 #define OP_EX_BT 0x4
pavone@61 88 #define OP_EX_BTS 0x5
pavone@61 89 #define OP_EX_BTR 0x6
pavone@61 90 #define OP_EX_BTC 0x7
pavone@61 91
pavone@82 92 #define OP_EX_TEST_I 0x0
pavone@82 93 #define OP_EX_NOT 0x2
pavone@82 94 #define OP_EX_NEG 0x3
pavone@151 95 #define OP_EX_MUL 0x4
pavone@151 96 #define OP_EX_IMUL 0x5
pavone@151 97 #define OP_EX_DIV 0x6
pavone@151 98 #define OP_EX_IDIV 0x7
pavone@82 99
pavone@81 100 #define OP_EX_INC 0x0
pavone@81 101 #define OP_EX_DEC 0x1
pavone@81 102 #define OP_EX_CALL_EA 0x2
pavone@81 103 #define OP_EX_JMP_EA 0x4
pavone@81 104 #define OP_EX_PUSH_EA 0x6
pavone@81 105
pavone@14 106 #define BIT_IMMED_RAX 0x4
pavone@14 107 #define BIT_DIR 0x2
pavone@14 108 #define BIT_SIZE 0x1
pavone@14 109
pavone@14 110
pavone@14 111 enum {
pavone@14 112 X86_RAX = 0,
pavone@14 113 X86_RCX,
pavone@14 114 X86_RDX,
pavone@14 115 X86_RBX,
pavone@14 116 X86_RSP,
pavone@14 117 X86_RBP,
pavone@14 118 X86_RSI,
pavone@14 119 X86_RDI,
pavone@14 120 X86_AH=4,
pavone@14 121 X86_CH,
pavone@14 122 X86_DH,
pavone@14 123 X86_BH,
pavone@14 124 X86_R8=0,
pavone@14 125 X86_R9,
pavone@14 126 X86_R10,
pavone@14 127 X86_R11,
pavone@14 128 X86_R12,
pavone@14 129 X86_R13,
pavone@14 130 X86_R14,
pavone@14 131 X86_R15
pavone@14 132 } x86_regs_enc;
pavone@14 133
pavone@728 134 char * x86_reg_names[] = {
pavone@728 135 #ifdef X86_64
pavone@728 136 "rax",
pavone@728 137 "rcx",
pavone@728 138 "rdx",
pavone@728 139 "rbx",
pavone@728 140 "rsp",
pavone@728 141 "rbp",
pavone@728 142 "rsi",
pavone@728 143 "rdi",
pavone@728 144 #else
pavone@728 145 "eax",
pavone@728 146 "ecx",
pavone@728 147 "edx",
pavone@728 148 "ebx",
pavone@728 149 "esp",
pavone@728 150 "ebp",
pavone@728 151 "esi",
pavone@728 152 "edi",
pavone@728 153 #endif
pavone@728 154 "ah",
pavone@728 155 "ch",
pavone@728 156 "dh",
pavone@728 157 "bh",
pavone@728 158 "r8",
pavone@728 159 "r9",
pavone@728 160 "r10",
pavone@728 161 "r11",
pavone@728 162 "r12",
pavone@728 163 "r13",
pavone@728 164 "r14",
pavone@728 165 "r15",
pavone@728 166 };
pavone@728 167
pavone@728 168 char * x86_sizes[] = {
pavone@728 169 "b", "w", "d", "q"
pavone@728 170 };
pavone@728 171
pavone@567 172 void jmp_nocheck(code_info *code, code_ptr dest)
pavone@14 173 {
pavone@567 174 code_ptr out = code->cur;
pavone@567 175 ptrdiff_t disp = dest-(out+2);
pavone@567 176 if (disp <= 0x7F && disp >= -0x80) {
pavone@567 177 *(out++) = OP_JMP_BYTE;
pavone@567 178 *(out++) = disp;
pavone@567 179 } else {
pavone@567 180 disp = dest-(out+5);
pavone@567 181 if (disp <= 0x7FFFFFFF && disp >= -2147483648) {
pavone@567 182 *(out++) = OP_JMP;
pavone@567 183 *(out++) = disp;
pavone@567 184 disp >>= 8;
pavone@567 185 *(out++) = disp;
pavone@567 186 disp >>= 8;
pavone@567 187 *(out++) = disp;
pavone@567 188 disp >>= 8;
pavone@567 189 *(out++) = disp;
pavone@567 190 } else {
pavone@792 191 fatal_error("jmp: %p - %p = %l which is out of range of a 32-bit displacementX\n", dest, out + 6, (long)disp);
pavone@567 192 }
pavone@567 193 }
pavone@567 194 code->cur = out;
pavone@567 195 }
pavone@567 196
pavone@567 197 void check_alloc_code(code_info *code, uint32_t inst_size)
pavone@567 198 {
pavone@567 199 if (code->cur + inst_size > code->last) {
pavone@567 200 size_t size = CODE_ALLOC_SIZE;
pavone@567 201 code_ptr next_code = alloc_code(&size);
pavone@567 202 if (!next_code) {
pavone@792 203 fatal_error("Failed to allocate memory for generated code\n");
pavone@567 204 }
pavone@567 205 if (next_code != code->last + RESERVE_WORDS) {
pavone@567 206 //new chunk is not contiguous with the current one
pavone@567 207 jmp_nocheck(code, next_code);
pavone@567 208 code->cur = next_code;
pavone@567 209 code->last = next_code + size/sizeof(RESERVE_WORDS);
pavone@567 210 }
pavone@567 211 code->last = next_code + size/sizeof(code_word) - RESERVE_WORDS;
pavone@567 212 }
pavone@567 213 }
pavone@567 214
pavone@567 215 void x86_rr_sizedir(code_info *code, uint16_t opcode, uint8_t src, uint8_t dst, uint8_t size)
pavone@567 216 {
pavone@567 217 check_alloc_code(code, 5);
pavone@567 218 code_ptr out = code->cur;
pavone@14 219 uint8_t tmp;
pavone@14 220 if (size == SZ_W) {
pavone@14 221 *(out++) = PRE_SIZE;
pavone@14 222 }
pavone@14 223 if (size == SZ_B && dst >= RSP && dst <= RDI) {
pavone@14 224 opcode |= BIT_DIR;
pavone@14 225 tmp = dst;
pavone@14 226 dst = src;
pavone@194 227 src = tmp;
pavone@14 228 }
pavone@14 229 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) {
pavone@728 230 #ifdef X86_64
pavone@14 231 *out = PRE_REX;
pavone@267 232 if (src >= AH && src <= BH || dst >= AH && dst <= BH) {
pavone@792 233 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
pavone@267 234 }
pavone@14 235 if (size == SZ_Q) {
pavone@14 236 *out |= REX_QUAD;
pavone@14 237 }
pavone@14 238 if (src >= R8) {
pavone@14 239 *out |= REX_REG_FIELD;
pavone@14 240 src -= (R8 - X86_R8);
pavone@14 241 }
pavone@14 242 if (dst >= R8) {
pavone@14 243 *out |= REX_RM_FIELD;
pavone@14 244 dst -= (R8 - X86_R8);
pavone@14 245 }
pavone@14 246 out++;
pavone@728 247 #else
pavone@792 248 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 249 #endif
pavone@14 250 }
pavone@14 251 if (size == SZ_B) {
pavone@14 252 if (src >= AH && src <= BH) {
pavone@14 253 src -= (AH-X86_AH);
pavone@14 254 }
pavone@14 255 if (dst >= AH && dst <= BH) {
pavone@14 256 dst -= (AH-X86_AH);
pavone@14 257 }
pavone@14 258 } else {
pavone@14 259 opcode |= BIT_SIZE;
pavone@14 260 }
pavone@151 261 if (opcode >= 0x100) {
pavone@151 262 *(out++) = opcode >> 8;
pavone@151 263 *(out++) = opcode;
pavone@151 264 } else {
pavone@151 265 *(out++) = opcode;
pavone@151 266 }
pavone@14 267 *(out++) = MODE_REG_DIRECT | dst | (src << 3);
pavone@567 268 code->cur = out;
pavone@14 269 }
pavone@14 270
pavone@567 271 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 272 {
pavone@567 273 check_alloc_code(code, 10);
pavone@567 274 code_ptr out = code->cur;
pavone@14 275 //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 276 uint8_t tmp;
pavone@14 277 if (size == SZ_W) {
pavone@14 278 *(out++) = PRE_SIZE;
pavone@14 279 }
pavone@14 280 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
pavone@728 281 #ifdef X86_64
pavone@14 282 *out = PRE_REX;
pavone@267 283 if (reg >= AH && reg <= BH) {
pavone@792 284 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
pavone@267 285 }
pavone@14 286 if (size == SZ_Q) {
pavone@14 287 *out |= REX_QUAD;
pavone@14 288 }
pavone@14 289 if (reg >= R8) {
pavone@14 290 *out |= REX_REG_FIELD;
pavone@14 291 reg -= (R8 - X86_R8);
pavone@14 292 }
pavone@14 293 if (base >= R8) {
pavone@14 294 *out |= REX_RM_FIELD;
pavone@14 295 base -= (R8 - X86_R8);
pavone@14 296 }
pavone@14 297 out++;
pavone@728 298 #else
pavone@792 299 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 300 #endif
pavone@14 301 }
pavone@14 302 if (size == SZ_B) {
pavone@14 303 if (reg >= AH && reg <= BH) {
pavone@14 304 reg -= (AH-X86_AH);
pavone@14 305 }
pavone@14 306 } else {
pavone@14 307 opcode |= BIT_SIZE;
pavone@14 308 }
pavone@151 309 opcode |= dir;
pavone@151 310 if (opcode >= 0x100) {
pavone@151 311 *(out++) = opcode >> 8;
pavone@151 312 *(out++) = opcode;
pavone@151 313 } else {
pavone@151 314 *(out++) = opcode;
pavone@151 315 }
pavone@567 316 if (disp < 128 && disp >= -128) {
pavone@14 317 *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3);
pavone@567 318 } else {
pavone@567 319 *(out++) = MODE_REG_DISPLACE32 | base | (reg << 3);
pavone@567 320 }
pavone@18 321 if (base == RSP) {
pavone@18 322 //add SIB byte, with no index and RSP as base
pavone@18 323 *(out++) = (RSP << 3) | RSP;
pavone@18 324 }
pavone@14 325 *(out++) = disp;
pavone@567 326 if (disp >= 128 || disp < -128) {
pavone@343 327 *(out++) = disp >> 8;
pavone@343 328 *(out++) = disp >> 16;
pavone@343 329 *(out++) = disp >> 24;
pavone@567 330 }
pavone@567 331 code->cur = out;
pavone@343 332 }
pavone@343 333
pavone@567 334 void x86_rrind_sizedir(code_info *code, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t size, uint8_t dir)
pavone@14 335 {
pavone@567 336 check_alloc_code(code, 5);
pavone@567 337 code_ptr out = code->cur;
pavone@14 338 //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 339 uint8_t tmp;
pavone@14 340 if (size == SZ_W) {
pavone@14 341 *(out++) = PRE_SIZE;
pavone@14 342 }
pavone@14 343 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
pavone@728 344 #ifdef X86_64
pavone@14 345 *out = PRE_REX;
pavone@267 346 if (reg >= AH && reg <= BH) {
pavone@792 347 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
pavone@267 348 }
pavone@14 349 if (size == SZ_Q) {
pavone@14 350 *out |= REX_QUAD;
pavone@14 351 }
pavone@14 352 if (reg >= R8) {
pavone@14 353 *out |= REX_REG_FIELD;
pavone@14 354 reg -= (R8 - X86_R8);
pavone@14 355 }
pavone@14 356 if (base >= R8) {
pavone@14 357 *out |= REX_RM_FIELD;
pavone@14 358 base -= (R8 - X86_R8);
pavone@14 359 }
pavone@14 360 out++;
pavone@728 361 #else
pavone@792 362 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 363 #endif
pavone@14 364 }
pavone@14 365 if (size == SZ_B) {
pavone@14 366 if (reg >= AH && reg <= BH) {
pavone@14 367 reg -= (AH-X86_AH);
pavone@14 368 }
pavone@14 369 } else {
pavone@14 370 opcode |= BIT_SIZE;
pavone@14 371 }
pavone@14 372 *(out++) = opcode | dir;
pavone@603 373 if (base == RBP) {
pavone@603 374 //add a dummy 8-bit displacement since MODE_REG_INDIRECT with
pavone@603 375 //an R/M field of RBP selects RIP, relative addressing
pavone@603 376 *(out++) = MODE_REG_DISPLACE8 | base | (reg << 3);
pavone@603 377 *(out++) = 0;
pavone@603 378 } else {
pavone@14 379 *(out++) = MODE_REG_INDIRECT | base | (reg << 3);
pavone@18 380 if (base == RSP) {
pavone@18 381 //add SIB byte, with no index and RSP as base
pavone@18 382 *(out++) = (RSP << 3) | RSP;
pavone@18 383 }
pavone@550 384 }
pavone@567 385 code->cur = out;
pavone@14 386 }
pavone@14 387
pavone@567 388 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 389 {
pavone@567 390 check_alloc_code(code, 5);
pavone@567 391 code_ptr out = code->cur;
pavone@343 392 //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 393 uint8_t tmp;
pavone@343 394 if (size == SZ_W) {
pavone@343 395 *(out++) = PRE_SIZE;
pavone@343 396 }
pavone@343 397 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
pavone@728 398 #ifdef X86_64
pavone@343 399 *out = PRE_REX;
pavone@343 400 if (reg >= AH && reg <= BH) {
pavone@792 401 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
pavone@343 402 }
pavone@343 403 if (size == SZ_Q) {
pavone@343 404 *out |= REX_QUAD;
pavone@343 405 }
pavone@343 406 if (reg >= R8) {
pavone@343 407 *out |= REX_REG_FIELD;
pavone@343 408 reg -= (R8 - X86_R8);
pavone@343 409 }
pavone@343 410 if (base >= R8) {
pavone@343 411 *out |= REX_RM_FIELD;
pavone@343 412 base -= (R8 - X86_R8);
pavone@343 413 }
pavone@343 414 if (index >= R8) {
pavone@343 415 *out |= REX_SIB_FIELD;
pavone@343 416 index -= (R8 - X86_R8);
pavone@343 417 }
pavone@343 418 out++;
pavone@728 419 #else
pavone@792 420 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 421 #endif
pavone@343 422 }
pavone@343 423 if (size == SZ_B) {
pavone@343 424 if (reg >= AH && reg <= BH) {
pavone@343 425 reg -= (AH-X86_AH);
pavone@343 426 }
pavone@343 427 } else {
pavone@343 428 opcode |= BIT_SIZE;
pavone@343 429 }
pavone@343 430 *(out++) = opcode | dir;
pavone@560 431 *(out++) = MODE_REG_INDIRECT | RSP | (reg << 3);
pavone@560 432 if (scale == 4) {
pavone@567 433 scale = 2;
pavone@567 434 } else if(scale == 8) {
pavone@682 435 scale = 3;
pavone@567 436 } else {
pavone@567 437 scale--;
pavone@343 438 }
pavone@560 439 *(out++) = scale << 6 | (index << 3) | base;
pavone@567 440 code->cur = out;
pavone@343 441 }
pavone@343 442
pavone@567 443 void x86_r_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, uint8_t size)
pavone@82 444 {
pavone@567 445 check_alloc_code(code, 4);
pavone@567 446 code_ptr out = code->cur;
pavone@82 447 uint8_t tmp;
pavone@82 448 if (size == SZ_W) {
pavone@82 449 *(out++) = PRE_SIZE;
pavone@82 450 }
pavone@82 451 if (size == SZ_Q || dst >= R8) {
pavone@728 452 #ifdef X86_64
pavone@82 453 *out = PRE_REX;
pavone@267 454 if (dst >= AH && dst <= BH) {
pavone@792 455 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
pavone@267 456 }
pavone@82 457 if (size == SZ_Q) {
pavone@82 458 *out |= REX_QUAD;
pavone@82 459 }
pavone@82 460 if (dst >= R8) {
pavone@82 461 *out |= REX_RM_FIELD;
pavone@82 462 dst -= (R8 - X86_R8);
pavone@82 463 }
pavone@82 464 out++;
pavone@728 465 #else
pavone@792 466 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 467 #endif
pavone@82 468 }
pavone@82 469 if (size == SZ_B) {
pavone@82 470 if (dst >= AH && dst <= BH) {
pavone@82 471 dst -= (AH-X86_AH);
pavone@82 472 }
pavone@82 473 } else {
pavone@82 474 opcode |= BIT_SIZE;
pavone@82 475 }
pavone@82 476 *(out++) = opcode;
pavone@82 477 *(out++) = MODE_REG_DIRECT | dst | (opex << 3);
pavone@567 478 code->cur = out;
pavone@82 479 }
pavone@82 480
pavone@567 481 void x86_rdisp_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, int32_t disp, uint8_t size)
pavone@82 482 {
pavone@567 483 check_alloc_code(code, 7);
pavone@567 484 code_ptr out = code->cur;
pavone@82 485 uint8_t tmp;
pavone@82 486 if (size == SZ_W) {
pavone@82 487 *(out++) = PRE_SIZE;
pavone@82 488 }
pavone@82 489 if (size == SZ_Q || dst >= R8) {
pavone@728 490 #ifdef X86_64
pavone@82 491 *out = PRE_REX;
pavone@82 492 if (size == SZ_Q) {
pavone@82 493 *out |= REX_QUAD;
pavone@82 494 }
pavone@82 495 if (dst >= R8) {
pavone@82 496 *out |= REX_RM_FIELD;
pavone@82 497 dst -= (R8 - X86_R8);
pavone@82 498 }
pavone@82 499 out++;
pavone@728 500 #else
pavone@792 501 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 502 #endif
pavone@82 503 }
pavone@82 504 if (size != SZ_B) {
pavone@82 505 opcode |= BIT_SIZE;
pavone@82 506 }
pavone@82 507 *(out++) = opcode;
pavone@567 508 if (disp < 128 && disp >= -128) {
pavone@82 509 *(out++) = MODE_REG_DISPLACE8 | dst | (opex << 3);
pavone@82 510 *(out++) = disp;
pavone@567 511 } else {
pavone@567 512 *(out++) = MODE_REG_DISPLACE32 | dst | (opex << 3);
pavone@567 513 *(out++) = disp;
pavone@567 514 *(out++) = disp >> 8;
pavone@567 515 *(out++) = disp >> 16;
pavone@567 516 *(out++) = disp >> 24;
pavone@567 517 }
pavone@567 518 code->cur = out;
pavone@82 519 }
pavone@82 520
pavone@567 521 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 522 {
pavone@567 523 check_alloc_code(code, 8);
pavone@567 524 code_ptr out = code->cur;
pavone@15 525 uint8_t sign_extend = 0;
pavone@484 526 if (opcode != OP_NOT_NEG && (size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
pavone@15 527 sign_extend = 1;
pavone@15 528 opcode |= BIT_DIR;
pavone@15 529 }
pavone@15 530 if (size == SZ_W) {
pavone@15 531 *(out++) = PRE_SIZE;
pavone@15 532 }
pavone@15 533 if (dst == RAX && !sign_extend) {
pavone@15 534 if (size != SZ_B) {
pavone@15 535 al_opcode |= BIT_SIZE;
pavone@15 536 if (size == SZ_Q) {
pavone@728 537 #ifdef X86_64
pavone@15 538 *out = PRE_REX | REX_QUAD;
pavone@728 539 #else
pavone@792 540 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 541 #endif
pavone@15 542 }
pavone@15 543 }
pavone@14 544 *(out++) = al_opcode | BIT_IMMED_RAX;
pavone@14 545 } else {
pavone@15 546 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
pavone@728 547 #ifdef X86_64
pavone@15 548 *out = PRE_REX;
pavone@15 549 if (size == SZ_Q) {
pavone@15 550 *out |= REX_QUAD;
pavone@15 551 }
pavone@15 552 if (dst >= R8) {
pavone@15 553 *out |= REX_RM_FIELD;
pavone@15 554 dst -= (R8 - X86_R8);
pavone@15 555 }
pavone@15 556 out++;
pavone@728 557 #else
pavone@792 558 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 559 #endif
pavone@15 560 }
pavone@14 561 if (dst >= AH && dst <= BH) {
pavone@14 562 dst -= (AH-X86_AH);
pavone@15 563 }
pavone@15 564 if (size != SZ_B) {
pavone@15 565 opcode |= BIT_SIZE;
pavone@14 566 }
pavone@14 567 *(out++) = opcode;
pavone@14 568 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
pavone@14 569 }
pavone@14 570 *(out++) = val;
pavone@15 571 if (size != SZ_B && !sign_extend) {
pavone@15 572 val >>= 8;
pavone@15 573 *(out++) = val;
pavone@15 574 if (size != SZ_W) {
pavone@15 575 val >>= 8;
pavone@15 576 *(out++) = val;
pavone@15 577 val >>= 8;
pavone@15 578 *(out++) = val;
pavone@15 579 }
pavone@15 580 }
pavone@567 581 code->cur = out;
pavone@14 582 }
pavone@14 583
pavone@567 584 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 585 {
pavone@567 586 check_alloc_code(code, 12);
pavone@567 587 code_ptr out = code->cur;
pavone@18 588 uint8_t sign_extend = 0;
pavone@18 589 if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
pavone@18 590 sign_extend = 1;
pavone@18 591 opcode |= BIT_DIR;
pavone@18 592 }
pavone@18 593 if (size == SZ_W) {
pavone@18 594 *(out++) = PRE_SIZE;
pavone@18 595 }
pavone@18 596
pavone@349 597 if (size == SZ_Q || dst >= R8) {
pavone@728 598 #ifdef X86_64
pavone@18 599 *out = PRE_REX;
pavone@18 600 if (size == SZ_Q) {
pavone@18 601 *out |= REX_QUAD;
pavone@18 602 }
pavone@18 603 if (dst >= R8) {
pavone@18 604 *out |= REX_RM_FIELD;
pavone@18 605 dst -= (R8 - X86_R8);
pavone@18 606 }
pavone@18 607 out++;
pavone@728 608 #else
pavone@792 609 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 610 #endif
pavone@18 611 }
pavone@18 612 if (size != SZ_B) {
pavone@18 613 opcode |= BIT_SIZE;
pavone@18 614 }
pavone@18 615 *(out++) = opcode;
pavone@567 616 if (disp < 128 && disp >= -128) {
pavone@18 617 *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
pavone@18 618 *(out++) = disp;
pavone@567 619 } else {
pavone@682 620 *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
pavone@682 621 *(out++) = disp;
pavone@682 622 disp >>= 8;
pavone@682 623 *(out++) = disp;
pavone@682 624 disp >>= 8;
pavone@682 625 *(out++) = disp;
pavone@682 626 disp >>= 8;
pavone@682 627 *(out++) = disp;
pavone@567 628 }
pavone@18 629 *(out++) = val;
pavone@18 630 if (size != SZ_B && !sign_extend) {
pavone@18 631 val >>= 8;
pavone@18 632 *(out++) = val;
pavone@18 633 if (size != SZ_W) {
pavone@18 634 val >>= 8;
pavone@18 635 *(out++) = val;
pavone@18 636 val >>= 8;
pavone@18 637 *(out++) = val;
pavone@18 638 }
pavone@18 639 }
pavone@567 640 code->cur = out;
pavone@18 641 }
pavone@18 642
pavone@567 643 void x86_shiftrot_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
pavone@420 644 {
pavone@567 645 check_alloc_code(code, 5);
pavone@567 646 code_ptr out = code->cur;
pavone@49 647 if (size == SZ_W) {
pavone@49 648 *(out++) = PRE_SIZE;
pavone@49 649 }
pavone@49 650 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
pavone@49 651 *out = PRE_REX;
pavone@49 652 if (size == SZ_Q) {
pavone@49 653 *out |= REX_QUAD;
pavone@49 654 }
pavone@49 655 if (dst >= R8) {
pavone@49 656 *out |= REX_RM_FIELD;
pavone@49 657 dst -= (R8 - X86_R8);
pavone@49 658 }
pavone@49 659 out++;
pavone@49 660 }
pavone@49 661 if (dst >= AH && dst <= BH) {
pavone@49 662 dst -= (AH-X86_AH);
pavone@49 663 }
pavone@49 664
pavone@49 665 *(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE);
pavone@49 666 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
pavone@49 667 if (val != 1) {
pavone@49 668 *(out++) = val;
pavone@49 669 }
pavone@567 670 code->cur = out;
pavone@49 671 }
pavone@49 672
pavone@567 673 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 674 {
pavone@567 675 check_alloc_code(code, 9);
pavone@567 676 code_ptr out = code->cur;
pavone@49 677 if (size == SZ_W) {
pavone@49 678 *(out++) = PRE_SIZE;
pavone@49 679 }
pavone@349 680 if (size == SZ_Q || dst >= R8) {
pavone@49 681 *out = PRE_REX;
pavone@49 682 if (size == SZ_Q) {
pavone@49 683 *out |= REX_QUAD;
pavone@49 684 }
pavone@49 685 if (dst >= R8) {
pavone@49 686 *out |= REX_RM_FIELD;
pavone@49 687 dst -= (R8 - X86_R8);
pavone@49 688 }
pavone@49 689 out++;
pavone@49 690 }
pavone@49 691 if (dst >= AH && dst <= BH) {
pavone@49 692 dst -= (AH-X86_AH);
pavone@49 693 }
pavone@49 694
pavone@49 695 *(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE);
pavone@567 696 if (disp < 128 && disp >= -128) {
pavone@49 697 *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
pavone@49 698 *(out++) = disp;
pavone@567 699 } else {
pavone@567 700 *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
pavone@567 701 *(out++) = disp;
pavone@567 702 *(out++) = disp >> 8;
pavone@567 703 *(out++) = disp >> 16;
pavone@567 704 *(out++) = disp >> 24;
pavone@567 705 }
pavone@49 706 if (val != 1) {
pavone@49 707 *(out++) = val;
pavone@49 708 }
pavone@567 709 code->cur = out;
pavone@49 710 }
pavone@49 711
pavone@567 712 void x86_shiftrot_clr(code_info *code, uint8_t op_ex, uint8_t dst, uint8_t size)
pavone@51 713 {
pavone@567 714 check_alloc_code(code, 4);
pavone@567 715 code_ptr out = code->cur;
pavone@51 716 if (size == SZ_W) {
pavone@51 717 *(out++) = PRE_SIZE;
pavone@51 718 }
pavone@51 719 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
pavone@51 720 *out = PRE_REX;
pavone@51 721 if (size == SZ_Q) {
pavone@51 722 *out |= REX_QUAD;
pavone@51 723 }
pavone@51 724 if (dst >= R8) {
pavone@51 725 *out |= REX_RM_FIELD;
pavone@51 726 dst -= (R8 - X86_R8);
pavone@51 727 }
pavone@51 728 out++;
pavone@51 729 }
pavone@51 730 if (dst >= AH && dst <= BH) {
pavone@51 731 dst -= (AH-X86_AH);
pavone@51 732 }
pavone@51 733
pavone@51 734 *(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE);
pavone@51 735 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
pavone@567 736 code->cur = out;
pavone@51 737 }
pavone@51 738
pavone@567 739 void x86_shiftrot_clrdisp(code_info *code, uint8_t op_ex, uint8_t dst, int32_t disp, uint8_t size)
pavone@51 740 {
pavone@567 741 check_alloc_code(code, 8);
pavone@567 742 code_ptr out = code->cur;
pavone@51 743 if (size == SZ_W) {
pavone@51 744 *(out++) = PRE_SIZE;
pavone@51 745 }
pavone@349 746 if (size == SZ_Q || dst >= R8) {
pavone@51 747 *out = PRE_REX;
pavone@51 748 if (size == SZ_Q) {
pavone@51 749 *out |= REX_QUAD;
pavone@51 750 }
pavone@51 751 if (dst >= R8) {
pavone@51 752 *out |= REX_RM_FIELD;
pavone@51 753 dst -= (R8 - X86_R8);
pavone@51 754 }
pavone@51 755 out++;
pavone@51 756 }
pavone@51 757 if (dst >= AH && dst <= BH) {
pavone@51 758 dst -= (AH-X86_AH);
pavone@51 759 }
pavone@51 760
pavone@51 761 *(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE);
pavone@567 762 if (disp < 128 && disp >= -128) {
pavone@51 763 *(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
pavone@51 764 *(out++) = disp;
pavone@567 765 } else {
pavone@567 766 *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
pavone@567 767 *(out++) = disp;
pavone@567 768 *(out++) = disp >> 8;
pavone@567 769 *(out++) = disp >> 16;
pavone@567 770 *(out++) = disp >> 24;
pavone@682 771 }
pavone@567 772 code->cur = out;
pavone@51 773 }
pavone@51 774
pavone@567 775 void rol_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 776 {
pavone@567 777 x86_shiftrot_ir(code, OP_EX_ROL, val, dst, size);
pavone@49 778 }
pavone@49 779
pavone@567 780 void ror_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 781 {
pavone@567 782 x86_shiftrot_ir(code, OP_EX_ROR, val, dst, size);
pavone@49 783 }
pavone@49 784
pavone@567 785 void rcl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 786 {
pavone@567 787 x86_shiftrot_ir(code, OP_EX_RCL, val, dst, size);
pavone@49 788 }
pavone@49 789
pavone@567 790 void rcr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 791 {
pavone@567 792 x86_shiftrot_ir(code, OP_EX_RCR, val, dst, size);
pavone@49 793 }
pavone@49 794
pavone@567 795 void shl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 796 {
pavone@567 797 x86_shiftrot_ir(code, OP_EX_SHL, val, dst, size);
pavone@49 798 }
pavone@49 799
pavone@567 800 void shr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 801 {
pavone@567 802 x86_shiftrot_ir(code, OP_EX_SHR, val, dst, size);
pavone@49 803 }
pavone@49 804
pavone@567 805 void sar_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@49 806 {
pavone@567 807 x86_shiftrot_ir(code, OP_EX_SAR, val, dst, size);
pavone@49 808 }
pavone@49 809
pavone@567 810 void rol_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 811 {
pavone@567 812 x86_shiftrot_irdisp(code, OP_EX_ROL, val, dst_base, disp, size);
pavone@49 813 }
pavone@49 814
pavone@567 815 void ror_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 816 {
pavone@567 817 x86_shiftrot_irdisp(code, OP_EX_ROR, val, dst_base, disp, size);
pavone@49 818 }
pavone@49 819
pavone@567 820 void rcl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 821 {
pavone@567 822 x86_shiftrot_irdisp(code, OP_EX_RCL, val, dst_base, disp, size);
pavone@49 823 }
pavone@49 824
pavone@567 825 void rcr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 826 {
pavone@567 827 x86_shiftrot_irdisp(code, OP_EX_RCR, val, dst_base, disp, size);
pavone@49 828 }
pavone@49 829
pavone@567 830 void shl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 831 {
pavone@567 832 x86_shiftrot_irdisp(code, OP_EX_SHL, val, dst_base, disp, size);
pavone@49 833 }
pavone@49 834
pavone@567 835 void shr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 836 {
pavone@567 837 x86_shiftrot_irdisp(code, OP_EX_SHR, val, dst_base, disp, size);
pavone@49 838 }
pavone@49 839
pavone@567 840 void sar_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@49 841 {
pavone@567 842 x86_shiftrot_irdisp(code, OP_EX_SAR, val, dst_base, disp, size);
pavone@49 843 }
pavone@49 844
pavone@567 845 void rol_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 846 {
pavone@567 847 x86_shiftrot_clr(code, OP_EX_ROL, dst, size);
pavone@51 848 }
pavone@51 849
pavone@567 850 void ror_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 851 {
pavone@567 852 x86_shiftrot_clr(code, OP_EX_ROR, dst, size);
pavone@51 853 }
pavone@51 854
pavone@567 855 void rcl_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 856 {
pavone@567 857 x86_shiftrot_clr(code, OP_EX_RCL, dst, size);
pavone@51 858 }
pavone@51 859
pavone@567 860 void rcr_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 861 {
pavone@567 862 x86_shiftrot_clr(code, OP_EX_RCR, dst, size);
pavone@51 863 }
pavone@51 864
pavone@567 865 void shl_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 866 {
pavone@567 867 x86_shiftrot_clr(code, OP_EX_SHL, dst, size);
pavone@51 868 }
pavone@51 869
pavone@567 870 void shr_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 871 {
pavone@567 872 x86_shiftrot_clr(code, OP_EX_SHR, dst, size);
pavone@51 873 }
pavone@51 874
pavone@567 875 void sar_clr(code_info *code, uint8_t dst, uint8_t size)
pavone@51 876 {
pavone@567 877 x86_shiftrot_clr(code, OP_EX_SAR, dst, size);
pavone@51 878 }
pavone@51 879
pavone@567 880 void rol_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 881 {
pavone@567 882 x86_shiftrot_clrdisp(code, OP_EX_ROL, dst_base, disp, size);
pavone@51 883 }
pavone@51 884
pavone@567 885 void ror_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 886 {
pavone@567 887 x86_shiftrot_clrdisp(code, OP_EX_ROR, dst_base, disp, size);
pavone@51 888 }
pavone@51 889
pavone@567 890 void rcl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 891 {
pavone@567 892 x86_shiftrot_clrdisp(code, OP_EX_RCL, dst_base, disp, size);
pavone@51 893 }
pavone@51 894
pavone@567 895 void rcr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 896 {
pavone@567 897 x86_shiftrot_clrdisp(code, OP_EX_RCR, dst_base, disp, size);
pavone@51 898 }
pavone@51 899
pavone@567 900 void shl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 901 {
pavone@567 902 x86_shiftrot_clrdisp(code, OP_EX_SHL, dst_base, disp, size);
pavone@51 903 }
pavone@51 904
pavone@567 905 void shr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 906 {
pavone@567 907 x86_shiftrot_clrdisp(code, OP_EX_SHR, dst_base, disp, size);
pavone@51 908 }
pavone@51 909
pavone@567 910 void sar_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@51 911 {
pavone@567 912 x86_shiftrot_clrdisp(code, OP_EX_SAR, dst_base, disp, size);
pavone@51 913 }
pavone@51 914
pavone@567 915 void add_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@14 916 {
pavone@567 917 x86_rr_sizedir(code, OP_ADD, src, dst, size);
pavone@14 918 }
pavone@14 919
pavone@567 920 void add_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@14 921 {
pavone@567 922 x86_ir(code, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size);
pavone@14 923 }
pavone@14 924
pavone@567 925 void add_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 926 {
pavone@567 927 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADDI, val, dst_base, disp, size);
pavone@18 928 }
pavone@18 929
pavone@567 930 void add_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@420 931 {
pavone@567 932 x86_rrdisp_sizedir(code, OP_ADD, src, dst_base, disp, size, 0);
pavone@420 933 }
pavone@420 934
pavone@567 935 void add_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 936 {
pavone@567 937 x86_rrdisp_sizedir(code, OP_ADD, dst, src_base, disp, size, BIT_DIR);
pavone@18 938 }
pavone@18 939
pavone@567 940 void adc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 941 {
pavone@567 942 x86_rr_sizedir(code, OP_ADC, src, dst, size);
pavone@18 943 }
pavone@18 944
pavone@567 945 void adc_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@146 946 {
pavone@567 947 x86_ir(code, OP_IMMED_ARITH, OP_EX_ADCI, OP_ADC, val, dst, size);
pavone@146 948 }
pavone@146 949
pavone@567 950 void adc_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@146 951 {
pavone@567 952 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADCI, val, dst_base, disp, size);
pavone@146 953 }
pavone@146 954
pavone@567 955 void adc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@146 956 {
pavone@567 957 x86_rrdisp_sizedir(code, OP_ADC, src, dst_base, disp, size, 0);
pavone@146 958 }
pavone@146 959
pavone@567 960 void adc_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@146 961 {
pavone@567 962 x86_rrdisp_sizedir(code, OP_ADC, dst, src_base, disp, size, BIT_DIR);
pavone@146 963 }
pavone@146 964
pavone@567 965 void or_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@146 966 {
pavone@567 967 x86_rr_sizedir(code, OP_OR, src, dst, size);
pavone@567 968 }
pavone@567 969 void or_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@567 970 {
pavone@567 971 x86_ir(code, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size);
pavone@146 972 }
pavone@146 973
pavone@567 974 void or_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 975 {
pavone@567 976 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ORI, val, dst_base, disp, size);
pavone@14 977 }
pavone@14 978
pavone@567 979 void or_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 980 {
pavone@567 981 x86_rrdisp_sizedir(code, OP_OR, src, dst_base, disp, size, 0);
pavone@18 982 }
pavone@18 983
pavone@567 984 void or_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 985 {
pavone@567 986 x86_rrdisp_sizedir(code, OP_OR, dst, src_base, disp, size, BIT_DIR);
pavone@18 987 }
pavone@18 988
pavone@567 989 void and_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 990 {
pavone@567 991 x86_rr_sizedir(code, OP_AND, src, dst, size);
pavone@18 992 }
pavone@18 993
pavone@567 994 void and_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@14 995 {
pavone@567 996 x86_ir(code, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size);
pavone@14 997 }
pavone@14 998
pavone@567 999 void and_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 1000 {
pavone@567 1001 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ANDI, val, dst_base, disp, size);
pavone@14 1002 }
pavone@14 1003
pavone@567 1004 void and_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 1005 {
pavone@567 1006 x86_rrdisp_sizedir(code, OP_AND, src, dst_base, disp, size, 0);
pavone@18 1007 }
pavone@18 1008
pavone@567 1009 void and_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 1010 {
pavone@567 1011 x86_rrdisp_sizedir(code, OP_AND, dst, src_base, disp, size, BIT_DIR);
pavone@18 1012 }
pavone@18 1013
pavone@567 1014 void xor_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 1015 {
pavone@567 1016 x86_rr_sizedir(code, OP_XOR, src, dst, size);
pavone@18 1017 }
pavone@18 1018
pavone@567 1019 void xor_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@14 1020 {
pavone@567 1021 x86_ir(code, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size);
pavone@14 1022 }
pavone@14 1023
pavone@567 1024 void xor_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 1025 {
pavone@567 1026 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_XORI, val, dst_base, disp, size);
pavone@14 1027 }
pavone@14 1028
pavone@567 1029 void xor_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 1030 {
pavone@567 1031 x86_rrdisp_sizedir(code, OP_XOR, src, dst_base, disp, size, 0);
pavone@18 1032 }
pavone@18 1033
pavone@567 1034 void xor_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 1035 {
pavone@567 1036 x86_rrdisp_sizedir(code, OP_XOR, dst, src_base, disp, size, BIT_DIR);
pavone@18 1037 }
pavone@18 1038
pavone@567 1039 void sub_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 1040 {
pavone@567 1041 x86_rr_sizedir(code, OP_SUB, src, dst, size);
pavone@18 1042 }
pavone@18 1043
pavone@567 1044 void sub_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@14 1045 {
pavone@567 1046 x86_ir(code, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size);
pavone@14 1047 }
pavone@14 1048
pavone@567 1049 void sub_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 1050 {
pavone@567 1051 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SUBI, val, dst_base, disp, size);
pavone@14 1052 }
pavone@14 1053
pavone@567 1054 void sub_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 1055 {
pavone@567 1056 x86_rrdisp_sizedir(code, OP_SUB, src, dst_base, disp, size, 0);
pavone@18 1057 }
pavone@18 1058
pavone@567 1059 void sub_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 1060 {
pavone@567 1061 x86_rrdisp_sizedir(code, OP_SUB, dst, src_base, disp, size, BIT_DIR);
pavone@18 1062 }
pavone@18 1063
pavone@567 1064 void sbb_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 1065 {
pavone@567 1066 x86_rr_sizedir(code, OP_SBB, src, dst, size);
pavone@18 1067 }
pavone@18 1068
pavone@567 1069 void sbb_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@146 1070 {
pavone@567 1071 x86_ir(code, OP_IMMED_ARITH, OP_EX_SBBI, OP_SBB, val, dst, size);
pavone@146 1072 }
pavone@146 1073
pavone@567 1074 void sbb_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@146 1075 {
pavone@567 1076 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SBBI, val, dst_base, disp, size);
pavone@146 1077 }
pavone@146 1078
pavone@567 1079 void sbb_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@146 1080 {
pavone@567 1081 x86_rrdisp_sizedir(code, OP_SBB, src, dst_base, disp, size, 0);
pavone@146 1082 }
pavone@146 1083
pavone@567 1084 void sbb_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@146 1085 {
pavone@567 1086 x86_rrdisp_sizedir(code, OP_SBB, dst, src_base, disp, size, BIT_DIR);
pavone@146 1087 }
pavone@146 1088
pavone@567 1089 void cmp_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@146 1090 {
pavone@567 1091 x86_rr_sizedir(code, OP_CMP, src, dst, size);
pavone@146 1092 }
pavone@146 1093
pavone@567 1094 void cmp_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@14 1095 {
pavone@567 1096 x86_ir(code, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size);
pavone@14 1097 }
pavone@14 1098
pavone@567 1099 void cmp_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 1100 {
pavone@567 1101 x86_irdisp(code, OP_IMMED_ARITH, OP_EX_CMPI, val, dst_base, disp, size);
pavone@14 1102 }
pavone@14 1103
pavone@567 1104 void cmp_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@18 1105 {
pavone@567 1106 x86_rrdisp_sizedir(code, OP_CMP, src, dst_base, disp, size, 0);
pavone@18 1107 }
pavone@18 1108
pavone@567 1109 void cmp_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@18 1110 {
pavone@567 1111 x86_rrdisp_sizedir(code, OP_CMP, dst, src_base, disp, size, BIT_DIR);
pavone@18 1112 }
pavone@18 1113
pavone@567 1114 void test_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@18 1115 {
pavone@567 1116 x86_rr_sizedir(code, OP_TEST, src, dst, size);
pavone@18 1117 }
pavone@18 1118
pavone@567 1119 void test_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@484 1120 {
pavone@567 1121 x86_ir(code, OP_NOT_NEG, OP_EX_TEST_I, OP_TEST, val, dst, size);
pavone@484 1122 }
pavone@484 1123
pavone@567 1124 void test_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@484 1125 {
pavone@567 1126 x86_irdisp(code, OP_NOT_NEG, OP_EX_TEST_I, val, dst_base, disp, size);
pavone@484 1127 }
pavone@484 1128
pavone@567 1129 void test_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@484 1130 {
pavone@567 1131 x86_rrdisp_sizedir(code, OP_TEST, src, dst_base, disp, size, 0);
pavone@484 1132 }
pavone@484 1133
pavone@567 1134 void test_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@484 1135 {
pavone@567 1136 x86_rrdisp_sizedir(code, OP_TEST, dst, src_base, disp, size, BIT_DIR);
pavone@484 1137 }
pavone@484 1138
pavone@567 1139 void imul_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@484 1140 {
pavone@567 1141 x86_rr_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src, size);
pavone@484 1142 }
pavone@484 1143
pavone@567 1144 void imul_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@151 1145 {
pavone@567 1146 x86_rrdisp_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src_base, disp, size, 0);
pavone@151 1147 }
pavone@151 1148
pavone@567 1149 void not_r(code_info *code, uint8_t dst, uint8_t size)
pavone@151 1150 {
pavone@567 1151 x86_r_size(code, OP_NOT_NEG, OP_EX_NOT, dst, size);
pavone@151 1152 }
pavone@151 1153
pavone@567 1154 void neg_r(code_info *code, uint8_t dst, uint8_t size)
pavone@82 1155 {
pavone@567 1156 x86_r_size(code, OP_NOT_NEG, OP_EX_NEG, dst, size);
pavone@82 1157 }
pavone@82 1158
pavone@567 1159 void not_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@82 1160 {
pavone@567 1161 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NOT, dst_base, disp, size);
pavone@82 1162 }
pavone@82 1163
pavone@567 1164 void neg_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@82 1165 {
pavone@567 1166 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size);
pavone@82 1167 }
pavone@82 1168
pavone@567 1169 void mul_r(code_info *code, uint8_t dst, uint8_t size)
pavone@82 1170 {
pavone@567 1171 x86_r_size(code, OP_NOT_NEG, OP_EX_MUL, dst, size);
pavone@82 1172 }
pavone@82 1173
pavone@567 1174 void imul_r(code_info *code, uint8_t dst, uint8_t size)
pavone@151 1175 {
pavone@567 1176 x86_r_size(code, OP_NOT_NEG, OP_EX_IMUL, dst, size);
pavone@151 1177 }
pavone@151 1178
pavone@567 1179 void div_r(code_info *code, uint8_t dst, uint8_t size)
pavone@151 1180 {
pavone@567 1181 x86_r_size(code, OP_NOT_NEG, OP_EX_DIV, dst, size);
pavone@151 1182 }
pavone@151 1183
pavone@567 1184 void idiv_r(code_info *code, uint8_t dst, uint8_t size)
pavone@151 1185 {
pavone@567 1186 x86_r_size(code, OP_NOT_NEG, OP_EX_IDIV, dst, size);
pavone@151 1187 }
pavone@151 1188
pavone@567 1189 void mul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@151 1190 {
pavone@567 1191 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_MUL, dst_base, disp, size);
pavone@151 1192 }
pavone@151 1193
pavone@567 1194 void imul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@151 1195 {
pavone@567 1196 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IMUL, dst_base, disp, size);
pavone@151 1197 }
pavone@151 1198
pavone@567 1199 void div_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@151 1200 {
pavone@567 1201 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_DIV, dst_base, disp, size);
pavone@151 1202 }
pavone@151 1203
pavone@567 1204 void idiv_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@151 1205 {
pavone@567 1206 x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IDIV, dst_base, disp, size);
pavone@151 1207 }
pavone@151 1208
pavone@567 1209 void mov_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@151 1210 {
pavone@567 1211 x86_rr_sizedir(code, OP_MOV, src, dst, size);
pavone@151 1212 }
pavone@151 1213
pavone@567 1214 void mov_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
pavone@14 1215 {
pavone@567 1216 x86_rrdisp_sizedir(code, OP_MOV, src, dst_base, disp, size, 0);
pavone@14 1217 }
pavone@14 1218
pavone@567 1219 void mov_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
pavone@14 1220 {
pavone@567 1221 x86_rrdisp_sizedir(code, OP_MOV, dst, src_base, disp, size, BIT_DIR);
pavone@14 1222 }
pavone@14 1223
pavone@567 1224 void mov_rrind(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@14 1225 {
pavone@567 1226 x86_rrind_sizedir(code, OP_MOV, src, dst, size, 0);
pavone@14 1227 }
pavone@14 1228
pavone@567 1229 void mov_rindr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@343 1230 {
pavone@567 1231 x86_rrind_sizedir(code, OP_MOV, dst, src, size, BIT_DIR);
pavone@343 1232 }
pavone@343 1233
pavone@567 1234 void mov_rrindex(code_info *code, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size)
pavone@343 1235 {
pavone@567 1236 x86_rrindex_sizedir(code, OP_MOV, src, dst_base, dst_index, scale, size, 0);
pavone@343 1237 }
pavone@343 1238
pavone@567 1239 void mov_rindexr(code_info *code, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size)
pavone@14 1240 {
pavone@567 1241 x86_rrindex_sizedir(code, OP_MOV, dst, src_base, src_index, scale, size, BIT_DIR);
pavone@14 1242 }
pavone@14 1243
pavone@567 1244 void mov_ir(code_info *code, int64_t val, uint8_t dst, uint8_t size)
pavone@14 1245 {
pavone@567 1246 check_alloc_code(code, 14);
pavone@567 1247 code_ptr out = code->cur;
pavone@15 1248 uint8_t sign_extend = 0;
pavone@15 1249 if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) {
pavone@15 1250 sign_extend = 1;
pavone@15 1251 }
pavone@15 1252 if (size == SZ_W) {
pavone@15 1253 *(out++) = PRE_SIZE;
pavone@15 1254 }
pavone@15 1255 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
pavone@15 1256 *out = PRE_REX;
pavone@15 1257 if (size == SZ_Q) {
pavone@15 1258 *out |= REX_QUAD;
pavone@15 1259 }
pavone@15 1260 if (dst >= R8) {
pavone@15 1261 *out |= REX_RM_FIELD;
pavone@15 1262 dst -= (R8 - X86_R8);
pavone@15 1263 }
pavone@15 1264 out++;
pavone@15 1265 }
pavone@14 1266 if (dst >= AH && dst <= BH) {
pavone@15 1267 dst -= (AH-X86_AH);
pavone@14 1268 }
pavone@15 1269 if (size == SZ_B) {
pavone@18 1270 *(out++) = OP_MOV_I8R | dst;
pavone@15 1271 } else if (size == SZ_Q && sign_extend) {
pavone@15 1272 *(out++) = OP_MOV_IEA | BIT_SIZE;
pavone@15 1273 *(out++) = MODE_REG_DIRECT | dst;
pavone@15 1274 } else {
pavone@18 1275 *(out++) = OP_MOV_IR | dst;
pavone@15 1276 }
pavone@14 1277 *(out++) = val;
pavone@15 1278 if (size != SZ_B) {
pavone@15 1279 val >>= 8;
pavone@15 1280 *(out++) = val;
pavone@15 1281 if (size != SZ_W) {
pavone@15 1282 val >>= 8;
pavone@15 1283 *(out++) = val;
pavone@15 1284 val >>= 8;
pavone@15 1285 *(out++) = val;
pavone@15 1286 if (size == SZ_Q && !sign_extend) {
pavone@15 1287 val >>= 8;
pavone@15 1288 *(out++) = val;
pavone@15 1289 val >>= 8;
pavone@15 1290 *(out++) = val;
pavone@15 1291 val >>= 8;
pavone@15 1292 *(out++) = val;
pavone@15 1293 val >>= 8;
pavone@15 1294 *(out++) = val;
pavone@15 1295 }
pavone@15 1296 }
pavone@14 1297 }
pavone@567 1298 code->cur = out;
pavone@14 1299 }
pavone@14 1300
pavone@567 1301 void mov_irdisp(code_info *code, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
pavone@18 1302 {
pavone@567 1303 check_alloc_code(code, 12);
pavone@567 1304 code_ptr out = code->cur;
pavone@18 1305 if (size == SZ_W) {
pavone@18 1306 *(out++) = PRE_SIZE;
pavone@18 1307 }
pavone@349 1308 if (size == SZ_Q || dst >= R8) {
pavone@18 1309 *out = PRE_REX;
pavone@18 1310 if (size == SZ_Q) {
pavone@18 1311 *out |= REX_QUAD;
pavone@18 1312 }
pavone@18 1313 if (dst >= R8) {
pavone@18 1314 *out |= REX_RM_FIELD;
pavone@18 1315 dst -= (R8 - X86_R8);
pavone@18 1316 }
pavone@18 1317 out++;
pavone@18 1318 }
pavone@18 1319 if (dst >= AH && dst <= BH) {
pavone@18 1320 dst -= (AH-X86_AH);
pavone@18 1321 }
pavone@18 1322 *(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE);
pavone@567 1323 if (disp < 128 && disp >= -128) {
pavone@18 1324 *(out++) = MODE_REG_DISPLACE8 | dst;
pavone@18 1325 *(out++) = disp;
pavone@567 1326 } else {
pavone@567 1327 *(out++) = MODE_REG_DISPLACE32 | dst;
pavone@567 1328 *(out++) = disp;
pavone@567 1329 *(out++) = disp >> 8;
pavone@567 1330 *(out++) = disp >> 16;
pavone@567 1331 *(out++) = disp >> 24;
pavone@567 1332 }
pavone@18 1333
pavone@18 1334 *(out++) = val;
pavone@18 1335 if (size != SZ_B) {
pavone@18 1336 val >>= 8;
pavone@18 1337 *(out++) = val;
pavone@18 1338 if (size != SZ_W) {
pavone@18 1339 val >>= 8;
pavone@18 1340 *(out++) = val;
pavone@18 1341 val >>= 8;
pavone@18 1342 *(out++) = val;
pavone@18 1343 }
pavone@18 1344 }
pavone@567 1345 code->cur = out;
pavone@18 1346 }
pavone@18 1347
pavone@567 1348 void mov_irind(code_info *code, int32_t val, uint8_t dst, uint8_t size)
pavone@71 1349 {
pavone@567 1350 check_alloc_code(code, 8);
pavone@567 1351 code_ptr out = code->cur;
pavone@71 1352 if (size == SZ_W) {
pavone@71 1353 *(out++) = PRE_SIZE;
pavone@71 1354 }
pavone@71 1355 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
pavone@71 1356 *out = PRE_REX;
pavone@71 1357 if (size == SZ_Q) {
pavone@71 1358 *out |= REX_QUAD;
pavone@71 1359 }
pavone@71 1360 if (dst >= R8) {
pavone@71 1361 *out |= REX_RM_FIELD;
pavone@71 1362 dst -= (R8 - X86_R8);
pavone@71 1363 }
pavone@71 1364 out++;
pavone@71 1365 }
pavone@71 1366 if (dst >= AH && dst <= BH) {
pavone@71 1367 dst -= (AH-X86_AH);
pavone@71 1368 }
pavone@71 1369 *(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE);
pavone@71 1370 *(out++) = MODE_REG_INDIRECT | dst;
pavone@71 1371
pavone@71 1372 *(out++) = val;
pavone@71 1373 if (size != SZ_B) {
pavone@71 1374 val >>= 8;
pavone@71 1375 *(out++) = val;
pavone@71 1376 if (size != SZ_W) {
pavone@71 1377 val >>= 8;
pavone@71 1378 *(out++) = val;
pavone@71 1379 val >>= 8;
pavone@71 1380 *(out++) = val;
pavone@71 1381 }
pavone@71 1382 }
pavone@567 1383 code->cur = out;
pavone@71 1384 }
pavone@71 1385
pavone@567 1386 void movsx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size)
pavone@81 1387 {
pavone@567 1388 check_alloc_code(code, 5);
pavone@567 1389 code_ptr out = code->cur;
pavone@81 1390 if (size == SZ_W) {
pavone@81 1391 *(out++) = PRE_SIZE;
pavone@81 1392 }
pavone@81 1393 if (size == SZ_Q || dst >= R8 || src >= R8) {
pavone@81 1394 *out = PRE_REX;
pavone@81 1395 if (size == SZ_Q) {
pavone@81 1396 *out |= REX_QUAD;
pavone@81 1397 }
pavone@81 1398 if (src >= R8) {
pavone@125 1399 *out |= REX_RM_FIELD;
pavone@81 1400 src -= (R8 - X86_R8);
pavone@81 1401 }
pavone@81 1402 if (dst >= R8) {
pavone@125 1403 *out |= REX_REG_FIELD;
pavone@81 1404 dst -= (R8 - X86_R8);
pavone@81 1405 }
pavone@81 1406 out++;
pavone@81 1407 }
pavone@81 1408 if (src_size == SZ_D) {
pavone@81 1409 *(out++) = OP_MOVSXD;
pavone@81 1410 } else {
pavone@81 1411 *(out++) = PRE_2BYTE;
pavone@81 1412 *(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
pavone@81 1413 }
pavone@81 1414 *(out++) = MODE_REG_DIRECT | src | (dst << 3);
pavone@567 1415 code->cur = out;
pavone@81 1416 }
pavone@81 1417
pavone@567 1418 void movsx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size)
pavone@81 1419 {
pavone@567 1420 check_alloc_code(code, 12);
pavone@567 1421 code_ptr out = code->cur;
pavone@81 1422 if (size == SZ_W) {
pavone@81 1423 *(out++) = PRE_SIZE;
pavone@81 1424 }
pavone@81 1425 if (size == SZ_Q || dst >= R8 || src >= R8) {
pavone@81 1426 *out = PRE_REX;
pavone@81 1427 if (size == SZ_Q) {
pavone@81 1428 *out |= REX_QUAD;
pavone@81 1429 }
pavone@81 1430 if (src >= R8) {
pavone@125 1431 *out |= REX_RM_FIELD;
pavone@81 1432 src -= (R8 - X86_R8);
pavone@81 1433 }
pavone@81 1434 if (dst >= R8) {
pavone@125 1435 *out |= REX_REG_FIELD;
pavone@81 1436 dst -= (R8 - X86_R8);
pavone@81 1437 }
pavone@81 1438 out++;
pavone@81 1439 }
pavone@81 1440 if (src_size == SZ_D) {
pavone@81 1441 *(out++) = OP_MOVSXD;
pavone@81 1442 } else {
pavone@81 1443 *(out++) = PRE_2BYTE;
pavone@81 1444 *(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
pavone@81 1445 }
pavone@567 1446 if (disp < 128 && disp >= -128) {
pavone@81 1447 *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3);
pavone@81 1448 *(out++) = disp;
pavone@567 1449 } else {
pavone@567 1450 *(out++) = MODE_REG_DISPLACE32 | src | (dst << 3);
pavone@567 1451 *(out++) = disp;
pavone@567 1452 *(out++) = disp >> 8;
pavone@567 1453 *(out++) = disp >> 16;
pavone@567 1454 *(out++) = disp >> 24;
pavone@567 1455 }
pavone@567 1456 code->cur = out;
pavone@81 1457 }
pavone@81 1458
pavone@567 1459 void movzx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size)
pavone@151 1460 {
pavone@567 1461 check_alloc_code(code, 5);
pavone@567 1462 code_ptr out = code->cur;
pavone@151 1463 if (size == SZ_W) {
pavone@151 1464 *(out++) = PRE_SIZE;
pavone@151 1465 }
pavone@151 1466 if (size == SZ_Q || dst >= R8 || src >= R8) {
pavone@151 1467 *out = PRE_REX;
pavone@151 1468 if (size == SZ_Q) {
pavone@151 1469 *out |= REX_QUAD;
pavone@151 1470 }
pavone@151 1471 if (src >= R8) {
pavone@151 1472 *out |= REX_RM_FIELD;
pavone@151 1473 src -= (R8 - X86_R8);
pavone@151 1474 }
pavone@151 1475 if (dst >= R8) {
pavone@151 1476 *out |= REX_REG_FIELD;
pavone@151 1477 dst -= (R8 - X86_R8);
pavone@151 1478 }
pavone@151 1479 out++;
pavone@151 1480 }
pavone@151 1481 *(out++) = PRE_2BYTE;
pavone@151 1482 *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE);
pavone@151 1483 *(out++) = MODE_REG_DIRECT | src | (dst << 3);
pavone@567 1484 code->cur = out;
pavone@151 1485 }
pavone@151 1486
pavone@567 1487 void movzx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size)
pavone@151 1488 {
pavone@567 1489 check_alloc_code(code, 9);
pavone@567 1490 code_ptr out = code->cur;
pavone@151 1491 if (size == SZ_W) {
pavone@151 1492 *(out++) = PRE_SIZE;
pavone@151 1493 }
pavone@151 1494 if (size == SZ_Q || dst >= R8 || src >= R8) {
pavone@151 1495 *out = PRE_REX;
pavone@151 1496 if (size == SZ_Q) {
pavone@151 1497 *out |= REX_QUAD;
pavone@151 1498 }
pavone@151 1499 if (src >= R8) {
pavone@151 1500 *out |= REX_RM_FIELD;
pavone@151 1501 src -= (R8 - X86_R8);
pavone@151 1502 }
pavone@151 1503 if (dst >= R8) {
pavone@151 1504 *out |= REX_REG_FIELD;
pavone@151 1505 dst -= (R8 - X86_R8);
pavone@151 1506 }
pavone@151 1507 out++;
pavone@151 1508 }
pavone@151 1509 *(out++) = PRE_2BYTE;
pavone@151 1510 *(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE);
pavone@567 1511 if (disp < 128 && disp >= -128) {
pavone@151 1512 *(out++) = MODE_REG_DISPLACE8 | src | (dst << 3);
pavone@151 1513 *(out++) = disp;
pavone@567 1514 } else {
pavone@567 1515 *(out++) = MODE_REG_DISPLACE32 | src | (dst << 3);
pavone@567 1516 *(out++) = disp;
pavone@567 1517 *(out++) = disp >> 8;
pavone@567 1518 *(out++) = disp >> 16;
pavone@567 1519 *(out++) = disp >> 24;
pavone@567 1520 }
pavone@567 1521 code->cur = out;
pavone@151 1522 }
pavone@151 1523
pavone@567 1524 void xchg_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@241 1525 {
pavone@567 1526 check_alloc_code(code, 4);
pavone@567 1527 code_ptr out = code->cur;
pavone@241 1528 //TODO: Use OP_XCHG_AX when one of the registers is AX, EAX or RAX
pavone@241 1529 uint8_t tmp;
pavone@241 1530 if (size == SZ_W) {
pavone@241 1531 *(out++) = PRE_SIZE;
pavone@241 1532 }
pavone@241 1533 if (size == SZ_B && dst >= RSP && dst <= RDI) {
pavone@241 1534 tmp = dst;
pavone@241 1535 dst = src;
pavone@241 1536 src = tmp;
pavone@241 1537 }
pavone@241 1538 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) {
pavone@241 1539 *out = PRE_REX;
pavone@241 1540 if (size == SZ_Q) {
pavone@241 1541 *out |= REX_QUAD;
pavone@241 1542 }
pavone@241 1543 if (src >= R8) {
pavone@241 1544 *out |= REX_REG_FIELD;
pavone@241 1545 src -= (R8 - X86_R8);
pavone@241 1546 }
pavone@241 1547 if (dst >= R8) {
pavone@241 1548 *out |= REX_RM_FIELD;
pavone@241 1549 dst -= (R8 - X86_R8);
pavone@241 1550 }
pavone@241 1551 out++;
pavone@241 1552 }
pavone@241 1553 uint8_t opcode = OP_XCHG;
pavone@241 1554 if (size == SZ_B) {
pavone@241 1555 if (src >= AH && src <= BH) {
pavone@241 1556 src -= (AH-X86_AH);
pavone@241 1557 }
pavone@241 1558 if (dst >= AH && dst <= BH) {
pavone@241 1559 dst -= (AH-X86_AH);
pavone@241 1560 }
pavone@241 1561 } else {
pavone@241 1562 opcode |= BIT_SIZE;
pavone@241 1563 }
pavone@241 1564 *(out++) = opcode;
pavone@241 1565 *(out++) = MODE_REG_DIRECT | dst | (src << 3);
pavone@567 1566 code->cur = out;
pavone@241 1567 }
pavone@241 1568
pavone@567 1569 void pushf(code_info *code)
pavone@14 1570 {
pavone@567 1571 check_alloc_code(code, 1);
pavone@567 1572 code_ptr out = code->cur;
pavone@14 1573 *(out++) = OP_PUSHF;
pavone@567 1574 code->cur = out;
pavone@14 1575 }
pavone@14 1576
pavone@567 1577 void popf(code_info *code)
pavone@14 1578 {
pavone@567 1579 check_alloc_code(code, 1);
pavone@567 1580 code_ptr out = code->cur;
pavone@14 1581 *(out++) = OP_POPF;
pavone@567 1582 code->cur = out;
pavone@14 1583 }
pavone@14 1584
pavone@567 1585 void push_r(code_info *code, uint8_t reg)
pavone@14 1586 {
pavone@567 1587 check_alloc_code(code, 2);
pavone@567 1588 code_ptr out = code->cur;
pavone@14 1589 if (reg >= R8) {
pavone@14 1590 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@14 1591 reg -= R8 - X86_R8;
pavone@14 1592 }
pavone@14 1593 *(out++) = OP_PUSH | reg;
pavone@567 1594 code->cur = out;
pavone@894 1595 code->stack_off += sizeof(void *);
pavone@14 1596 }
pavone@14 1597
pavone@593 1598 void push_rdisp(code_info *code, uint8_t base, int32_t disp)
pavone@14 1599 {
pavone@593 1600 //This instruction has no explicit size, so we pass SZ_B
pavone@593 1601 //to avoid any prefixes or bits being set
pavone@593 1602 x86_rdisp_size(code, OP_SINGLE_EA, OP_EX_PUSH_EA, base, disp, SZ_B);
pavone@894 1603 code->stack_off += sizeof(void *);
pavone@593 1604 }
pavone@593 1605
pavone@567 1606 void pop_r(code_info *code, uint8_t reg)
pavone@550 1607 {
pavone@567 1608 check_alloc_code(code, 2);
pavone@567 1609 code_ptr out = code->cur;
pavone@14 1610 if (reg >= R8) {
pavone@14 1611 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@14 1612 reg -= R8 - X86_R8;
pavone@14 1613 }
pavone@14 1614 *(out++) = OP_POP | reg;
pavone@567 1615 code->cur = out;
pavone@894 1616 code->stack_off -= sizeof(void *);
pavone@14 1617 }
pavone@14 1618
pavone@593 1619 void pop_rind(code_info *code, uint8_t reg)
pavone@14 1620 {
pavone@593 1621 check_alloc_code(code, 3);
pavone@593 1622 code_ptr out = code->cur;
pavone@593 1623 if (reg >= R8) {
pavone@593 1624 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@593 1625 reg -= R8 - X86_R8;
pavone@593 1626 }
pavone@593 1627 *(out++) = PRE_XOP;
pavone@593 1628 *(out++) = MODE_REG_INDIRECT | reg;
pavone@593 1629 code->cur = out;
pavone@894 1630 code->stack_off -= sizeof(void *);
pavone@593 1631 }
pavone@593 1632
pavone@567 1633 void setcc_r(code_info *code, uint8_t cc, uint8_t dst)
pavone@550 1634 {
pavone@567 1635 check_alloc_code(code, 4);
pavone@567 1636 code_ptr out = code->cur;
pavone@14 1637 if (dst >= R8) {
pavone@14 1638 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@14 1639 dst -= R8 - X86_R8;
pavone@14 1640 } else if (dst >= RSP && dst <= RDI) {
pavone@14 1641 *(out++) = PRE_REX;
pavone@14 1642 } else if (dst >= AH && dst <= BH) {
pavone@14 1643 dst -= AH - X86_AH;
pavone@14 1644 }
pavone@14 1645 *(out++) = PRE_2BYTE;
pavone@14 1646 *(out++) = OP2_SETCC | cc;
pavone@14 1647 *(out++) = MODE_REG_DIRECT | dst;
pavone@567 1648 code->cur = out;
pavone@14 1649 }
pavone@14 1650
pavone@567 1651 void setcc_rind(code_info *code, uint8_t cc, uint8_t dst)
pavone@14 1652 {
pavone@567 1653 check_alloc_code(code, 4);
pavone@567 1654 code_ptr out = code->cur;
pavone@14 1655 if (dst >= R8) {
pavone@14 1656 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@14 1657 dst -= R8 - X86_R8;
pavone@14 1658 }
pavone@14 1659 *(out++) = PRE_2BYTE;
pavone@14 1660 *(out++) = OP2_SETCC | cc;
pavone@14 1661 *(out++) = MODE_REG_INDIRECT | dst;
pavone@567 1662 code->cur = out;
pavone@14 1663 }
pavone@14 1664
pavone@567 1665 void setcc_rdisp(code_info *code, uint8_t cc, uint8_t dst, int32_t disp)
pavone@112 1666 {
pavone@567 1667 check_alloc_code(code, 8);
pavone@567 1668 code_ptr out = code->cur;
pavone@112 1669 if (dst >= R8) {
pavone@112 1670 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@112 1671 dst -= R8 - X86_R8;
pavone@112 1672 }
pavone@112 1673 *(out++) = PRE_2BYTE;
pavone@112 1674 *(out++) = OP2_SETCC | cc;
pavone@567 1675 if (disp < 128 && disp >= -128) {
pavone@112 1676 *(out++) = MODE_REG_DISPLACE8 | dst;
pavone@112 1677 *(out++) = disp;
pavone@567 1678 } else {
pavone@567 1679 *(out++) = MODE_REG_DISPLACE32 | dst;
pavone@567 1680 *(out++) = disp;
pavone@567 1681 *(out++) = disp >> 8;
pavone@567 1682 *(out++) = disp >> 16;
pavone@567 1683 *(out++) = disp >> 24;
pavone@567 1684 }
pavone@567 1685 code->cur = out;
pavone@112 1686 }
pavone@112 1687
pavone@567 1688 void bit_rr(code_info *code, uint8_t op2, uint8_t src, uint8_t dst, uint8_t size)
pavone@61 1689 {
pavone@567 1690 check_alloc_code(code, 5);
pavone@567 1691 code_ptr out = code->cur;
pavone@61 1692 if (size == SZ_W) {
pavone@61 1693 *(out++) = PRE_SIZE;
pavone@61 1694 }
pavone@61 1695 if (size == SZ_Q || src >= R8 || dst >= R8) {
pavone@61 1696 *out = PRE_REX;
pavone@61 1697 if (size == SZ_Q) {
pavone@61 1698 *out |= REX_QUAD;
pavone@61 1699 }
pavone@61 1700 if (src >= R8) {
pavone@61 1701 *out |= REX_REG_FIELD;
pavone@61 1702 src -= (R8 - X86_R8);
pavone@61 1703 }
pavone@61 1704 if (dst >= R8) {
pavone@61 1705 *out |= REX_RM_FIELD;
pavone@61 1706 dst -= (R8 - X86_R8);
pavone@61 1707 }
pavone@61 1708 out++;
pavone@61 1709 }
pavone@61 1710 *(out++) = PRE_2BYTE;
pavone@123 1711 *(out++) = op2;
pavone@61 1712 *(out++) = MODE_REG_DIRECT | dst | (src << 3);
pavone@567 1713 code->cur = out;
pavone@61 1714 }
pavone@61 1715
pavone@567 1716 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 1717 {
pavone@567 1718 check_alloc_code(code, 9);
pavone@567 1719 code_ptr out = code->cur;
pavone@61 1720 if (size == SZ_W) {
pavone@61 1721 *(out++) = PRE_SIZE;
pavone@61 1722 }
pavone@61 1723 if (size == SZ_Q || src >= R8 || dst_base >= R8) {
pavone@61 1724 *out = PRE_REX;
pavone@61 1725 if (size == SZ_Q) {
pavone@61 1726 *out |= REX_QUAD;
pavone@61 1727 }
pavone@61 1728 if (src >= R8) {
pavone@61 1729 *out |= REX_REG_FIELD;
pavone@61 1730 src -= (R8 - X86_R8);
pavone@61 1731 }
pavone@61 1732 if (dst_base >= R8) {
pavone@61 1733 *out |= REX_RM_FIELD;
pavone@61 1734 dst_base -= (R8 - X86_R8);
pavone@61 1735 }
pavone@61 1736 out++;
pavone@61 1737 }
pavone@61 1738 *(out++) = PRE_2BYTE;
pavone@123 1739 *(out++) = op2;
pavone@567 1740 if (dst_disp < 128 && dst_disp >= -128) {
pavone@61 1741 *(out++) = MODE_REG_DISPLACE8 | dst_base | (src << 3);
pavone@61 1742 *(out++) = dst_disp;
pavone@567 1743 } else {
pavone@343 1744 *(out++) = MODE_REG_DISPLACE32 | dst_base | (src << 3);
pavone@343 1745 *(out++) = dst_disp;
pavone@343 1746 *(out++) = dst_disp >> 8;
pavone@343 1747 *(out++) = dst_disp >> 16;
pavone@343 1748 *(out++) = dst_disp >> 24;
pavone@567 1749 }
pavone@567 1750 code->cur = out;
pavone@343 1751 }
pavone@343 1752
pavone@567 1753 void bit_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
pavone@61 1754 {
pavone@567 1755 check_alloc_code(code, 6);
pavone@567 1756 code_ptr out = code->cur;
pavone@61 1757 if (size == SZ_W) {
pavone@61 1758 *(out++) = PRE_SIZE;
pavone@61 1759 }
pavone@61 1760 if (size == SZ_Q || dst >= R8) {
pavone@61 1761 *out = PRE_REX;
pavone@61 1762 if (size == SZ_Q) {
pavone@61 1763 *out |= REX_QUAD;
pavone@61 1764 }
pavone@61 1765 if (dst >= R8) {
pavone@61 1766 *out |= REX_RM_FIELD;
pavone@61 1767 dst -= (R8 - X86_R8);
pavone@61 1768 }
pavone@61 1769 out++;
pavone@61 1770 }
pavone@61 1771 *(out++) = PRE_2BYTE;
pavone@61 1772 *(out++) = OP2_BTX_I;
pavone@123 1773 *(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
pavone@61 1774 *(out++) = val;
pavone@567 1775 code->cur = out;
pavone@61 1776 }
pavone@61 1777
pavone@567 1778 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 1779 {
pavone@567 1780 check_alloc_code(code, 10);
pavone@567 1781 code_ptr out = code->cur;
pavone@61 1782 if (size == SZ_W) {
pavone@61 1783 *(out++) = PRE_SIZE;
pavone@61 1784 }
pavone@61 1785 if (size == SZ_Q || dst_base >= R8) {
pavone@61 1786 *out = PRE_REX;
pavone@61 1787 if (size == SZ_Q) {
pavone@61 1788 *out |= REX_QUAD;
pavone@61 1789 }
pavone@61 1790 if (dst_base >= R8) {
pavone@61 1791 *out |= REX_RM_FIELD;
pavone@61 1792 dst_base -= (R8 - X86_R8);
pavone@61 1793 }
pavone@61 1794 out++;
pavone@61 1795 }
pavone@61 1796 *(out++) = PRE_2BYTE;
pavone@61 1797 *(out++) = OP2_BTX_I;
pavone@567 1798 if (dst_disp < 128 && dst_disp >= -128) {
pavone@123 1799 *(out++) = MODE_REG_DISPLACE8 | dst_base | (op_ex << 3);
pavone@61 1800 *(out++) = dst_disp;
pavone@567 1801 } else {
pavone@567 1802 *(out++) = MODE_REG_DISPLACE32 | dst_base | (op_ex << 3);
pavone@567 1803 *(out++) = dst_disp;
pavone@567 1804 *(out++) = dst_disp >> 8;
pavone@567 1805 *(out++) = dst_disp >> 16;
pavone@567 1806 *(out++) = dst_disp >> 24;
pavone@567 1807 }
pavone@61 1808 *(out++) = val;
pavone@567 1809 code->cur = out;
pavone@61 1810 }
pavone@61 1811
pavone@567 1812 void bt_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@123 1813 {
pavone@567 1814 return bit_rr(code, OP2_BT, src, dst, size);
pavone@123 1815 }
pavone@123 1816
pavone@567 1817 void bt_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1818 {
pavone@567 1819 return bit_rrdisp(code, OP2_BT, src, dst_base, dst_disp, size);
pavone@123 1820 }
pavone@123 1821
pavone@567 1822 void bt_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@343 1823 {
pavone@567 1824 return bit_ir(code, OP_EX_BT, val, dst, size);
pavone@343 1825 }
pavone@343 1826
pavone@567 1827 void bt_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1828 {
pavone@567 1829 return bit_irdisp(code, OP_EX_BT, val, dst_base, dst_disp, size);
pavone@123 1830 }
pavone@123 1831
pavone@567 1832 void bts_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@123 1833 {
pavone@567 1834 return bit_rr(code, OP2_BTS, src, dst, size);
pavone@123 1835 }
pavone@123 1836
pavone@567 1837 void bts_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1838 {
pavone@567 1839 return bit_rrdisp(code, OP2_BTS, src, dst_base, dst_disp, size);
pavone@123 1840 }
pavone@123 1841
pavone@567 1842 void bts_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@123 1843 {
pavone@567 1844 return bit_ir(code, OP_EX_BTS, val, dst, size);
pavone@123 1845 }
pavone@123 1846
pavone@567 1847 void bts_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1848 {
pavone@567 1849 return bit_irdisp(code, OP_EX_BTS, val, dst_base, dst_disp, size);
pavone@123 1850 }
pavone@123 1851
pavone@567 1852 void btr_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@123 1853 {
pavone@567 1854 return bit_rr(code, OP2_BTR, src, dst, size);
pavone@123 1855 }
pavone@123 1856
pavone@567 1857 void btr_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1858 {
pavone@567 1859 return bit_rrdisp(code, OP2_BTR, src, dst_base, dst_disp, size);
pavone@123 1860 }
pavone@123 1861
pavone@567 1862 void btr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@123 1863 {
pavone@567 1864 return bit_ir(code, OP_EX_BTR, val, dst, size);
pavone@123 1865 }
pavone@123 1866
pavone@567 1867 void btr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1868 {
pavone@567 1869 return bit_irdisp(code, OP_EX_BTR, val, dst_base, dst_disp, size);
pavone@123 1870 }
pavone@123 1871
pavone@567 1872 void btc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
pavone@123 1873 {
pavone@567 1874 return bit_rr(code, OP2_BTC, src, dst, size);
pavone@123 1875 }
pavone@123 1876
pavone@567 1877 void btc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1878 {
pavone@567 1879 return bit_rrdisp(code, OP2_BTC, src, dst_base, dst_disp, size);
pavone@123 1880 }
pavone@123 1881
pavone@567 1882 void btc_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
pavone@123 1883 {
pavone@567 1884 return bit_ir(code, OP_EX_BTC, val, dst, size);
pavone@123 1885 }
pavone@123 1886
pavone@567 1887 void btc_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
pavone@123 1888 {
pavone@567 1889 return bit_irdisp(code, OP_EX_BTC, val, dst_base, dst_disp, size);
pavone@123 1890 }
pavone@123 1891
pavone@567 1892 void jcc(code_info *code, uint8_t cc, code_ptr dest)
pavone@123 1893 {
pavone@567 1894 check_alloc_code(code, 6);
pavone@567 1895 code_ptr out = code->cur;
pavone@18 1896 ptrdiff_t disp = dest-(out+2);
pavone@14 1897 if (disp <= 0x7F && disp >= -0x80) {
pavone@14 1898 *(out++) = OP_JCC | cc;
pavone@14 1899 *(out++) = disp;
pavone@14 1900 } else {
pavone@18 1901 disp = dest-(out+6);
pavone@18 1902 if (disp <= 0x7FFFFFFF && disp >= -2147483648) {
pavone@18 1903 *(out++) = PRE_2BYTE;
pavone@18 1904 *(out++) = OP2_JCC | cc;
pavone@18 1905 *(out++) = disp;
pavone@18 1906 disp >>= 8;
pavone@18 1907 *(out++) = disp;
pavone@18 1908 disp >>= 8;
pavone@18 1909 *(out++) = disp;
pavone@18 1910 disp >>= 8;
pavone@18 1911 *(out++) = disp;
pavone@18 1912 } else {
pavone@792 1913 fatal_error("jcc: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp);
pavone@18 1914 }
pavone@18 1915 }
pavone@567 1916 code->cur = out;
pavone@18 1917 }
pavone@18 1918
pavone@567 1919 void jmp(code_info *code, code_ptr dest)
pavone@18 1920 {
pavone@567 1921 check_alloc_code(code, 5);
pavone@567 1922 code_ptr out = code->cur;
pavone@18 1923 ptrdiff_t disp = dest-(out+2);
pavone@18 1924 if (disp <= 0x7F && disp >= -0x80) {
pavone@18 1925 *(out++) = OP_JMP_BYTE;
pavone@14 1926 *(out++) = disp;
pavone@18 1927 } else {
pavone@18 1928 disp = dest-(out+5);
pavone@18 1929 if (disp <= 0x7FFFFFFF && disp >= -2147483648) {
pavone@18 1930 *(out++) = OP_JMP;
pavone@18 1931 *(out++) = disp;
pavone@18 1932 disp >>= 8;
pavone@18 1933 *(out++) = disp;
pavone@18 1934 disp >>= 8;
pavone@18 1935 *(out++) = disp;
pavone@18 1936 disp >>= 8;
pavone@18 1937 *(out++) = disp;
pavone@18 1938 } else {
pavone@792 1939 fatal_error("jmp: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp);
pavone@18 1940 }
pavone@14 1941 }
pavone@567 1942 code->cur = out;
pavone@14 1943 }
pavone@14 1944
pavone@567 1945 void jmp_r(code_info *code, uint8_t dst)
pavone@81 1946 {
pavone@567 1947 check_alloc_code(code, 3);
pavone@567 1948 code_ptr out = code->cur;
pavone@235 1949 if (dst >= R8) {
pavone@235 1950 dst -= R8 - X86_R8;
pavone@235 1951 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@235 1952 }
pavone@81 1953 *(out++) = OP_SINGLE_EA;
pavone@81 1954 *(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3);
pavone@567 1955 code->cur = out;
pavone@81 1956 }
pavone@81 1957
pavone@593 1958 void jmp_rind(code_info *code, uint8_t dst)
pavone@14 1959 {
pavone@593 1960 check_alloc_code(code, 3);
pavone@593 1961 code_ptr out = code->cur;
pavone@593 1962 if (dst >= R8) {
pavone@593 1963 dst -= R8 - X86_R8;
pavone@593 1964 *(out++) = PRE_REX | REX_RM_FIELD;
pavone@593 1965 }
pavone@593 1966 *(out++) = OP_SINGLE_EA;
pavone@593 1967 *(out++) = MODE_REG_INDIRECT | dst | (OP_EX_JMP_EA << 3);
pavone@593 1968 code->cur = out;
pavone@593 1969 }
pavone@593 1970
pavone@899 1971 void call_noalign(code_info *code, code_ptr fun)
pavone@550 1972 {
pavone@567 1973 check_alloc_code(code, 5);
pavone@567 1974 code_ptr out = code->cur;
pavone@14 1975 ptrdiff_t disp = fun-(out+5);
pavone@14 1976 if (disp <= 0x7FFFFFFF && disp >= -2147483648) {
pavone@14 1977 *(out++) = OP_CALL;
pavone@14 1978 *(out++) = disp;
pavone@14 1979 disp >>= 8;
pavone@14 1980 *(out++) = disp;
pavone@14 1981 disp >>= 8;
pavone@14 1982 *(out++) = disp;
pavone@14 1983 disp >>= 8;
pavone@14 1984 *(out++) = disp;
pavone@14 1985 } else {
pavone@18 1986 //TODO: Implement far call???
pavone@792 1987 fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp);
pavone@14 1988 }
pavone@567 1989 code->cur = out;
pavone@899 1990 }
pavone@899 1991
pavone@899 1992
pavone@899 1993 void call(code_info *code, code_ptr fun)
pavone@899 1994 {
pavone@899 1995 code->stack_off += sizeof(void *);
pavone@899 1996 int32_t adjust = 0;
pavone@899 1997 if (code->stack_off & 0xF) {
pavone@899 1998 adjust = 16 - (code->stack_off & 0xF);
pavone@899 1999 code->stack_off += adjust;
pavone@899 2000 sub_ir(code, adjust, RSP, SZ_PTR);
pavone@899 2001 }
pavone@899 2002 call_noalign(code, fun);
pavone@894 2003 if (adjust) {
pavone@894 2004 add_ir(code, adjust, RSP, SZ_PTR);
pavone@894 2005 }
pavone@894 2006 code->stack_off -= sizeof(void *) + adjust;
pavone@14 2007 }
pavone@754 2008 void call_raxfallback(code_info *code, code_ptr fun)
pavone@754 2009 {
pavone@754 2010 check_alloc_code(code, 5);
pavone@754 2011 code_ptr out = code->cur;
pavone@754 2012 ptrdiff_t disp = fun-(out+5);
pavone@754 2013 if (disp <= 0x7FFFFFFF && disp >= -2147483648) {
pavone@754 2014 *(out++) = OP_CALL;
pavone@754 2015 *(out++) = disp;
pavone@754 2016 disp >>= 8;
pavone@754 2017 *(out++) = disp;
pavone@754 2018 disp >>= 8;
pavone@754 2019 *(out++) = disp;
pavone@754 2020 disp >>= 8;
pavone@754 2021 *(out++) = disp;
pavone@754 2022 } else {
pavone@755 2023 mov_ir(code, (int64_t)fun, RAX, SZ_PTR);
pavone@754 2024 call_r(code, RAX);
pavone@754 2025 }
pavone@754 2026 code->cur = out;
pavone@754 2027 }
pavone@754 2028
pavone@567 2029 void call_r(code_info *code, uint8_t dst)
pavone@81 2030 {
pavone@894 2031 code->stack_off += sizeof(void *);
pavone@894 2032 int32_t adjust = 0;
pavone@894 2033 if (code->stack_off & 0xF) {
pavone@894 2034 adjust = 16 - (code->stack_off & 0xF);
pavone@894 2035 code->stack_off += adjust;
pavone@894 2036 sub_ir(code, adjust, RSP, SZ_PTR);
pavone@894 2037 }
pavone@567 2038 check_alloc_code(code, 2);
pavone@567 2039 code_ptr out = code->cur;
pavone@81 2040 *(out++) = OP_SINGLE_EA;
pavone@81 2041 *(out++) = MODE_REG_DIRECT | dst | (OP_EX_CALL_EA << 3);
pavone@567 2042 code->cur = out;
pavone@894 2043 if (adjust) {
pavone@894 2044 add_ir(code, adjust, RSP, SZ_PTR);
pavone@894 2045 }
pavone@894 2046 code->stack_off -= sizeof(void *) + adjust;
pavone@81 2047 }
pavone@81 2048
pavone@567 2049 void retn(code_info *code)
pavone@14 2050 {
pavone@567 2051 check_alloc_code(code, 1);
pavone@567 2052 code_ptr out = code->cur;
pavone@14 2053 *(out++) = OP_RETN;
pavone@567 2054 code->cur = out;
pavone@14 2055 }
pavone@14 2056
pavone@567 2057 void cdq(code_info *code)
pavone@151 2058 {
pavone@567 2059 check_alloc_code(code, 1);
pavone@567 2060 code_ptr out = code->cur;
pavone@151 2061 *(out++) = OP_CDQ;
pavone@567 2062 code->cur = out;
pavone@151 2063 }
pavone@14 2064
pavone@567 2065 void loop(code_info *code, code_ptr dst)
pavone@207 2066 {
pavone@567 2067 check_alloc_code(code, 2);
pavone@567 2068 code_ptr out = code->cur;
pavone@207 2069 ptrdiff_t disp = dst-(out+2);
pavone@207 2070 *(out++) = OP_LOOP;
pavone@207 2071 *(out++) = disp;
pavone@567 2072 code->cur = out;
pavone@207 2073 }
pavone@567 2074
pavone@656 2075 uint32_t prep_args(code_info *code, uint32_t num_args, va_list args)
pavone@656 2076 {
pavone@656 2077 uint8_t *arg_arr = malloc(num_args);
pavone@656 2078 for (int i = 0; i < num_args; i ++)
pavone@656 2079 {
pavone@656 2080 arg_arr[i] = va_arg(args, int);
pavone@656 2081 }
pavone@656 2082 #ifdef X86_64
pavone@656 2083 uint32_t stack_args = 0;
pavone@656 2084 uint8_t abi_regs[] = {RDI, RSI, RDX, RCX, R8, R9};
pavone@656 2085 int8_t reg_swap[R15+1];
pavone@656 2086 uint32_t usage = 0;
pavone@656 2087 memset(reg_swap, -1, sizeof(reg_swap));
pavone@656 2088 for (int i = 0; i < num_args; i ++)
pavone@656 2089 {
pavone@656 2090 usage |= 1 << arg_arr[i];
pavone@656 2091 }
pavone@656 2092 for (int i = 0; i < num_args; i ++)
pavone@656 2093 {
pavone@656 2094 uint8_t reg_arg = arg_arr[i];
pavone@656 2095 if (i < sizeof(abi_regs)) {
pavone@656 2096 if (reg_swap[reg_arg] >= 0) {
pavone@656 2097 reg_arg = reg_swap[reg_arg];
pavone@656 2098 }
pavone@656 2099 if (reg_arg != abi_regs[i]) {
pavone@656 2100 if (usage & (1 << abi_regs[i])) {
pavone@656 2101 xchg_rr(code, reg_arg, abi_regs[i], SZ_PTR);
pavone@656 2102 reg_swap[abi_regs[i]] = reg_arg;
pavone@656 2103 } else {
pavone@656 2104 mov_rr(code, reg_arg, abi_regs[i], SZ_PTR);
pavone@656 2105 }
pavone@656 2106 }
pavone@656 2107 } else {
pavone@656 2108 arg_arr[stack_args++] = reg_arg;
pavone@656 2109 }
pavone@656 2110 }
pavone@656 2111 #else
pavone@656 2112 #define stack_args num_args
pavone@656 2113 #endif
pavone@901 2114 uint32_t stack_off_call = code->stack_off + sizeof(void *) * (stack_args + 1);
pavone@894 2115 uint32_t adjust = 0;
pavone@894 2116 if (stack_off_call & 0xF) {
pavone@894 2117 adjust = 16 - (stack_off_call & 0xF);
pavone@894 2118 sub_ir(code, adjust, RSP, SZ_PTR);
pavone@894 2119 code->stack_off += adjust;
pavone@894 2120 }
pavone@901 2121 for (int i = stack_args -1; i >= 0; i--)
pavone@901 2122 {
pavone@901 2123 push_r(code, arg_arr[i]);
pavone@901 2124 }
pavone@901 2125
pavone@894 2126 return stack_args * sizeof(void *) + adjust;
pavone@656 2127 }
pavone@656 2128
pavone@656 2129 void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...)
pavone@656 2130 {
pavone@656 2131 va_list args;
pavone@656 2132 va_start(args, num_args);
pavone@656 2133 uint32_t adjust = prep_args(code, num_args, args);
pavone@656 2134 va_end(args);
pavone@754 2135 call_raxfallback(code, fun);
pavone@656 2136 if (adjust) {
pavone@656 2137 add_ir(code, adjust, RSP, SZ_PTR);
pavone@894 2138 code->stack_off -= adjust;
pavone@656 2139 }
pavone@656 2140 }
pavone@894 2141 /*
pavone@656 2142 void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...)
pavone@656 2143 {
pavone@656 2144 va_list args;
pavone@656 2145 va_start(args, num_args);
pavone@656 2146 uint32_t adjust = prep_args(code, num_args, args);
pavone@656 2147 va_end(args);
pavone@656 2148 #ifdef X86_64
pavone@656 2149 test_ir(code, 8, RSP, SZ_PTR); //check stack alignment
pavone@656 2150 code_ptr do_adjust_rsp = code->cur + 1;
pavone@656 2151 jcc(code, CC_NZ, code->cur + 2);
pavone@656 2152 #endif
pavone@754 2153 call_raxfallback(code, fun);
pavone@656 2154 if (adjust) {
pavone@656 2155 add_ir(code, adjust, RSP, SZ_PTR);
pavone@656 2156 }
pavone@656 2157 #ifdef X86_64
pavone@656 2158 code_ptr no_adjust_rsp = code->cur + 1;
pavone@656 2159 jmp(code, code->cur + 2);
pavone@656 2160 *do_adjust_rsp = code->cur - (do_adjust_rsp+1);
pavone@656 2161 sub_ir(code, 8, RSP, SZ_PTR);
pavone@754 2162 call_raxfallback(code, fun);
pavone@656 2163 add_ir(code, adjust + 8 , RSP, SZ_PTR);
pavone@656 2164 *no_adjust_rsp = code->cur - (no_adjust_rsp+1);
pavone@656 2165 #endif
pavone@656 2166 }
pavone@894 2167 */
pavone@665 2168 void save_callee_save_regs(code_info *code)
pavone@665 2169 {
pavone@665 2170 push_r(code, RBX);
pavone@665 2171 push_r(code, RBP);
pavone@665 2172 #ifdef X86_64
pavone@665 2173 push_r(code, R12);
pavone@665 2174 push_r(code, R13);
pavone@665 2175 push_r(code, R14);
pavone@665 2176 push_r(code, R15);
pavone@665 2177 #else
pavone@665 2178 push_r(code, RDI);
pavone@665 2179 push_r(code, RSI);
pavone@665 2180 #endif
pavone@665 2181 }
pavone@665 2182
pavone@665 2183 void restore_callee_save_regs(code_info *code)
pavone@665 2184 {
pavone@665 2185 #ifdef X86_64
pavone@665 2186 pop_r(code, R15);
pavone@665 2187 pop_r(code, R14);
pavone@665 2188 pop_r(code, R13);
pavone@665 2189 pop_r(code, R12);
pavone@665 2190 #else
pavone@665 2191 pop_r(code, RSI);
pavone@665 2192 pop_r(code, RDI);
pavone@665 2193 #endif
pavone@665 2194 pop_r(code, RBP);
pavone@665 2195 pop_r(code, RBX);
pavone@665 2196 }
pavone@691 2197
pavone@691 2198 uint8_t has_modrm(uint8_t prefix, uint8_t opcode)
pavone@691 2199 {
pavone@691 2200 if (!prefix) {
pavone@691 2201 switch (opcode)
pavone@691 2202 {
pavone@691 2203 case OP_JMP:
pavone@691 2204 case OP_JMP_BYTE:
pavone@691 2205 case OP_JCC:
pavone@691 2206 case OP_CALL:
pavone@691 2207 case OP_RETN:
pavone@691 2208 case OP_LOOP:
pavone@691 2209 case OP_MOV_I8R:
pavone@691 2210 case OP_MOV_IR:
pavone@691 2211 case OP_PUSHF:
pavone@691 2212 case OP_POPF:
pavone@691 2213 case OP_PUSH:
pavone@691 2214 case OP_POP:
pavone@691 2215 case OP_CDQ:
pavone@691 2216 return 0;
pavone@691 2217 }
pavone@691 2218 } else if (prefix == PRE_2BYTE) {
pavone@691 2219 switch (opcode)
pavone@691 2220 {
pavone@691 2221 case OP2_JCC:
pavone@691 2222 return 0;
pavone@691 2223 }
pavone@691 2224 }
pavone@691 2225 return 1;
pavone@691 2226 }
pavone@691 2227
pavone@691 2228 uint8_t has_sib(uint8_t mod_rm)
pavone@691 2229 {
pavone@691 2230 uint8_t mode = mod_rm & 0xC0;
pavone@691 2231 uint8_t rm = mod_rm & 3;
pavone@691 2232
pavone@691 2233 return mode != MODE_REG_DIRECT && rm == RSP;
pavone@691 2234 }
pavone@691 2235
pavone@691 2236 uint32_t x86_inst_size(code_ptr start)
pavone@691 2237 {
pavone@691 2238 code_ptr code = start;
pavone@691 2239 uint8_t cont = 1;
pavone@691 2240 uint8_t prefix = 0;
pavone@691 2241 uint8_t op_size = SZ_B;
pavone@691 2242 uint8_t main_op;
pavone@691 2243
pavone@691 2244 while (cont)
pavone@691 2245 {
pavone@691 2246 if (*code == PRE_SIZE) {
pavone@691 2247 op_size = SZ_W;
pavone@691 2248 } else if (*code == PRE_REX) {
pavone@691 2249 if (*code & REX_QUAD) {
pavone@691 2250 op_size = SZ_Q;
pavone@691 2251 }
pavone@755 2252 } else if(*code == PRE_2BYTE || *code == PRE_XOP) {
pavone@691 2253 prefix = *code;
pavone@691 2254 } else {
pavone@691 2255 main_op = *code;
pavone@691 2256 cont = 0;
pavone@691 2257 }
pavone@691 2258 code++;
pavone@691 2259 }
pavone@691 2260 if (has_modrm(prefix, main_op)) {
pavone@691 2261 uint8_t mod_rm = *(code++);
pavone@691 2262 if (has_sib(mod_rm)) {
pavone@692 2263 //sib takes up a byte, but can't add any additional ones beyond that
pavone@692 2264 code++;
pavone@692 2265 }
pavone@692 2266 uint8_t mode = mod_rm & 0xC0;
pavone@692 2267 uint8_t rm = mod_rm & 3;
pavone@692 2268 if (mode == MODE_REG_DISPLACE8) {
pavone@692 2269 code++;
pavone@692 2270 } else if (mode == MODE_REG_DISPLACE32 || (mode == MODE_REG_INDIRECT && rm == RBP)) {
pavone@692 2271 code += 4;
pavone@691 2272 }
pavone@691 2273 } else {
pavone@691 2274 }
pavone@691 2275
pavone@691 2276 return code-start;
pavone@691 2277 }