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 }
|