1 |
/* |
2 |
* x86-codegen.h: Macros for generating x86 code |
3 |
* |
4 |
* Authors: |
5 |
* Paolo Molaro (lupus@ximian.com) |
6 |
* Intel Corporation (ORP Project) |
7 |
* Sergey Chaban (serge@wildwestsoftware.com) |
8 |
* Dietmar Maurer (dietmar@ximian.com) |
9 |
* Patrik Torstensson |
10 |
* |
11 |
* Copyright (C) 2000 Intel Corporation. All rights reserved. |
12 |
* Copyright (C) 2001, 2002 Ximian, Inc. |
13 |
*/ |
14 |
|
15 |
#ifndef X86_H |
16 |
#define X86_H |
17 |
#include <assert.h> |
18 |
/* |
19 |
// x86 register numbers |
20 |
*/ |
21 |
typedef enum { |
22 |
X86_EAX = 0, |
23 |
X86_ECX = 1, |
24 |
X86_EDX = 2, |
25 |
X86_EBX = 3, |
26 |
X86_ESP = 4, |
27 |
X86_EBP = 5, |
28 |
X86_ESI = 6, |
29 |
X86_EDI = 7, |
30 |
X86_NREG |
31 |
} X86_Reg_No; |
32 |
/* |
33 |
// opcodes for alu instructions |
34 |
*/ |
35 |
typedef enum { |
36 |
X86_ADD = 0, |
37 |
X86_OR = 1, |
38 |
X86_ADC = 2, |
39 |
X86_SBB = 3, |
40 |
X86_AND = 4, |
41 |
X86_SUB = 5, |
42 |
X86_XOR = 6, |
43 |
X86_CMP = 7, |
44 |
X86_NALU |
45 |
} X86_ALU_Opcode; |
46 |
/* |
47 |
// opcodes for shift instructions |
48 |
*/ |
49 |
typedef enum { |
50 |
X86_SHLD, |
51 |
X86_SHLR, |
52 |
X86_ROL = 0, |
53 |
X86_ROR = 1, |
54 |
X86_RCL = 2, |
55 |
X86_RCR = 3, |
56 |
X86_SHL = 4, |
57 |
X86_SHR = 5, |
58 |
X86_SAR = 7, |
59 |
X86_NSHIFT = 8 |
60 |
} X86_Shift_Opcode; |
61 |
/* |
62 |
// opcodes for floating-point instructions |
63 |
*/ |
64 |
typedef enum { |
65 |
X86_FADD = 0, |
66 |
X86_FMUL = 1, |
67 |
X86_FCOM = 2, |
68 |
X86_FCOMP = 3, |
69 |
X86_FSUB = 4, |
70 |
X86_FSUBR = 5, |
71 |
X86_FDIV = 6, |
72 |
X86_FDIVR = 7, |
73 |
X86_NFP = 8 |
74 |
} X86_FP_Opcode; |
75 |
/* |
76 |
// integer conditions codes |
77 |
*/ |
78 |
typedef enum { |
79 |
X86_CC_EQ = 0, X86_CC_E = 0, X86_CC_Z = 0, |
80 |
X86_CC_NE = 1, X86_CC_NZ = 1, |
81 |
X86_CC_LT = 2, X86_CC_B = 2, X86_CC_C = 2, X86_CC_NAE = 2, |
82 |
X86_CC_LE = 3, X86_CC_BE = 3, X86_CC_NA = 3, |
83 |
X86_CC_GT = 4, X86_CC_A = 4, X86_CC_NBE = 4, |
84 |
X86_CC_GE = 5, X86_CC_AE = 5, X86_CC_NB = 5, X86_CC_NC = 5, |
85 |
X86_CC_LZ = 6, X86_CC_S = 6, |
86 |
X86_CC_GEZ = 7, X86_CC_NS = 7, |
87 |
X86_CC_P = 8, X86_CC_PE = 8, |
88 |
X86_CC_NP = 9, X86_CC_PO = 9, |
89 |
X86_CC_O = 10, |
90 |
X86_CC_NO = 11, |
91 |
X86_NCC |
92 |
} X86_CC; |
93 |
|
94 |
/* FP status */ |
95 |
enum { |
96 |
X86_FP_C0 = 0x100, |
97 |
X86_FP_C1 = 0x200, |
98 |
X86_FP_C2 = 0x400, |
99 |
X86_FP_C3 = 0x4000, |
100 |
X86_FP_CC_MASK = 0x4500 |
101 |
}; |
102 |
|
103 |
/* FP control word */ |
104 |
enum { |
105 |
X86_FPCW_INVOPEX_MASK = 0x1, |
106 |
X86_FPCW_DENOPEX_MASK = 0x2, |
107 |
X86_FPCW_ZERODIV_MASK = 0x4, |
108 |
X86_FPCW_OVFEX_MASK = 0x8, |
109 |
X86_FPCW_UNDFEX_MASK = 0x10, |
110 |
X86_FPCW_PRECEX_MASK = 0x20, |
111 |
X86_FPCW_PRECC_MASK = 0x300, |
112 |
X86_FPCW_ROUNDC_MASK = 0xc00, |
113 |
|
114 |
/* values for precision control */ |
115 |
X86_FPCW_PREC_SINGLE = 0, |
116 |
X86_FPCW_PREC_DOUBLE = 0x200, |
117 |
X86_FPCW_PREC_EXTENDED = 0x300, |
118 |
|
119 |
/* values for rounding control */ |
120 |
X86_FPCW_ROUND_NEAREST = 0, |
121 |
X86_FPCW_ROUND_DOWN = 0x400, |
122 |
X86_FPCW_ROUND_UP = 0x800, |
123 |
X86_FPCW_ROUND_TOZERO = 0xc00 |
124 |
}; |
125 |
|
126 |
/* |
127 |
// prefix code |
128 |
*/ |
129 |
typedef enum { |
130 |
X86_LOCK_PREFIX = 0xF0, |
131 |
X86_REPNZ_PREFIX = 0xF2, |
132 |
X86_REPZ_PREFIX = 0xF3, |
133 |
X86_REP_PREFIX = 0xF3, |
134 |
X86_CS_PREFIX = 0x2E, |
135 |
X86_SS_PREFIX = 0x36, |
136 |
X86_DS_PREFIX = 0x3E, |
137 |
X86_ES_PREFIX = 0x26, |
138 |
X86_FS_PREFIX = 0x64, |
139 |
X86_GS_PREFIX = 0x65, |
140 |
X86_UNLIKELY_PREFIX = 0x2E, |
141 |
X86_LIKELY_PREFIX = 0x3E, |
142 |
X86_OPERAND_PREFIX = 0x66, |
143 |
X86_ADDRESS_PREFIX = 0x67 |
144 |
} X86_Prefix; |
145 |
|
146 |
static const unsigned char |
147 |
x86_cc_unsigned_map [X86_NCC] = { |
148 |
0x74, /* eq */ |
149 |
0x75, /* ne */ |
150 |
0x72, /* lt */ |
151 |
0x76, /* le */ |
152 |
0x77, /* gt */ |
153 |
0x73, /* ge */ |
154 |
0x78, /* lz */ |
155 |
0x79, /* gez */ |
156 |
0x7a, /* p */ |
157 |
0x7b, /* np */ |
158 |
0x70, /* o */ |
159 |
0x71, /* no */ |
160 |
}; |
161 |
|
162 |
static const unsigned char |
163 |
x86_cc_signed_map [X86_NCC] = { |
164 |
0x74, /* eq */ |
165 |
0x75, /* ne */ |
166 |
0x7c, /* lt */ |
167 |
0x7e, /* le */ |
168 |
0x7f, /* gt */ |
169 |
0x7d, /* ge */ |
170 |
0x78, /* lz */ |
171 |
0x79, /* gez */ |
172 |
0x7a, /* p */ |
173 |
0x7b, /* np */ |
174 |
0x70, /* o */ |
175 |
0x71, /* no */ |
176 |
}; |
177 |
|
178 |
typedef union { |
179 |
int val; |
180 |
unsigned char b [4]; |
181 |
} x86_imm_buf; |
182 |
|
183 |
#define X86_NOBASEREG (-1) |
184 |
|
185 |
/* |
186 |
// bitvector mask for callee-saved registers |
187 |
*/ |
188 |
#define X86_ESI_MASK (1<<X86_ESI) |
189 |
#define X86_EDI_MASK (1<<X86_EDI) |
190 |
#define X86_EBX_MASK (1<<X86_EBX) |
191 |
#define X86_EBP_MASK (1<<X86_EBP) |
192 |
|
193 |
#define X86_CALLEE_REGS ((1<<X86_EAX) | (1<<X86_ECX) | (1<<X86_EDX)) |
194 |
#define X86_CALLER_REGS ((1<<X86_EBX) | (1<<X86_EBP) | (1<<X86_ESI) | (1<<X86_EDI)) |
195 |
#define X86_BYTE_REGS ((1<<X86_EAX) | (1<<X86_ECX) | (1<<X86_EDX) | (1<<X86_EBX)) |
196 |
|
197 |
#define X86_IS_SCRATCH(reg) (X86_CALLER_REGS & (1 << (reg))) /* X86_EAX, X86_ECX, or X86_EDX */ |
198 |
#define X86_IS_CALLEE(reg) (X86_CALLEE_REGS & (1 << (reg))) /* X86_ESI, X86_EDI, X86_EBX, or X86_EBP */ |
199 |
|
200 |
#define X86_IS_BYTE_REG(reg) ((reg) < 4) |
201 |
|
202 |
/* |
203 |
// Frame structure: |
204 |
// |
205 |
// +--------------------------------+ |
206 |
// | in_arg[0] = var[0] | |
207 |
// | in_arg[1] = var[1] | |
208 |
// | . . . | |
209 |
// | in_arg[n_arg-1] = var[n_arg-1] | |
210 |
// +--------------------------------+ |
211 |
// | return IP | |
212 |
// +--------------------------------+ |
213 |
// | saved EBP | <-- frame pointer (EBP) |
214 |
// +--------------------------------+ |
215 |
// | ... | n_extra |
216 |
// +--------------------------------+ |
217 |
// | var[n_arg] | |
218 |
// | var[n_arg+1] | local variables area |
219 |
// | . . . | |
220 |
// | var[n_var-1] | |
221 |
// +--------------------------------+ |
222 |
// | | |
223 |
// | | |
224 |
// | spill area | area for spilling mimic stack |
225 |
// | | |
226 |
// +--------------------------------| |
227 |
// | ebx | |
228 |
// | ebp [ESP_Frame only] | |
229 |
// | esi | 0..3 callee-saved regs |
230 |
// | edi | <-- stack pointer (ESP) |
231 |
// +--------------------------------+ |
232 |
// | stk0 | |
233 |
// | stk1 | operand stack area/ |
234 |
// | . . . | out args |
235 |
// | stkn-1 | |
236 |
// +--------------------------------| |
237 |
// |
238 |
// |
239 |
*/ |
240 |
|
241 |
|
242 |
/* |
243 |
* useful building blocks |
244 |
*/ |
245 |
#define x86_modrm_mod(modrm) ((modrm) >> 6) |
246 |
#define x86_modrm_reg(modrm) (((modrm) >> 3) & 0x7) |
247 |
#define x86_modrm_rm(modrm) ((modrm) & 0x7) |
248 |
|
249 |
#define x86_address_byte(inst,m,o,r) do { *(inst)++ = ((((m)&0x03)<<6)|(((o)&0x07)<<3)|(((r)&0x07))); } while (0) |
250 |
#define x86_imm_emit32(inst,imm) \ |
251 |
do { \ |
252 |
x86_imm_buf imb; imb.val = (int) (imm); \ |
253 |
*(inst)++ = imb.b [0]; \ |
254 |
*(inst)++ = imb.b [1]; \ |
255 |
*(inst)++ = imb.b [2]; \ |
256 |
*(inst)++ = imb.b [3]; \ |
257 |
} while (0) |
258 |
#define x86_imm_emit16(inst,imm) do { *(short*)(inst) = (imm); (inst) += 2; } while (0) |
259 |
#define x86_imm_emit8(inst,imm) do { *(inst) = (unsigned char)((imm) & 0xff); ++(inst); } while (0) |
260 |
#define x86_is_imm8(imm) (((int)(imm) >= -128 && (int)(imm) <= 127)) |
261 |
#define x86_is_imm16(imm) (((int)(imm) >= -(1<<16) && (int)(imm) <= ((1<<16)-1))) |
262 |
|
263 |
#define x86_reg_emit(inst,r,regno) do { x86_address_byte ((inst), 3, (r), (regno)); } while (0) |
264 |
#define x86_reg8_emit(inst,r,regno,is_rh,is_rnoh) do {x86_address_byte ((inst), 3, (is_rh)?((r)|4):(r), (is_rnoh)?((regno)|4):(regno));} while (0) |
265 |
#define x86_regp_emit(inst,r,regno) do { x86_address_byte ((inst), 0, (r), (regno)); } while (0) |
266 |
#define x86_mem_emit(inst,r,disp) do { x86_address_byte ((inst), 0, (r), 5); x86_imm_emit32((inst), (disp)); } while (0) |
267 |
|
268 |
#define x86_membase_emit(inst,r,basereg,disp) do {\ |
269 |
if ((basereg) == X86_ESP) { \ |
270 |
if ((disp) == 0) { \ |
271 |
x86_address_byte ((inst), 0, (r), X86_ESP); \ |
272 |
x86_address_byte ((inst), 0, X86_ESP, X86_ESP); \ |
273 |
} else if (x86_is_imm8((disp))) { \ |
274 |
x86_address_byte ((inst), 1, (r), X86_ESP); \ |
275 |
x86_address_byte ((inst), 0, X86_ESP, X86_ESP); \ |
276 |
x86_imm_emit8 ((inst), (disp)); \ |
277 |
} else { \ |
278 |
x86_address_byte ((inst), 2, (r), X86_ESP); \ |
279 |
x86_address_byte ((inst), 0, X86_ESP, X86_ESP); \ |
280 |
x86_imm_emit32 ((inst), (disp)); \ |
281 |
} \ |
282 |
break; \ |
283 |
} \ |
284 |
if ((disp) == 0 && (basereg) != X86_EBP) { \ |
285 |
x86_address_byte ((inst), 0, (r), (basereg)); \ |
286 |
break; \ |
287 |
} \ |
288 |
if (x86_is_imm8((disp))) { \ |
289 |
x86_address_byte ((inst), 1, (r), (basereg)); \ |
290 |
x86_imm_emit8 ((inst), (disp)); \ |
291 |
} else { \ |
292 |
x86_address_byte ((inst), 2, (r), (basereg)); \ |
293 |
x86_imm_emit32 ((inst), (disp)); \ |
294 |
} \ |
295 |
} while (0) |
296 |
|
297 |
#define x86_memindex_emit(inst,r,basereg,disp,indexreg,shift) \ |
298 |
do { \ |
299 |
if ((basereg) == X86_NOBASEREG) { \ |
300 |
x86_address_byte ((inst), 0, (r), 4); \ |
301 |
x86_address_byte ((inst), (shift), (indexreg), 5); \ |
302 |
x86_imm_emit32 ((inst), (disp)); \ |
303 |
} else if ((disp) == 0 && (basereg) != X86_EBP) { \ |
304 |
x86_address_byte ((inst), 0, (r), 4); \ |
305 |
x86_address_byte ((inst), (shift), (indexreg), (basereg)); \ |
306 |
} else if (x86_is_imm8((disp))) { \ |
307 |
x86_address_byte ((inst), 1, (r), 4); \ |
308 |
x86_address_byte ((inst), (shift), (indexreg), (basereg)); \ |
309 |
x86_imm_emit8 ((inst), (disp)); \ |
310 |
} else { \ |
311 |
x86_address_byte ((inst), 2, (r), 4); \ |
312 |
x86_address_byte ((inst), (shift), (indexreg), 5); \ |
313 |
x86_imm_emit32 ((inst), (disp)); \ |
314 |
} \ |
315 |
} while (0) |
316 |
|
317 |
/* |
318 |
* target is the position in the code where to jump to: |
319 |
* target = code; |
320 |
* .. output loop code... |
321 |
* x86_mov_reg_imm (code, X86_EAX, 0); |
322 |
* loop = code; |
323 |
* x86_loop (code, -1); |
324 |
* ... finish method |
325 |
* |
326 |
* patch displacement |
327 |
* x86_patch (loop, target); |
328 |
* |
329 |
* ins should point at the start of the instruction that encodes a target. |
330 |
* the instruction is inspected for validity and the correct displacement |
331 |
* is inserted. |
332 |
*/ |
333 |
#define x86_patch(ins,target) \ |
334 |
do { \ |
335 |
unsigned char* pos = (ins) + 1; \ |
336 |
int disp, size = 0; \ |
337 |
switch (*(unsigned char*)(ins)) { \ |
338 |
case 0xe8: case 0xe9: ++size; break; /* call, jump32 */ \ |
339 |
case 0x0f: if (!(*pos >= 0x70 && *pos <= 0x8f)) assert (0); \ |
340 |
++size; ++pos; break; /* prefix for 32-bit disp */ \ |
341 |
case 0xe0: case 0xe1: case 0xe2: /* loop */ \ |
342 |
case 0xeb: /* jump8 */ \ |
343 |
/* conditional jump opcodes */ \ |
344 |
case 0x70: case 0x71: case 0x72: case 0x73: \ |
345 |
case 0x74: case 0x75: case 0x76: case 0x77: \ |
346 |
case 0x78: case 0x79: case 0x7a: case 0x7b: \ |
347 |
case 0x7c: case 0x7d: case 0x7e: case 0x7f: \ |
348 |
break; \ |
349 |
default: assert (0); \ |
350 |
} \ |
351 |
disp = (target) - pos; \ |
352 |
if (size) x86_imm_emit32 (pos, disp - 4); \ |
353 |
else if (x86_is_imm8 (disp - 1)) x86_imm_emit8 (pos, disp - 1); \ |
354 |
else assert (0); \ |
355 |
} while (0) |
356 |
|
357 |
#define x86_breakpoint(inst) \ |
358 |
do { \ |
359 |
*(inst)++ = 0xcc; \ |
360 |
} while (0) |
361 |
|
362 |
#define x86_clc(inst) do { *(inst)++ =(unsigned char)0xf8; } while (0) |
363 |
#define x86_cld(inst) do { *(inst)++ =(unsigned char)0xfc; } while (0) |
364 |
#define x86_stosb(inst) do { *(inst)++ =(unsigned char)0xaa; } while (0) |
365 |
#define x86_stosl(inst) do { *(inst)++ =(unsigned char)0xab; } while (0) |
366 |
#define x86_stosd(inst) x86_stosl((inst)) |
367 |
#define x86_movsb(inst) do { *(inst)++ =(unsigned char)0xa4; } while (0) |
368 |
#define x86_movsl(inst) do { *(inst)++ =(unsigned char)0xa5; } while (0) |
369 |
#define x86_movsd(inst) x86_movsl((inst)) |
370 |
|
371 |
#define x86_prefix(inst,p) do { *(inst)++ =(unsigned char) (p); } while (0) |
372 |
|
373 |
#define x86_bswap(inst,reg) \ |
374 |
do { \ |
375 |
*(inst)++ = 0x0f; \ |
376 |
*(inst)++ = (unsigned char)0xc8 + (reg); \ |
377 |
} while (0) |
378 |
|
379 |
#define x86_rdtsc(inst) \ |
380 |
do { \ |
381 |
*(inst)++ = 0x0f; \ |
382 |
*(inst)++ = 0x31; \ |
383 |
} while (0) |
384 |
|
385 |
#define x86_cmpxchg_reg_reg(inst,dreg,reg) \ |
386 |
do { \ |
387 |
*(inst)++ = (unsigned char)0x0f; \ |
388 |
*(inst)++ = (unsigned char)0xb1; \ |
389 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
390 |
} while (0) |
391 |
|
392 |
#define x86_cmpxchg_mem_reg(inst,mem,reg) \ |
393 |
do { \ |
394 |
*(inst)++ = (unsigned char)0x0f; \ |
395 |
*(inst)++ = (unsigned char)0xb1; \ |
396 |
x86_mem_emit ((inst), (reg), (mem)); \ |
397 |
} while (0) |
398 |
|
399 |
#define x86_cmpxchg_membase_reg(inst,basereg,disp,reg) \ |
400 |
do { \ |
401 |
*(inst)++ = (unsigned char)0x0f; \ |
402 |
*(inst)++ = (unsigned char)0xb1; \ |
403 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
404 |
} while (0) |
405 |
|
406 |
#define x86_xchg_reg_reg(inst,dreg,reg,size) \ |
407 |
do { \ |
408 |
if ((size) == 1) \ |
409 |
*(inst)++ = (unsigned char)0x86; \ |
410 |
else \ |
411 |
*(inst)++ = (unsigned char)0x87; \ |
412 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
413 |
} while (0) |
414 |
|
415 |
#define x86_xchg_mem_reg(inst,mem,reg,size) \ |
416 |
do { \ |
417 |
if ((size) == 1) \ |
418 |
*(inst)++ = (unsigned char)0x86; \ |
419 |
else \ |
420 |
*(inst)++ = (unsigned char)0x87; \ |
421 |
x86_mem_emit ((inst), (reg), (mem)); \ |
422 |
} while (0) |
423 |
|
424 |
#define x86_xchg_membase_reg(inst,basereg,disp,reg,size) \ |
425 |
do { \ |
426 |
if ((size) == 1) \ |
427 |
*(inst)++ = (unsigned char)0x86; \ |
428 |
else \ |
429 |
*(inst)++ = (unsigned char)0x87; \ |
430 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
431 |
} while (0) |
432 |
|
433 |
#define x86_xadd_reg_reg(inst,dreg,reg,size) \ |
434 |
do { \ |
435 |
*(inst)++ = (unsigned char)0x0F; \ |
436 |
if ((size) == 1) \ |
437 |
*(inst)++ = (unsigned char)0xC0; \ |
438 |
else \ |
439 |
*(inst)++ = (unsigned char)0xC1; \ |
440 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
441 |
} while (0) |
442 |
|
443 |
#define x86_xadd_mem_reg(inst,mem,reg,size) \ |
444 |
do { \ |
445 |
*(inst)++ = (unsigned char)0x0F; \ |
446 |
if ((size) == 1) \ |
447 |
*(inst)++ = (unsigned char)0xC0; \ |
448 |
else \ |
449 |
*(inst)++ = (unsigned char)0xC1; \ |
450 |
x86_mem_emit ((inst), (reg), (mem)); \ |
451 |
} while (0) |
452 |
|
453 |
#define x86_xadd_membase_reg(inst,basereg,disp,reg,size) \ |
454 |
do { \ |
455 |
*(inst)++ = (unsigned char)0x0F; \ |
456 |
if ((size) == 1) \ |
457 |
*(inst)++ = (unsigned char)0xC0; \ |
458 |
else \ |
459 |
*(inst)++ = (unsigned char)0xC1; \ |
460 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
461 |
} while (0) |
462 |
|
463 |
#define x86_inc_mem(inst,mem) \ |
464 |
do { \ |
465 |
*(inst)++ = (unsigned char)0xff; \ |
466 |
x86_mem_emit ((inst), 0, (mem)); \ |
467 |
} while (0) |
468 |
|
469 |
#define x86_inc_membase(inst,basereg,disp) \ |
470 |
do { \ |
471 |
*(inst)++ = (unsigned char)0xff; \ |
472 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
473 |
} while (0) |
474 |
|
475 |
#define x86_inc_reg(inst,reg) do { *(inst)++ = (unsigned char)0x40 + (reg); } while (0) |
476 |
|
477 |
#define x86_dec_mem(inst,mem) \ |
478 |
do { \ |
479 |
*(inst)++ = (unsigned char)0xff; \ |
480 |
x86_mem_emit ((inst), 1, (mem)); \ |
481 |
} while (0) |
482 |
|
483 |
#define x86_dec_membase(inst,basereg,disp) \ |
484 |
do { \ |
485 |
*(inst)++ = (unsigned char)0xff; \ |
486 |
x86_membase_emit ((inst), 1, (basereg), (disp)); \ |
487 |
} while (0) |
488 |
|
489 |
#define x86_dec_reg(inst,reg) do { *(inst)++ = (unsigned char)0x48 + (reg); } while (0) |
490 |
|
491 |
#define x86_not_mem(inst,mem) \ |
492 |
do { \ |
493 |
*(inst)++ = (unsigned char)0xf7; \ |
494 |
x86_mem_emit ((inst), 2, (mem)); \ |
495 |
} while (0) |
496 |
|
497 |
#define x86_not_membase(inst,basereg,disp) \ |
498 |
do { \ |
499 |
*(inst)++ = (unsigned char)0xf7; \ |
500 |
x86_membase_emit ((inst), 2, (basereg), (disp)); \ |
501 |
} while (0) |
502 |
|
503 |
#define x86_not_reg(inst,reg) \ |
504 |
do { \ |
505 |
*(inst)++ = (unsigned char)0xf7; \ |
506 |
x86_reg_emit ((inst), 2, (reg)); \ |
507 |
} while (0) |
508 |
|
509 |
#define x86_neg_mem(inst,mem) \ |
510 |
do { \ |
511 |
*(inst)++ = (unsigned char)0xf7; \ |
512 |
x86_mem_emit ((inst), 3, (mem)); \ |
513 |
} while (0) |
514 |
|
515 |
#define x86_neg_membase(inst,basereg,disp) \ |
516 |
do { \ |
517 |
*(inst)++ = (unsigned char)0xf7; \ |
518 |
x86_membase_emit ((inst), 3, (basereg), (disp)); \ |
519 |
} while (0) |
520 |
|
521 |
#define x86_neg_reg(inst,reg) \ |
522 |
do { \ |
523 |
*(inst)++ = (unsigned char)0xf7; \ |
524 |
x86_reg_emit ((inst), 3, (reg)); \ |
525 |
} while (0) |
526 |
|
527 |
#define x86_nop(inst) do { *(inst)++ = (unsigned char)0x90; } while (0) |
528 |
|
529 |
#define x86_alu_reg_imm(inst,opc,reg,imm) \ |
530 |
do { \ |
531 |
if ((reg) == X86_EAX) { \ |
532 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 5; \ |
533 |
x86_imm_emit32 ((inst), (imm)); \ |
534 |
break; \ |
535 |
} \ |
536 |
if (x86_is_imm8((imm))) { \ |
537 |
*(inst)++ = (unsigned char)0x83; \ |
538 |
x86_reg_emit ((inst), (opc), (reg)); \ |
539 |
x86_imm_emit8 ((inst), (imm)); \ |
540 |
} else { \ |
541 |
*(inst)++ = (unsigned char)0x81; \ |
542 |
x86_reg_emit ((inst), (opc), (reg)); \ |
543 |
x86_imm_emit32 ((inst), (imm)); \ |
544 |
} \ |
545 |
} while (0) |
546 |
|
547 |
#define x86_alu_mem_imm(inst,opc,mem,imm) \ |
548 |
do { \ |
549 |
if (x86_is_imm8((imm))) { \ |
550 |
*(inst)++ = (unsigned char)0x83; \ |
551 |
x86_mem_emit ((inst), (opc), (mem)); \ |
552 |
x86_imm_emit8 ((inst), (imm)); \ |
553 |
} else { \ |
554 |
*(inst)++ = (unsigned char)0x81; \ |
555 |
x86_mem_emit ((inst), (opc), (mem)); \ |
556 |
x86_imm_emit32 ((inst), (imm)); \ |
557 |
} \ |
558 |
} while (0) |
559 |
|
560 |
#define x86_alu_membase_imm(inst,opc,basereg,disp,imm) \ |
561 |
do { \ |
562 |
if (x86_is_imm8((imm))) { \ |
563 |
*(inst)++ = (unsigned char)0x83; \ |
564 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
565 |
x86_imm_emit8 ((inst), (imm)); \ |
566 |
} else { \ |
567 |
*(inst)++ = (unsigned char)0x81; \ |
568 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
569 |
x86_imm_emit32 ((inst), (imm)); \ |
570 |
} \ |
571 |
} while (0) |
572 |
|
573 |
#define x86_alu_membase8_imm(inst,opc,basereg,disp,imm) \ |
574 |
do { \ |
575 |
*(inst)++ = (unsigned char)0x80; \ |
576 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
577 |
x86_imm_emit8 ((inst), (imm)); \ |
578 |
} while (0) |
579 |
|
580 |
#define x86_alu_mem_reg(inst,opc,mem,reg) \ |
581 |
do { \ |
582 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 1; \ |
583 |
x86_mem_emit ((inst), (reg), (mem)); \ |
584 |
} while (0) |
585 |
|
586 |
#define x86_alu_membase_reg(inst,opc,basereg,disp,reg) \ |
587 |
do { \ |
588 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 1; \ |
589 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
590 |
} while (0) |
591 |
|
592 |
#define x86_alu_reg_reg(inst,opc,dreg,reg) \ |
593 |
do { \ |
594 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 3; \ |
595 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
596 |
} while (0) |
597 |
|
598 |
/** |
599 |
* @x86_alu_reg8_reg8: |
600 |
* Supports ALU operations between two 8-bit registers. |
601 |
* dreg := dreg opc reg |
602 |
* X86_Reg_No enum is used to specify the registers. |
603 |
* Additionally is_*_h flags are used to specify what part |
604 |
* of a given 32-bit register is used - high (TRUE) or low (FALSE). |
605 |
* For example: dreg = X86_EAX, is_dreg_h = TRUE -> use AH |
606 |
*/ |
607 |
#define x86_alu_reg8_reg8(inst,opc,dreg,reg,is_dreg_h,is_reg_h) \ |
608 |
do { \ |
609 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 2; \ |
610 |
x86_reg8_emit ((inst), (dreg), (reg), (is_dreg_h), (is_reg_h)); \ |
611 |
} while (0) |
612 |
|
613 |
#define x86_alu_reg_mem(inst,opc,reg,mem) \ |
614 |
do { \ |
615 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 3; \ |
616 |
x86_mem_emit ((inst), (reg), (mem)); \ |
617 |
} while (0) |
618 |
|
619 |
#define x86_alu_reg_membase(inst,opc,reg,basereg,disp) \ |
620 |
do { \ |
621 |
*(inst)++ = (((unsigned char)(opc)) << 3) + 3; \ |
622 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
623 |
} while (0) |
624 |
|
625 |
#define x86_test_reg_imm(inst,reg,imm) \ |
626 |
do { \ |
627 |
if ((reg) == X86_EAX) { \ |
628 |
*(inst)++ = (unsigned char)0xa9; \ |
629 |
} else { \ |
630 |
*(inst)++ = (unsigned char)0xf7; \ |
631 |
x86_reg_emit ((inst), 0, (reg)); \ |
632 |
} \ |
633 |
x86_imm_emit32 ((inst), (imm)); \ |
634 |
} while (0) |
635 |
|
636 |
#define x86_test_mem_imm(inst,mem,imm) \ |
637 |
do { \ |
638 |
*(inst)++ = (unsigned char)0xf7; \ |
639 |
x86_mem_emit ((inst), 0, (mem)); \ |
640 |
x86_imm_emit32 ((inst), (imm)); \ |
641 |
} while (0) |
642 |
|
643 |
#define x86_test_membase_imm(inst,basereg,disp,imm) \ |
644 |
do { \ |
645 |
*(inst)++ = (unsigned char)0xf7; \ |
646 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
647 |
x86_imm_emit32 ((inst), (imm)); \ |
648 |
} while (0) |
649 |
|
650 |
#define x86_test_reg_reg(inst,dreg,reg) \ |
651 |
do { \ |
652 |
*(inst)++ = (unsigned char)0x85; \ |
653 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
654 |
} while (0) |
655 |
|
656 |
#define x86_test_mem_reg(inst,mem,reg) \ |
657 |
do { \ |
658 |
*(inst)++ = (unsigned char)0x85; \ |
659 |
x86_mem_emit ((inst), (reg), (mem)); \ |
660 |
} while (0) |
661 |
|
662 |
#define x86_test_membase_reg(inst,basereg,disp,reg) \ |
663 |
do { \ |
664 |
*(inst)++ = (unsigned char)0x85; \ |
665 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
666 |
} while (0) |
667 |
|
668 |
#define x86_shift_reg_imm(inst,opc,reg,imm) \ |
669 |
do { \ |
670 |
if ((imm) == 1) { \ |
671 |
*(inst)++ = (unsigned char)0xd1; \ |
672 |
x86_reg_emit ((inst), (opc), (reg)); \ |
673 |
} else { \ |
674 |
*(inst)++ = (unsigned char)0xc1; \ |
675 |
x86_reg_emit ((inst), (opc), (reg)); \ |
676 |
x86_imm_emit8 ((inst), (imm)); \ |
677 |
} \ |
678 |
} while (0) |
679 |
|
680 |
#define x86_shift_mem_imm(inst,opc,mem,imm) \ |
681 |
do { \ |
682 |
if ((imm) == 1) { \ |
683 |
*(inst)++ = (unsigned char)0xd1; \ |
684 |
x86_mem_emit ((inst), (opc), (mem)); \ |
685 |
} else { \ |
686 |
*(inst)++ = (unsigned char)0xc1; \ |
687 |
x86_mem_emit ((inst), (opc), (mem)); \ |
688 |
x86_imm_emit8 ((inst), (imm)); \ |
689 |
} \ |
690 |
} while (0) |
691 |
|
692 |
#define x86_shift_membase_imm(inst,opc,basereg,disp,imm) \ |
693 |
do { \ |
694 |
if ((imm) == 1) { \ |
695 |
*(inst)++ = (unsigned char)0xd1; \ |
696 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
697 |
} else { \ |
698 |
*(inst)++ = (unsigned char)0xc1; \ |
699 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
700 |
x86_imm_emit8 ((inst), (imm)); \ |
701 |
} \ |
702 |
} while (0) |
703 |
|
704 |
#define x86_shift_reg(inst,opc,reg) \ |
705 |
do { \ |
706 |
*(inst)++ = (unsigned char)0xd3; \ |
707 |
x86_reg_emit ((inst), (opc), (reg)); \ |
708 |
} while (0) |
709 |
|
710 |
#define x86_shift_mem(inst,opc,mem) \ |
711 |
do { \ |
712 |
*(inst)++ = (unsigned char)0xd3; \ |
713 |
x86_mem_emit ((inst), (opc), (mem)); \ |
714 |
} while (0) |
715 |
|
716 |
#define x86_shift_membase(inst,opc,basereg,disp) \ |
717 |
do { \ |
718 |
*(inst)++ = (unsigned char)0xd3; \ |
719 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
720 |
} while (0) |
721 |
|
722 |
/* |
723 |
* Multi op shift missing. |
724 |
*/ |
725 |
|
726 |
#define x86_shrd_reg(inst,dreg,reg) \ |
727 |
do { \ |
728 |
*(inst)++ = (unsigned char)0x0f; \ |
729 |
*(inst)++ = (unsigned char)0xad; \ |
730 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
731 |
} while (0) |
732 |
|
733 |
#define x86_shrd_reg_imm(inst,dreg,reg,shamt) \ |
734 |
do { \ |
735 |
*(inst)++ = (unsigned char)0x0f; \ |
736 |
*(inst)++ = (unsigned char)0xac; \ |
737 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
738 |
x86_imm_emit8 ((inst), (shamt)); \ |
739 |
} while (0) |
740 |
|
741 |
#define x86_shld_reg(inst,dreg,reg) \ |
742 |
do { \ |
743 |
*(inst)++ = (unsigned char)0x0f; \ |
744 |
*(inst)++ = (unsigned char)0xa5; \ |
745 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
746 |
} while (0) |
747 |
|
748 |
#define x86_shld_reg_imm(inst,dreg,reg,shamt) \ |
749 |
do { \ |
750 |
*(inst)++ = (unsigned char)0x0f; \ |
751 |
*(inst)++ = (unsigned char)0xa4; \ |
752 |
x86_reg_emit ((inst), (reg), (dreg)); \ |
753 |
x86_imm_emit8 ((inst), (shamt)); \ |
754 |
} while (0) |
755 |
|
756 |
/* |
757 |
* EDX:EAX = EAX * rm |
758 |
*/ |
759 |
#define x86_mul_reg(inst,reg,is_signed) \ |
760 |
do { \ |
761 |
*(inst)++ = (unsigned char)0xf7; \ |
762 |
x86_reg_emit ((inst), 4 + ((is_signed) ? 1 : 0), (reg)); \ |
763 |
} while (0) |
764 |
|
765 |
#define x86_mul_mem(inst,mem,is_signed) \ |
766 |
do { \ |
767 |
*(inst)++ = (unsigned char)0xf7; \ |
768 |
x86_mem_emit ((inst), 4 + ((is_signed) ? 1 : 0), (mem)); \ |
769 |
} while (0) |
770 |
|
771 |
#define x86_mul_membase(inst,basereg,disp,is_signed) \ |
772 |
do { \ |
773 |
*(inst)++ = (unsigned char)0xf7; \ |
774 |
x86_membase_emit ((inst), 4 + ((is_signed) ? 1 : 0), (basereg), (disp)); \ |
775 |
} while (0) |
776 |
|
777 |
/* |
778 |
* r *= rm |
779 |
*/ |
780 |
#define x86_imul_reg_reg(inst,dreg,reg) \ |
781 |
do { \ |
782 |
*(inst)++ = (unsigned char)0x0f; \ |
783 |
*(inst)++ = (unsigned char)0xaf; \ |
784 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
785 |
} while (0) |
786 |
|
787 |
#define x86_imul_reg_mem(inst,reg,mem) \ |
788 |
do { \ |
789 |
*(inst)++ = (unsigned char)0x0f; \ |
790 |
*(inst)++ = (unsigned char)0xaf; \ |
791 |
x86_mem_emit ((inst), (reg), (mem)); \ |
792 |
} while (0) |
793 |
|
794 |
#define x86_imul_reg_membase(inst,reg,basereg,disp) \ |
795 |
do { \ |
796 |
*(inst)++ = (unsigned char)0x0f; \ |
797 |
*(inst)++ = (unsigned char)0xaf; \ |
798 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
799 |
} while (0) |
800 |
|
801 |
/* |
802 |
* dreg = rm * imm |
803 |
*/ |
804 |
#define x86_imul_reg_reg_imm(inst,dreg,reg,imm) \ |
805 |
do { \ |
806 |
if (x86_is_imm8 ((imm))) { \ |
807 |
*(inst)++ = (unsigned char)0x6b; \ |
808 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
809 |
x86_imm_emit8 ((inst), (imm)); \ |
810 |
} else { \ |
811 |
*(inst)++ = (unsigned char)0x69; \ |
812 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
813 |
x86_imm_emit32 ((inst), (imm)); \ |
814 |
} \ |
815 |
} while (0) |
816 |
|
817 |
#define x86_imul_reg_mem_imm(inst,reg,mem,imm) \ |
818 |
do { \ |
819 |
if (x86_is_imm8 ((imm))) { \ |
820 |
*(inst)++ = (unsigned char)0x6b; \ |
821 |
x86_mem_emit ((inst), (reg), (mem)); \ |
822 |
x86_imm_emit8 ((inst), (imm)); \ |
823 |
} else { \ |
824 |
*(inst)++ = (unsigned char)0x69; \ |
825 |
x86_reg_emit ((inst), (reg), (mem)); \ |
826 |
x86_imm_emit32 ((inst), (imm)); \ |
827 |
} \ |
828 |
} while (0) |
829 |
|
830 |
#define x86_imul_reg_membase_imm(inst,reg,basereg,disp,imm) \ |
831 |
do { \ |
832 |
if (x86_is_imm8 ((imm))) { \ |
833 |
*(inst)++ = (unsigned char)0x6b; \ |
834 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
835 |
x86_imm_emit8 ((inst), (imm)); \ |
836 |
} else { \ |
837 |
*(inst)++ = (unsigned char)0x69; \ |
838 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
839 |
x86_imm_emit32 ((inst), (imm)); \ |
840 |
} \ |
841 |
} while (0) |
842 |
|
843 |
/* |
844 |
* divide EDX:EAX by rm; |
845 |
* eax = quotient, edx = remainder |
846 |
*/ |
847 |
|
848 |
#define x86_div_reg(inst,reg,is_signed) \ |
849 |
do { \ |
850 |
*(inst)++ = (unsigned char)0xf7; \ |
851 |
x86_reg_emit ((inst), 6 + ((is_signed) ? 1 : 0), (reg)); \ |
852 |
} while (0) |
853 |
|
854 |
#define x86_div_mem(inst,mem,is_signed) \ |
855 |
do { \ |
856 |
*(inst)++ = (unsigned char)0xf7; \ |
857 |
x86_mem_emit ((inst), 6 + ((is_signed) ? 1 : 0), (mem)); \ |
858 |
} while (0) |
859 |
|
860 |
#define x86_div_membase(inst,basereg,disp,is_signed) \ |
861 |
do { \ |
862 |
*(inst)++ = (unsigned char)0xf7; \ |
863 |
x86_membase_emit ((inst), 6 + ((is_signed) ? 1 : 0), (basereg), (disp)); \ |
864 |
} while (0) |
865 |
|
866 |
#define x86_mov_mem_reg(inst,mem,reg,size) \ |
867 |
do { \ |
868 |
switch ((size)) { \ |
869 |
case 1: *(inst)++ = (unsigned char)0x88; break; \ |
870 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
871 |
case 4: *(inst)++ = (unsigned char)0x89; break; \ |
872 |
default: assert (0); \ |
873 |
} \ |
874 |
x86_mem_emit ((inst), (reg), (mem)); \ |
875 |
} while (0) |
876 |
|
877 |
#define x86_mov_regp_reg(inst,regp,reg,size) \ |
878 |
do { \ |
879 |
switch ((size)) { \ |
880 |
case 1: *(inst)++ = (unsigned char)0x88; break; \ |
881 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
882 |
case 4: *(inst)++ = (unsigned char)0x89; break; \ |
883 |
default: assert (0); \ |
884 |
} \ |
885 |
x86_regp_emit ((inst), (reg), (regp)); \ |
886 |
} while (0) |
887 |
|
888 |
#define x86_mov_membase_reg(inst,basereg,disp,reg,size) \ |
889 |
do { \ |
890 |
switch ((size)) { \ |
891 |
case 1: *(inst)++ = (unsigned char)0x88; break; \ |
892 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
893 |
case 4: *(inst)++ = (unsigned char)0x89; break; \ |
894 |
default: assert (0); \ |
895 |
} \ |
896 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
897 |
} while (0) |
898 |
|
899 |
#define x86_mov_memindex_reg(inst,basereg,disp,indexreg,shift,reg,size) \ |
900 |
do { \ |
901 |
switch ((size)) { \ |
902 |
case 1: *(inst)++ = (unsigned char)0x88; break; \ |
903 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
904 |
case 4: *(inst)++ = (unsigned char)0x89; break; \ |
905 |
default: assert (0); \ |
906 |
} \ |
907 |
x86_memindex_emit ((inst), (reg), (basereg), (disp), (indexreg), (shift)); \ |
908 |
} while (0) |
909 |
|
910 |
#define x86_mov_reg_reg(inst,dreg,reg,size) \ |
911 |
do { \ |
912 |
switch ((size)) { \ |
913 |
case 1: *(inst)++ = (unsigned char)0x8a; break; \ |
914 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
915 |
case 4: *(inst)++ = (unsigned char)0x8b; break; \ |
916 |
default: assert (0); \ |
917 |
} \ |
918 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
919 |
} while (0) |
920 |
|
921 |
#define x86_mov_reg_mem(inst,reg,mem,size) \ |
922 |
do { \ |
923 |
switch ((size)) { \ |
924 |
case 1: *(inst)++ = (unsigned char)0x8a; break; \ |
925 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
926 |
case 4: *(inst)++ = (unsigned char)0x8b; break; \ |
927 |
default: assert (0); \ |
928 |
} \ |
929 |
x86_mem_emit ((inst), (reg), (mem)); \ |
930 |
} while (0) |
931 |
|
932 |
#define x86_mov_reg_membase(inst,reg,basereg,disp,size) \ |
933 |
do { \ |
934 |
switch ((size)) { \ |
935 |
case 1: *(inst)++ = (unsigned char)0x8a; break; \ |
936 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
937 |
case 4: *(inst)++ = (unsigned char)0x8b; break; \ |
938 |
default: assert (0); \ |
939 |
} \ |
940 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
941 |
} while (0) |
942 |
|
943 |
#define x86_mov_reg_memindex(inst,reg,basereg,disp,indexreg,shift,size) \ |
944 |
do { \ |
945 |
switch ((size)) { \ |
946 |
case 1: *(inst)++ = (unsigned char)0x8a; break; \ |
947 |
case 2: *(inst)++ = (unsigned char)0x66; /* fall through */ \ |
948 |
case 4: *(inst)++ = (unsigned char)0x8b; break; \ |
949 |
default: assert (0); \ |
950 |
} \ |
951 |
x86_memindex_emit ((inst), (reg), (basereg), (disp), (indexreg), (shift)); \ |
952 |
} while (0) |
953 |
|
954 |
/* |
955 |
* Note: x86_clear_reg () chacnges the condition code! |
956 |
*/ |
957 |
#define x86_clear_reg(inst,reg) x86_alu_reg_reg((inst), X86_XOR, (reg), (reg)) |
958 |
|
959 |
#define x86_mov_reg_imm(inst,reg,imm) \ |
960 |
do { \ |
961 |
*(inst)++ = (unsigned char)0xb8 + (reg); \ |
962 |
x86_imm_emit32 ((inst), (imm)); \ |
963 |
} while (0) |
964 |
|
965 |
#define x86_mov_mem_imm(inst,mem,imm,size) \ |
966 |
do { \ |
967 |
if ((size) == 1) { \ |
968 |
*(inst)++ = (unsigned char)0xc6; \ |
969 |
x86_mem_emit ((inst), 0, (mem)); \ |
970 |
x86_imm_emit8 ((inst), (imm)); \ |
971 |
} else if ((size) == 2) { \ |
972 |
*(inst)++ = (unsigned char)0x66; \ |
973 |
*(inst)++ = (unsigned char)0xc7; \ |
974 |
x86_mem_emit ((inst), 0, (mem)); \ |
975 |
x86_imm_emit16 ((inst), (imm)); \ |
976 |
} else { \ |
977 |
*(inst)++ = (unsigned char)0xc7; \ |
978 |
x86_mem_emit ((inst), 0, (mem)); \ |
979 |
x86_imm_emit32 ((inst), (imm)); \ |
980 |
} \ |
981 |
} while (0) |
982 |
|
983 |
#define x86_mov_membase_imm(inst,basereg,disp,imm,size) \ |
984 |
do { \ |
985 |
if ((size) == 1) { \ |
986 |
*(inst)++ = (unsigned char)0xc6; \ |
987 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
988 |
x86_imm_emit8 ((inst), (imm)); \ |
989 |
} else if ((size) == 2) { \ |
990 |
*(inst)++ = (unsigned char)0x66; \ |
991 |
*(inst)++ = (unsigned char)0xc7; \ |
992 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
993 |
x86_imm_emit16 ((inst), (imm)); \ |
994 |
} else { \ |
995 |
*(inst)++ = (unsigned char)0xc7; \ |
996 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
997 |
x86_imm_emit32 ((inst), (imm)); \ |
998 |
} \ |
999 |
} while (0) |
1000 |
|
1001 |
#define x86_mov_memindex_imm(inst,basereg,disp,indexreg,shift,imm,size) \ |
1002 |
do { \ |
1003 |
if ((size) == 1) { \ |
1004 |
*(inst)++ = (unsigned char)0xc6; \ |
1005 |
x86_memindex_emit ((inst), 0, (basereg), (disp), (indexreg), (shift)); \ |
1006 |
x86_imm_emit8 ((inst), (imm)); \ |
1007 |
} else if ((size) == 2) { \ |
1008 |
*(inst)++ = (unsigned char)0x66; \ |
1009 |
*(inst)++ = (unsigned char)0xc7; \ |
1010 |
x86_memindex_emit ((inst), 0, (basereg), (disp), (indexreg), (shift)); \ |
1011 |
x86_imm_emit16 ((inst), (imm)); \ |
1012 |
} else { \ |
1013 |
*(inst)++ = (unsigned char)0xc7; \ |
1014 |
x86_memindex_emit ((inst), 0, (basereg), (disp), (indexreg), (shift)); \ |
1015 |
x86_imm_emit32 ((inst), (imm)); \ |
1016 |
} \ |
1017 |
} while (0) |
1018 |
|
1019 |
#define x86_lea_mem(inst,reg,mem) \ |
1020 |
do { \ |
1021 |
*(inst)++ = (unsigned char)0x8d; \ |
1022 |
x86_mem_emit ((inst), (reg), (mem)); \ |
1023 |
} while (0) |
1024 |
|
1025 |
#define x86_lea_membase(inst,reg,basereg,disp) \ |
1026 |
do { \ |
1027 |
*(inst)++ = (unsigned char)0x8d; \ |
1028 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
1029 |
} while (0) |
1030 |
|
1031 |
#define x86_lea_memindex(inst,reg,basereg,disp,indexreg,shift) \ |
1032 |
do { \ |
1033 |
*(inst)++ = (unsigned char)0x8d; \ |
1034 |
x86_memindex_emit ((inst), (reg), (basereg), (disp), (indexreg), (shift)); \ |
1035 |
} while (0) |
1036 |
|
1037 |
#define x86_widen_reg(inst,dreg,reg,is_signed,is_half) \ |
1038 |
do { \ |
1039 |
unsigned char op = 0xb6; \ |
1040 |
assert (is_half || X86_IS_BYTE_REG (reg)); \ |
1041 |
*(inst)++ = (unsigned char)0x0f; \ |
1042 |
if ((is_signed)) op += 0x08; \ |
1043 |
if ((is_half)) op += 0x01; \ |
1044 |
*(inst)++ = op; \ |
1045 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
1046 |
} while (0) |
1047 |
|
1048 |
#define x86_widen_mem(inst,dreg,mem,is_signed,is_half) \ |
1049 |
do { \ |
1050 |
unsigned char op = 0xb6; \ |
1051 |
*(inst)++ = (unsigned char)0x0f; \ |
1052 |
if ((is_signed)) op += 0x08; \ |
1053 |
if ((is_half)) op += 0x01; \ |
1054 |
*(inst)++ = op; \ |
1055 |
x86_mem_emit ((inst), (dreg), (mem)); \ |
1056 |
} while (0) |
1057 |
|
1058 |
#define x86_widen_membase(inst,dreg,basereg,disp,is_signed,is_half) \ |
1059 |
do { \ |
1060 |
unsigned char op = 0xb6; \ |
1061 |
*(inst)++ = (unsigned char)0x0f; \ |
1062 |
if ((is_signed)) op += 0x08; \ |
1063 |
if ((is_half)) op += 0x01; \ |
1064 |
*(inst)++ = op; \ |
1065 |
x86_membase_emit ((inst), (dreg), (basereg), (disp)); \ |
1066 |
} while (0) |
1067 |
|
1068 |
#define x86_widen_memindex(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half) \ |
1069 |
do { \ |
1070 |
unsigned char op = 0xb6; \ |
1071 |
*(inst)++ = (unsigned char)0x0f; \ |
1072 |
if ((is_signed)) op += 0x08; \ |
1073 |
if ((is_half)) op += 0x01; \ |
1074 |
*(inst)++ = op; \ |
1075 |
x86_memindex_emit ((inst), (dreg), (basereg), (disp), (indexreg), (shift)); \ |
1076 |
} while (0) |
1077 |
|
1078 |
#define x86_lahf(inst) do { *(inst)++ = (unsigned char)0x9f; } while (0) |
1079 |
#define x86_sahf(inst) do { *(inst)++ = (unsigned char)0x9e; } while (0) |
1080 |
#define x86_xchg_ah_al(inst) \ |
1081 |
do { \ |
1082 |
*(inst)++ = (unsigned char)0x86; \ |
1083 |
*(inst)++ = (unsigned char)0xe0; \ |
1084 |
} while (0) |
1085 |
|
1086 |
|
1087 |
#define x86_cdq(inst) do { *(inst)++ = (unsigned char)0x99; } while (0) |
1088 |
#define x86_wait(inst) do { *(inst)++ = (unsigned char)0x9b; } while (0) |
1089 |
|
1090 |
#define x86_fp_op_mem(inst,opc,mem,is_double) \ |
1091 |
do { \ |
1092 |
*(inst)++ = (is_double) ? (unsigned char)0xdc : (unsigned char)0xd8; \ |
1093 |
x86_mem_emit ((inst), (opc), (mem)); \ |
1094 |
} while (0) |
1095 |
|
1096 |
#define x86_fp_op_membase(inst,opc,basereg,disp,is_double) \ |
1097 |
do { \ |
1098 |
*(inst)++ = (is_double) ? (unsigned char)0xdc : (unsigned char)0xd8; \ |
1099 |
x86_membase_emit ((inst), (opc), (basereg), (disp)); \ |
1100 |
} while (0) |
1101 |
|
1102 |
#define x86_fp_op(inst,opc,index) \ |
1103 |
do { \ |
1104 |
*(inst)++ = (unsigned char)0xd8; \ |
1105 |
*(inst)++ = (unsigned char)0xc0+((opc)<<3)+((index)&0x07); \ |
1106 |
} while (0) |
1107 |
|
1108 |
#define x86_fp_op_reg(inst,opc,index,pop_stack) \ |
1109 |
do { \ |
1110 |
static const unsigned char map[] = { 0, 1, 2, 3, 5, 4, 7, 6, 8}; \ |
1111 |
*(inst)++ = (pop_stack) ? (unsigned char)0xde : (unsigned char)0xdc; \ |
1112 |
*(inst)++ = (unsigned char)0xc0+(map[(opc)]<<3)+((index)&0x07); \ |
1113 |
} while (0) |
1114 |
|
1115 |
/** |
1116 |
* @x86_fp_int_op_membase |
1117 |
* Supports FPU operations between ST(0) and integer operand in memory. |
1118 |
* Operation encoded using X86_FP_Opcode enum. |
1119 |
* Operand is addressed by [basereg + disp]. |
1120 |
* is_int specifies whether operand is int32 (TRUE) or int16 (FALSE). |
1121 |
*/ |
1122 |
#define x86_fp_int_op_membase(inst,opc,basereg,disp,is_int) \ |
1123 |
do { \ |
1124 |
*(inst)++ = (is_int) ? (unsigned char)0xda : (unsigned char)0xde; \ |
1125 |
x86_membase_emit ((inst), opc, (basereg), (disp)); \ |
1126 |
} while (0) |
1127 |
|
1128 |
#define x86_fstp(inst,index) \ |
1129 |
do { \ |
1130 |
*(inst)++ = (unsigned char)0xdd; \ |
1131 |
*(inst)++ = (unsigned char)0xd8+(index); \ |
1132 |
} while (0) |
1133 |
|
1134 |
#define x86_fcompp(inst) \ |
1135 |
do { \ |
1136 |
*(inst)++ = (unsigned char)0xde; \ |
1137 |
*(inst)++ = (unsigned char)0xd9; \ |
1138 |
} while (0) |
1139 |
|
1140 |
#define x86_fucompp(inst) \ |
1141 |
do { \ |
1142 |
*(inst)++ = (unsigned char)0xda; \ |
1143 |
*(inst)++ = (unsigned char)0xe9; \ |
1144 |
} while (0) |
1145 |
|
1146 |
#define x86_fnstsw(inst) \ |
1147 |
do { \ |
1148 |
*(inst)++ = (unsigned char)0xdf; \ |
1149 |
*(inst)++ = (unsigned char)0xe0; \ |
1150 |
} while (0) |
1151 |
|
1152 |
#define x86_fnstcw(inst,mem) \ |
1153 |
do { \ |
1154 |
*(inst)++ = (unsigned char)0xd9; \ |
1155 |
x86_mem_emit ((inst), 7, (mem)); \ |
1156 |
} while (0) |
1157 |
|
1158 |
#define x86_fnstcw_membase(inst,basereg,disp) \ |
1159 |
do { \ |
1160 |
*(inst)++ = (unsigned char)0xd9; \ |
1161 |
x86_membase_emit ((inst), 7, (basereg), (disp)); \ |
1162 |
} while (0) |
1163 |
|
1164 |
#define x86_fldcw(inst,mem) \ |
1165 |
do { \ |
1166 |
*(inst)++ = (unsigned char)0xd9; \ |
1167 |
x86_mem_emit ((inst), 5, (mem)); \ |
1168 |
} while (0) |
1169 |
|
1170 |
#define x86_fldcw_membase(inst,basereg,disp) \ |
1171 |
do { \ |
1172 |
*(inst)++ = (unsigned char)0xd9; \ |
1173 |
x86_membase_emit ((inst), 5, (basereg), (disp)); \ |
1174 |
} while (0) |
1175 |
|
1176 |
#define x86_fchs(inst) \ |
1177 |
do { \ |
1178 |
*(inst)++ = (unsigned char)0xd9; \ |
1179 |
*(inst)++ = (unsigned char)0xe0; \ |
1180 |
} while (0) |
1181 |
|
1182 |
#define x86_frem(inst) \ |
1183 |
do { \ |
1184 |
*(inst)++ = (unsigned char)0xd9; \ |
1185 |
*(inst)++ = (unsigned char)0xf8; \ |
1186 |
} while (0) |
1187 |
|
1188 |
#define x86_fxch(inst,index) \ |
1189 |
do { \ |
1190 |
*(inst)++ = (unsigned char)0xd9; \ |
1191 |
*(inst)++ = (unsigned char)0xc8 + ((index) & 0x07); \ |
1192 |
} while (0) |
1193 |
|
1194 |
#define x86_fcomi(inst,index) \ |
1195 |
do { \ |
1196 |
*(inst)++ = (unsigned char)0xdb; \ |
1197 |
*(inst)++ = (unsigned char)0xf0 + ((index) & 0x07); \ |
1198 |
} while (0) |
1199 |
|
1200 |
#define x86_fcomip(inst,index) \ |
1201 |
do { \ |
1202 |
*(inst)++ = (unsigned char)0xdf; \ |
1203 |
*(inst)++ = (unsigned char)0xf0 + ((index) & 0x07); \ |
1204 |
} while (0) |
1205 |
|
1206 |
#define x86_fucomi(inst,index) \ |
1207 |
do { \ |
1208 |
*(inst)++ = (unsigned char)0xdb; \ |
1209 |
*(inst)++ = (unsigned char)0xe8 + ((index) & 0x07); \ |
1210 |
} while (0) |
1211 |
|
1212 |
#define x86_fucomip(inst,index) \ |
1213 |
do { \ |
1214 |
*(inst)++ = (unsigned char)0xdf; \ |
1215 |
*(inst)++ = (unsigned char)0xe8 + ((index) & 0x07); \ |
1216 |
} while (0) |
1217 |
|
1218 |
#define x86_fld(inst,mem,is_double) \ |
1219 |
do { \ |
1220 |
*(inst)++ = (is_double) ? (unsigned char)0xdd : (unsigned char)0xd9; \ |
1221 |
x86_mem_emit ((inst), 0, (mem)); \ |
1222 |
} while (0) |
1223 |
|
1224 |
#define x86_fld_membase(inst,basereg,disp,is_double) \ |
1225 |
do { \ |
1226 |
*(inst)++ = (is_double) ? (unsigned char)0xdd : (unsigned char)0xd9; \ |
1227 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
1228 |
} while (0) |
1229 |
|
1230 |
#define x86_fld80_mem(inst,mem) \ |
1231 |
do { \ |
1232 |
*(inst)++ = (unsigned char)0xdb; \ |
1233 |
x86_mem_emit ((inst), 5, (mem)); \ |
1234 |
} while (0) |
1235 |
|
1236 |
#define x86_fld80_membase(inst,basereg,disp) \ |
1237 |
do { \ |
1238 |
*(inst)++ = (unsigned char)0xdb; \ |
1239 |
x86_membase_emit ((inst), 5, (basereg), (disp)); \ |
1240 |
} while (0) |
1241 |
|
1242 |
#define x86_fild(inst,mem,is_long) \ |
1243 |
do { \ |
1244 |
if ((is_long)) { \ |
1245 |
*(inst)++ = (unsigned char)0xdf; \ |
1246 |
x86_mem_emit ((inst), 5, (mem)); \ |
1247 |
} else { \ |
1248 |
*(inst)++ = (unsigned char)0xdb; \ |
1249 |
x86_mem_emit ((inst), 0, (mem)); \ |
1250 |
} \ |
1251 |
} while (0) |
1252 |
|
1253 |
#define x86_fild_membase(inst,basereg,disp,is_long) \ |
1254 |
do { \ |
1255 |
if ((is_long)) { \ |
1256 |
*(inst)++ = (unsigned char)0xdf; \ |
1257 |
x86_membase_emit ((inst), 5, (basereg), (disp)); \ |
1258 |
} else { \ |
1259 |
*(inst)++ = (unsigned char)0xdb; \ |
1260 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
1261 |
} \ |
1262 |
} while (0) |
1263 |
|
1264 |
#define x86_fld_reg(inst,index) \ |
1265 |
do { \ |
1266 |
*(inst)++ = (unsigned char)0xd9; \ |
1267 |
*(inst)++ = (unsigned char)0xc0 + ((index) & 0x07); \ |
1268 |
} while (0) |
1269 |
|
1270 |
#define x86_fldz(inst) \ |
1271 |
do { \ |
1272 |
*(inst)++ = (unsigned char)0xd9; \ |
1273 |
*(inst)++ = (unsigned char)0xee; \ |
1274 |
} while (0) |
1275 |
|
1276 |
#define x86_fld1(inst) \ |
1277 |
do { \ |
1278 |
*(inst)++ = (unsigned char)0xd9; \ |
1279 |
*(inst)++ = (unsigned char)0xe8; \ |
1280 |
} while (0) |
1281 |
|
1282 |
#define x86_fldpi(inst) \ |
1283 |
do { \ |
1284 |
*(inst)++ = (unsigned char)0xd9; \ |
1285 |
*(inst)++ = (unsigned char)0xeb; \ |
1286 |
} while (0) |
1287 |
|
1288 |
#define x86_fst(inst,mem,is_double,pop_stack) \ |
1289 |
do { \ |
1290 |
*(inst)++ = (is_double) ? (unsigned char)0xdd: (unsigned char)0xd9; \ |
1291 |
x86_mem_emit ((inst), 2 + ((pop_stack) ? 1 : 0), (mem)); \ |
1292 |
} while (0) |
1293 |
|
1294 |
#define x86_fst_membase(inst,basereg,disp,is_double,pop_stack) \ |
1295 |
do { \ |
1296 |
*(inst)++ = (is_double) ? (unsigned char)0xdd: (unsigned char)0xd9; \ |
1297 |
x86_membase_emit ((inst), 2 + ((pop_stack) ? 1 : 0), (basereg), (disp)); \ |
1298 |
} while (0) |
1299 |
|
1300 |
#define x86_fst80_mem(inst,mem) \ |
1301 |
do { \ |
1302 |
*(inst)++ = (unsigned char)0xdb; \ |
1303 |
x86_mem_emit ((inst), 7, (mem)); \ |
1304 |
} while (0) |
1305 |
|
1306 |
|
1307 |
#define x86_fst80_membase(inst,basereg,disp) \ |
1308 |
do { \ |
1309 |
*(inst)++ = (unsigned char)0xdb; \ |
1310 |
x86_membase_emit ((inst), 7, (basereg), (disp)); \ |
1311 |
} while (0) |
1312 |
|
1313 |
|
1314 |
#define x86_fist_pop(inst,mem,is_long) \ |
1315 |
do { \ |
1316 |
if ((is_long)) { \ |
1317 |
*(inst)++ = (unsigned char)0xdf; \ |
1318 |
x86_mem_emit ((inst), 7, (mem)); \ |
1319 |
} else { \ |
1320 |
*(inst)++ = (unsigned char)0xdb; \ |
1321 |
x86_mem_emit ((inst), 3, (mem)); \ |
1322 |
} \ |
1323 |
} while (0) |
1324 |
|
1325 |
#define x86_fist_pop_membase(inst,basereg,disp,is_long) \ |
1326 |
do { \ |
1327 |
if ((is_long)) { \ |
1328 |
*(inst)++ = (unsigned char)0xdf; \ |
1329 |
x86_membase_emit ((inst), 7, (basereg), (disp)); \ |
1330 |
} else { \ |
1331 |
*(inst)++ = (unsigned char)0xdb; \ |
1332 |
x86_membase_emit ((inst), 3, (basereg), (disp)); \ |
1333 |
} \ |
1334 |
} while (0) |
1335 |
|
1336 |
#define x86_fstsw(inst) \ |
1337 |
do { \ |
1338 |
*(inst)++ = (unsigned char)0x9b; \ |
1339 |
*(inst)++ = (unsigned char)0xdf; \ |
1340 |
*(inst)++ = (unsigned char)0xe0; \ |
1341 |
} while (0) |
1342 |
|
1343 |
/** |
1344 |
* @x86_fist_membase |
1345 |
* Converts content of ST(0) to integer and stores it at memory location |
1346 |
* addressed by [basereg + disp]. |
1347 |
* is_int specifies whether destination is int32 (TRUE) or int16 (FALSE). |
1348 |
*/ |
1349 |
#define x86_fist_membase(inst,basereg,disp,is_int) \ |
1350 |
do { \ |
1351 |
if ((is_int)) { \ |
1352 |
*(inst)++ = (unsigned char)0xdb; \ |
1353 |
x86_membase_emit ((inst), 2, (basereg), (disp)); \ |
1354 |
} else { \ |
1355 |
*(inst)++ = (unsigned char)0xdf; \ |
1356 |
x86_membase_emit ((inst), 2, (basereg), (disp)); \ |
1357 |
} \ |
1358 |
} while (0) |
1359 |
|
1360 |
|
1361 |
#define x86_push_reg(inst,reg) \ |
1362 |
do { \ |
1363 |
*(inst)++ = (unsigned char)0x50 + (reg); \ |
1364 |
} while (0) |
1365 |
|
1366 |
#define x86_push_regp(inst,reg) \ |
1367 |
do { \ |
1368 |
*(inst)++ = (unsigned char)0xff; \ |
1369 |
x86_regp_emit ((inst), 6, (reg)); \ |
1370 |
} while (0) |
1371 |
|
1372 |
#define x86_push_mem(inst,mem) \ |
1373 |
do { \ |
1374 |
*(inst)++ = (unsigned char)0xff; \ |
1375 |
x86_mem_emit ((inst), 6, (mem)); \ |
1376 |
} while (0) |
1377 |
|
1378 |
#define x86_push_membase(inst,basereg,disp) \ |
1379 |
do { \ |
1380 |
*(inst)++ = (unsigned char)0xff; \ |
1381 |
x86_membase_emit ((inst), 6, (basereg), (disp)); \ |
1382 |
} while (0) |
1383 |
|
1384 |
#define x86_push_memindex(inst,basereg,disp,indexreg,shift) \ |
1385 |
do { \ |
1386 |
*(inst)++ = (unsigned char)0xff; \ |
1387 |
x86_memindex_emit ((inst), 6, (basereg), (disp), (indexreg), (shift)); \ |
1388 |
} while (0) |
1389 |
|
1390 |
#define x86_push_imm_template(inst) x86_push_imm (inst, 0xf0f0f0f0) |
1391 |
|
1392 |
#define x86_push_imm(inst,imm) \ |
1393 |
do { \ |
1394 |
int _imm = (int) (imm); \ |
1395 |
if (x86_is_imm8 (_imm)) { \ |
1396 |
*(inst)++ = (unsigned char)0x6A; \ |
1397 |
x86_imm_emit8 ((inst), (_imm)); \ |
1398 |
} else { \ |
1399 |
*(inst)++ = (unsigned char)0x68; \ |
1400 |
x86_imm_emit32 ((inst), (_imm)); \ |
1401 |
} \ |
1402 |
} while (0) |
1403 |
|
1404 |
#define x86_pop_reg(inst,reg) \ |
1405 |
do { \ |
1406 |
*(inst)++ = (unsigned char)0x58 + (reg); \ |
1407 |
} while (0) |
1408 |
|
1409 |
#define x86_pop_mem(inst,mem) \ |
1410 |
do { \ |
1411 |
*(inst)++ = (unsigned char)0x87; \ |
1412 |
x86_mem_emit ((inst), 0, (mem)); \ |
1413 |
} while (0) |
1414 |
|
1415 |
#define x86_pop_membase(inst,basereg,disp) \ |
1416 |
do { \ |
1417 |
*(inst)++ = (unsigned char)0x87; \ |
1418 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
1419 |
} while (0) |
1420 |
|
1421 |
#define x86_pushad(inst) do { *(inst)++ = (unsigned char)0x60; } while (0) |
1422 |
#define x86_pushfd(inst) do { *(inst)++ = (unsigned char)0x9c; } while (0) |
1423 |
#define x86_popad(inst) do { *(inst)++ = (unsigned char)0x61; } while (0) |
1424 |
#define x86_popfd(inst) do { *(inst)++ = (unsigned char)0x9d; } while (0) |
1425 |
|
1426 |
#define x86_loop(inst,imm) \ |
1427 |
do { \ |
1428 |
*(inst)++ = (unsigned char)0xe2; \ |
1429 |
x86_imm_emit8 ((inst), (imm)); \ |
1430 |
} while (0) |
1431 |
|
1432 |
#define x86_loope(inst,imm) \ |
1433 |
do { \ |
1434 |
*(inst)++ = (unsigned char)0xe1; \ |
1435 |
x86_imm_emit8 ((inst), (imm)); \ |
1436 |
} while (0) |
1437 |
|
1438 |
#define x86_loopne(inst,imm) \ |
1439 |
do { \ |
1440 |
*(inst)++ = (unsigned char)0xe0; \ |
1441 |
x86_imm_emit8 ((inst), (imm)); \ |
1442 |
} while (0) |
1443 |
|
1444 |
#define x86_jump32(inst,imm) \ |
1445 |
do { \ |
1446 |
*(inst)++ = (unsigned char)0xe9; \ |
1447 |
x86_imm_emit32 ((inst), (imm)); \ |
1448 |
} while (0) |
1449 |
|
1450 |
#define x86_jump8(inst,imm) \ |
1451 |
do { \ |
1452 |
*(inst)++ = (unsigned char)0xeb; \ |
1453 |
x86_imm_emit8 ((inst), (imm)); \ |
1454 |
} while (0) |
1455 |
|
1456 |
#define x86_jump_reg(inst,reg) \ |
1457 |
do { \ |
1458 |
*(inst)++ = (unsigned char)0xff; \ |
1459 |
x86_reg_emit ((inst), 4, (reg)); \ |
1460 |
} while (0) |
1461 |
|
1462 |
#define x86_jump_mem(inst,mem) \ |
1463 |
do { \ |
1464 |
*(inst)++ = (unsigned char)0xff; \ |
1465 |
x86_mem_emit ((inst), 4, (mem)); \ |
1466 |
} while (0) |
1467 |
|
1468 |
#define x86_jump_membase(inst,basereg,disp) \ |
1469 |
do { \ |
1470 |
*(inst)++ = (unsigned char)0xff; \ |
1471 |
x86_membase_emit ((inst), 4, (basereg), (disp)); \ |
1472 |
} while (0) |
1473 |
|
1474 |
/* |
1475 |
* target is a pointer in our buffer. |
1476 |
*/ |
1477 |
#define x86_jump_code(inst,target) \ |
1478 |
do { \ |
1479 |
int t = (unsigned char*)(target) - (inst) - 2; \ |
1480 |
if (x86_is_imm8(t)) { \ |
1481 |
x86_jump8 ((inst), t); \ |
1482 |
} else { \ |
1483 |
t -= 3; \ |
1484 |
x86_jump32 ((inst), t); \ |
1485 |
} \ |
1486 |
} while (0) |
1487 |
|
1488 |
#define x86_jump_disp(inst,disp) \ |
1489 |
do { \ |
1490 |
int t = (disp) - 2; \ |
1491 |
if (x86_is_imm8(t)) { \ |
1492 |
x86_jump8 ((inst), t); \ |
1493 |
} else { \ |
1494 |
t -= 3; \ |
1495 |
x86_jump32 ((inst), t); \ |
1496 |
} \ |
1497 |
} while (0) |
1498 |
|
1499 |
#define x86_branch8(inst,cond,imm,is_signed) \ |
1500 |
do { \ |
1501 |
if ((is_signed)) \ |
1502 |
*(inst)++ = x86_cc_signed_map [(cond)]; \ |
1503 |
else \ |
1504 |
*(inst)++ = x86_cc_unsigned_map [(cond)]; \ |
1505 |
x86_imm_emit8 ((inst), (imm)); \ |
1506 |
} while (0) |
1507 |
|
1508 |
#define x86_branch32(inst,cond,imm,is_signed) \ |
1509 |
do { \ |
1510 |
*(inst)++ = (unsigned char)0x0f; \ |
1511 |
if ((is_signed)) \ |
1512 |
*(inst)++ = x86_cc_signed_map [(cond)] + 0x10; \ |
1513 |
else \ |
1514 |
*(inst)++ = x86_cc_unsigned_map [(cond)] + 0x10; \ |
1515 |
x86_imm_emit32 ((inst), (imm)); \ |
1516 |
} while (0) |
1517 |
|
1518 |
#define x86_branch(inst,cond,target,is_signed) \ |
1519 |
do { \ |
1520 |
int offset = (target) - (inst) - 2; \ |
1521 |
if (x86_is_imm8 ((offset))) \ |
1522 |
x86_branch8 ((inst), (cond), offset, (is_signed)); \ |
1523 |
else { \ |
1524 |
offset -= 4; \ |
1525 |
x86_branch32 ((inst), (cond), offset, (is_signed)); \ |
1526 |
} \ |
1527 |
} while (0) |
1528 |
|
1529 |
#define x86_branch_disp(inst,cond,disp,is_signed) \ |
1530 |
do { \ |
1531 |
int offset = (disp) - 2; \ |
1532 |
if (x86_is_imm8 ((offset))) \ |
1533 |
x86_branch8 ((inst), (cond), offset, (is_signed)); \ |
1534 |
else { \ |
1535 |
offset -= 4; \ |
1536 |
x86_branch32 ((inst), (cond), offset, (is_signed)); \ |
1537 |
} \ |
1538 |
} while (0) |
1539 |
|
1540 |
#define x86_set_reg(inst,cond,reg,is_signed) \ |
1541 |
do { \ |
1542 |
assert (X86_IS_BYTE_REG (reg)); \ |
1543 |
*(inst)++ = (unsigned char)0x0f; \ |
1544 |
if ((is_signed)) \ |
1545 |
*(inst)++ = x86_cc_signed_map [(cond)] + 0x20; \ |
1546 |
else \ |
1547 |
*(inst)++ = x86_cc_unsigned_map [(cond)] + 0x20; \ |
1548 |
x86_reg_emit ((inst), 0, (reg)); \ |
1549 |
} while (0) |
1550 |
|
1551 |
#define x86_set_mem(inst,cond,mem,is_signed) \ |
1552 |
do { \ |
1553 |
*(inst)++ = (unsigned char)0x0f; \ |
1554 |
if ((is_signed)) \ |
1555 |
*(inst)++ = x86_cc_signed_map [(cond)] + 0x20; \ |
1556 |
else \ |
1557 |
*(inst)++ = x86_cc_unsigned_map [(cond)] + 0x20; \ |
1558 |
x86_mem_emit ((inst), 0, (mem)); \ |
1559 |
} while (0) |
1560 |
|
1561 |
#define x86_set_membase(inst,cond,basereg,disp,is_signed) \ |
1562 |
do { \ |
1563 |
*(inst)++ = (unsigned char)0x0f; \ |
1564 |
if ((is_signed)) \ |
1565 |
*(inst)++ = x86_cc_signed_map [(cond)] + 0x20; \ |
1566 |
else \ |
1567 |
*(inst)++ = x86_cc_unsigned_map [(cond)] + 0x20; \ |
1568 |
x86_membase_emit ((inst), 0, (basereg), (disp)); \ |
1569 |
} while (0) |
1570 |
|
1571 |
#define x86_call_imm(inst,disp) \ |
1572 |
do { \ |
1573 |
*(inst)++ = (unsigned char)0xe8; \ |
1574 |
x86_imm_emit32 ((inst), (int)(disp)); \ |
1575 |
} while (0) |
1576 |
|
1577 |
#define x86_call_reg(inst,reg) \ |
1578 |
do { \ |
1579 |
*(inst)++ = (unsigned char)0xff; \ |
1580 |
x86_reg_emit ((inst), 2, (reg)); \ |
1581 |
} while (0) |
1582 |
|
1583 |
#define x86_call_mem(inst,mem) \ |
1584 |
do { \ |
1585 |
*(inst)++ = (unsigned char)0xff; \ |
1586 |
x86_mem_emit ((inst), 2, (mem)); \ |
1587 |
} while (0) |
1588 |
|
1589 |
#define x86_call_membase(inst,basereg,disp) \ |
1590 |
do { \ |
1591 |
*(inst)++ = (unsigned char)0xff; \ |
1592 |
x86_membase_emit ((inst), 2, (basereg), (disp)); \ |
1593 |
} while (0) |
1594 |
|
1595 |
#define x86_call_code(inst,target) \ |
1596 |
do { \ |
1597 |
int _x86_offset = (unsigned char*)(target) - (inst); \ |
1598 |
_x86_offset -= 5; \ |
1599 |
x86_call_imm ((inst), _x86_offset); \ |
1600 |
} while (0) |
1601 |
|
1602 |
#define x86_ret(inst) do { *(inst)++ = (unsigned char)0xc3; } while (0) |
1603 |
|
1604 |
#define x86_ret_imm(inst,imm) \ |
1605 |
do { \ |
1606 |
if ((imm) == 0) { \ |
1607 |
x86_ret ((inst)); \ |
1608 |
} else { \ |
1609 |
*(inst)++ = (unsigned char)0xc2; \ |
1610 |
x86_imm_emit16 ((inst), (imm)); \ |
1611 |
} \ |
1612 |
} while (0) |
1613 |
|
1614 |
#define x86_cmov_reg(inst,cond,is_signed,dreg,reg) \ |
1615 |
do { \ |
1616 |
*(inst)++ = (unsigned char) 0x0f; \ |
1617 |
if ((is_signed)) \ |
1618 |
*(inst)++ = x86_cc_signed_map [(cond)] - 0x30; \ |
1619 |
else \ |
1620 |
*(inst)++ = x86_cc_unsigned_map [(cond)] - 0x30; \ |
1621 |
x86_reg_emit ((inst), (dreg), (reg)); \ |
1622 |
} while (0) |
1623 |
|
1624 |
#define x86_cmov_mem(inst,cond,is_signed,reg,mem) \ |
1625 |
do { \ |
1626 |
*(inst)++ = (unsigned char) 0x0f; \ |
1627 |
if ((is_signed)) \ |
1628 |
*(inst)++ = x86_cc_signed_map [(cond)] - 0x30; \ |
1629 |
else \ |
1630 |
*(inst)++ = x86_cc_unsigned_map [(cond)] - 0x30; \ |
1631 |
x86_mem_emit ((inst), (reg), (mem)); \ |
1632 |
} while (0) |
1633 |
|
1634 |
#define x86_cmov_membase(inst,cond,is_signed,reg,basereg,disp) \ |
1635 |
do { \ |
1636 |
*(inst)++ = (unsigned char) 0x0f; \ |
1637 |
if ((is_signed)) \ |
1638 |
*(inst)++ = x86_cc_signed_map [(cond)] - 0x30; \ |
1639 |
else \ |
1640 |
*(inst)++ = x86_cc_unsigned_map [(cond)] - 0x30; \ |
1641 |
x86_membase_emit ((inst), (reg), (basereg), (disp)); \ |
1642 |
} while (0) |
1643 |
|
1644 |
#define x86_enter(inst,framesize) \ |
1645 |
do { \ |
1646 |
*(inst)++ = (unsigned char)0xc8; \ |
1647 |
x86_imm_emit16 ((inst), (framesize)); \ |
1648 |
*(inst)++ = 0; \ |
1649 |
} while (0) |
1650 |
|
1651 |
#define x86_leave(inst) do { *(inst)++ = (unsigned char)0xc9; } while (0) |
1652 |
#define x86_sahf(inst) do { *(inst)++ = (unsigned char)0x9e; } while (0) |
1653 |
|
1654 |
#define x86_fsin(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xfe; } while (0) |
1655 |
#define x86_fcos(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xff; } while (0) |
1656 |
#define x86_fabs(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xe1; } while (0) |
1657 |
#define x86_ftst(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xe4; } while (0) |
1658 |
#define x86_fxam(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xe5; } while (0) |
1659 |
#define x86_fpatan(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xf3; } while (0) |
1660 |
#define x86_fprem(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xf8; } while (0) |
1661 |
#define x86_fprem1(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xf5; } while (0) |
1662 |
#define x86_frndint(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xfc; } while (0) |
1663 |
#define x86_fsqrt(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xfa; } while (0) |
1664 |
#define x86_fptan(inst) do { *(inst)++ = (unsigned char)0xd9; *(inst)++ = (unsigned char)0xf2; } while (0) |
1665 |
|
1666 |
#define x86_padding(inst,size) \ |
1667 |
do { \ |
1668 |
switch ((size)) { \ |
1669 |
case 1: x86_nop ((inst)); break; \ |
1670 |
case 2: *(inst)++ = 0x8b; \ |
1671 |
*(inst)++ = 0xc0; break; \ |
1672 |
case 3: *(inst)++ = 0x8d; *(inst)++ = 0x6d; \ |
1673 |
*(inst)++ = 0x00; break; \ |
1674 |
case 4: *(inst)++ = 0x8d; *(inst)++ = 0x64; \ |
1675 |
*(inst)++ = 0x24; *(inst)++ = 0x00; \ |
1676 |
break; \ |
1677 |
case 5: *(inst)++ = 0x8d; *(inst)++ = 0x64; \ |
1678 |
*(inst)++ = 0x24; *(inst)++ = 0x00; \ |
1679 |
x86_nop ((inst)); break; \ |
1680 |
case 6: *(inst)++ = 0x8d; *(inst)++ = 0xad; \ |
1681 |
*(inst)++ = 0x00; *(inst)++ = 0x00; \ |
1682 |
*(inst)++ = 0x00; *(inst)++ = 0x00; \ |
1683 |
break; \ |
1684 |
case 7: *(inst)++ = 0x8d; *(inst)++ = 0xa4; \ |
1685 |
*(inst)++ = 0x24; *(inst)++ = 0x00; \ |
1686 |
*(inst)++ = 0x00; *(inst)++ = 0x00; \ |
1687 |
*(inst)++ = 0x00; break; \ |
1688 |
default: assert (0); \ |
1689 |
} \ |
1690 |
} while (0) |
1691 |
|
1692 |
#define x86_prolog(inst,frame_size,reg_mask) \ |
1693 |
do { \ |
1694 |
unsigned i, m = 1; \ |
1695 |
x86_enter ((inst), (frame_size)); \ |
1696 |
for (i = 0; i < X86_NREG; ++i, m <<= 1) { \ |
1697 |
if ((reg_mask) & m) \ |
1698 |
x86_push_reg ((inst), i); \ |
1699 |
} \ |
1700 |
} while (0) |
1701 |
|
1702 |
#define x86_epilog(inst,reg_mask) \ |
1703 |
do { \ |
1704 |
unsigned i, m = 1 << X86_EDI; \ |
1705 |
for (i = X86_EDI; m != 0; i--, m=m>>1) { \ |
1706 |
if ((reg_mask) & m) \ |
1707 |
x86_pop_reg ((inst), i); \ |
1708 |
} \ |
1709 |
x86_leave ((inst)); \ |
1710 |
x86_ret ((inst)); \ |
1711 |
} while (0) |
1712 |
|
1713 |
#endif // X86_H |