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