1 /*
2 * ix86 core v0.6.2
3 * Authors: linuzappz <linuzappz@pcsx.net>
4 * alexey silinov
5 * goldfinger
6 * zerofrog(@gmail.com)
7 */
8
9 #ifdef __x86_64__
10
11 // stop compiling if NORECBUILD build (only for Visual Studio)
12 #if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <assert.h>
17 #include "ix86-64.h"
18
19 #ifdef __x86_64__
20
21 #ifdef _MSC_VER
22 // visual studio calling convention
23 x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 };
24 x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX };
25
26 // arranged in savedreg -> tempreg order
27 x86IntRegType g_x86allregs[14] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15, R8, R9, R10, R11, RDX, RCX };
28
29 #else
30 // standard calling convention
31
32 // registers saved by called functions (no need to flush them across calls)
33 x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 };
34 // temp registers that need to be saved across calls
35 x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI };
36
37 // arranged in savedreg -> tempreg order
38 x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI };
39
40 #endif
41
42 x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 };
43 x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI };
44
45 #endif // __x86_64__
46
47 s8 *x86Ptr;
48 u8 *j8Ptr[32];
49 u32 *j32Ptr[32];
50
WriteRmOffset(x86IntRegType to,int offset)51 void WriteRmOffset(x86IntRegType to, int offset)
52 {
53 if( (to&7) == ESP ) {
54 if( offset == 0 ) {
55 ModRM( 0, 0, 4 );
56 ModRM( 0, ESP, 4 );
57 }
58 else if( offset < 128 && offset >= -128 ) {
59 ModRM( 1, 0, 4 );
60 ModRM( 0, ESP, 4 );
61 write8(offset);
62 }
63 else {
64 ModRM( 2, 0, 4 );
65 ModRM( 0, ESP, 4 );
66 write32(offset);
67 }
68 }
69 else {
70 if( offset == 0 ) {
71 ModRM( 0, 0, to );
72 }
73 else if( offset < 128 && offset >= -128 ) {
74 ModRM( 1, 0, to );
75 write8(offset);
76 }
77 else {
78 ModRM( 2, 0, to );
79 write32(offset);
80 }
81 }
82 }
83
WriteRmOffsetFrom(x86IntRegType to,x86IntRegType from,int offset)84 void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset)
85 {
86 if ((from&7) == ESP) {
87 if( offset == 0 ) {
88 ModRM( 0, to, 0x4 );
89 SibSB( 0, 0x4, 0x4 );
90 }
91 else if( offset < 128 && offset >= -128 ) {
92 ModRM( 1, to, 0x4 );
93 SibSB( 0, 0x4, 0x4 );
94 write8(offset);
95 }
96 else {
97 ModRM( 2, to, 0x4 );
98 SibSB( 0, 0x4, 0x4 );
99 write32(offset);
100 }
101 }
102 else {
103 if( offset == 0 ) {
104 ModRM( 0, to, from );
105 }
106 else if( offset < 128 && offset >= -128 ) {
107 ModRM( 1, to, from );
108 write8(offset);
109 }
110 else {
111 ModRM( 2, to, from );
112 write32(offset);
113 }
114 }
115 }
116
117 // This function is just for rec debugging purposes
CheckX86Ptr(void)118 void CheckX86Ptr( void )
119 {
120 }
121
writeVAROP(unsigned opl,u64 op)122 void writeVAROP(unsigned opl, u64 op)
123 {
124 while (opl--)
125 {
126 write8(op & 0xFF);
127 op >>= 8;
128 }
129 }
130
131 #define writeVARROP(REX, opl, op) ({ \
132 if (opl > 1 && ((op & 0xFF) == 0x66 || (op & 0xFF) == 0xF3 || (op & 0xFF) == 0xF2)) { \
133 write8(op & 0xFF); \
134 opl --; \
135 op >>= 8; \
136 } \
137 REX; \
138 writeVAROP(opl, op); \
139 })
140
MEMADDR_OP(bool w,unsigned opl,u64 op,bool isreg,int reg,uptr p,sptr off)141 void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off)
142 {
143 #ifdef __x86_64__
144 sptr pr = MEMADDR_(p, 5 + opl + (w || reg >= 8) + off);
145 if (SPTR32(pr))
146 {
147 writeVARROP(RexR(w, reg), opl, op);
148 ModRM(0, reg, DISP32);
149 write32(pr);
150 }
151 else if (UPTR32(p))
152 {
153 writeVARROP(RexR(w, reg), opl, op);
154 ModRM(0, reg, SIB);
155 SibSB(0, SIB, DISP32);
156 write32(p);
157 }
158 else
159 {
160 assert(!isreg || reg != X86_TEMP);
161 MOV64ItoR(X86_TEMP, p);
162 writeVARROP(RexRB(w, reg, X86_TEMP), opl, op);
163 ModRM(0, reg, X86_TEMP);
164 }
165 #else
166 writeVARROP(RexR(w, reg), opl, op);
167 ModRM(0, reg, DISP32);
168 write32(p);
169 #endif
170 }
171
SET8R(int cc,int to)172 void SET8R( int cc, int to )
173 {
174 RexB(0, to);
175 write8( 0x0F );
176 write8( cc );
177 write8( 0xC0 | ( to ) );
178 }
179
J8Rel(int cc,int to)180 u8* J8Rel( int cc, int to )
181 {
182 write8( cc );
183 write8( to );
184 return x86Ptr - 1;
185 }
186
J16Rel(int cc,u32 to)187 u16* J16Rel( int cc, u32 to )
188 {
189 write16( 0x0F66 );
190 write8( cc );
191 write16( to );
192 return (u16*)( x86Ptr - 2 );
193 }
194
J32Rel(int cc,u32 to)195 u32* J32Rel( int cc, u32 to )
196 {
197 write8( 0x0F );
198 write8( cc );
199 write32( to );
200 return (u32*)( x86Ptr - 4 );
201 }
202
CMOV32RtoR(int cc,int to,int from)203 void CMOV32RtoR( int cc, int to, int from )
204 {
205 RexRB(0,to, from);
206 write8( 0x0F );
207 write8( cc );
208 ModRM( 3, to, from );
209 }
210
CMOV32MtoR(int cc,x86IntRegType to,uptr from)211 void CMOV32MtoR( int cc, x86IntRegType to, uptr from )
212 {
213 MEMADDR_OP(0, VAROP2(0x0F, cc), true, to, from, 0);
214 }
215
216 ////////////////////////////////////////////////////
x86SetPtr(char * ptr)217 void x86SetPtr( char* ptr )
218 {
219 x86Ptr = ptr;
220 }
221
222 ////////////////////////////////////////////////////
x86Shutdown(void)223 void x86Shutdown( void )
224 {
225 }
226
227 ////////////////////////////////////////////////////
x86SetJ8(u8 * j8)228 void x86SetJ8( u8* j8 )
229 {
230 u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
231
232 if ( jump > 0x7f ) {
233 SysPrintf( "j8 greater than 0x7f!!\n" );
234 assert(0);
235 }
236 *j8 = (u8)jump;
237 }
238
x86SetJ8A(u8 * j8)239 void x86SetJ8A( u8* j8 )
240 {
241 u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
242
243 if ( jump > 0x7f ) {
244 SysPrintf( "j8 greater than 0x7f!!\n" );
245 //assert(0);
246 }
247
248 if( ((uptr)x86Ptr&0xf) > 4 ) {
249
250 uptr newjump = jump + 16-((uptr)x86Ptr&0xf);
251
252 if( newjump <= 0x7f ) {
253 jump = newjump;
254 while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
255 }
256 }
257 *j8 = (u8)jump;
258 }
259
x86SetJ16(u16 * j16)260 void x86SetJ16( u16 *j16 )
261 {
262 // doesn't work
263 u32 jump = ( x86Ptr - (s8*)j16 ) - 2;
264
265 if ( jump > 0x7fff ) {
266 SysPrintf( "j16 greater than 0x7fff!!\n" );
267 //assert(0);
268 }
269 *j16 = (u16)jump;
270 }
271
x86SetJ16A(u16 * j16)272 void x86SetJ16A( u16 *j16 )
273 {
274 if( ((uptr)x86Ptr&0xf) > 4 ) {
275 while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
276 }
277 x86SetJ16(j16);
278 }
279
280 ////////////////////////////////////////////////////
x86SetJ32(u32 * j32)281 void x86SetJ32( u32* j32 )
282 {
283 *j32 = ( x86Ptr - (s8*)j32 ) - 4;
284 }
285
x86SetJ32A(u32 * j32)286 void x86SetJ32A( u32* j32 )
287 {
288 while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
289 x86SetJ32(j32);
290 }
291
292 ////////////////////////////////////////////////////
x86Align(int bytes)293 void x86Align( int bytes )
294 {
295 // fordward align
296 x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) );
297 }
298
299 /********************/
300 /* IX86 intructions */
301 /********************/
302
STC(void)303 void STC( void )
304 {
305 write8( 0xF9 );
306 }
307
CLC(void)308 void CLC( void )
309 {
310 write8( 0xF8 );
311 }
312
313 ////////////////////////////////////
314 // mov instructions /
315 ////////////////////////////////////
316
317 /* mov r64 to r64 */
MOV64RtoR(x86IntRegType to,x86IntRegType from)318 void MOV64RtoR( x86IntRegType to, x86IntRegType from )
319 {
320 RexRB(1, from, to);
321 write8( 0x89 );
322 ModRM( 3, from, to );
323 }
324
325 /* mov r64 to m64 */
MOV64RtoM(uptr to,x86IntRegType from)326 void MOV64RtoM( uptr to, x86IntRegType from )
327 {
328 if (from == RAX)
329 {
330 RexR(1, 0);
331 write8(0xA3);
332 write64(to);
333 }
334 else
335 {
336 MEMADDR_OP(1, VAROP1(0x89), true, from, to, 0);
337 }
338 }
339
340 /* mov m64 to r64 */
MOV64MtoR(x86IntRegType to,uptr from)341 void MOV64MtoR( x86IntRegType to, uptr from )
342 {
343 if (to == RAX)
344 {
345 RexR(1, 0);
346 write8(0xA1);
347 write64(from);
348 }
349 else
350 {
351 MEMADDR_OP(1, VAROP1(0x8B), true, to, from, 0);
352 }
353 }
354
355 /* mov imm32 to m64 */
MOV64I32toM(uptr to,u32 from)356 void MOV64I32toM(uptr to, u32 from )
357 {
358 MEMADDR_OP(1, VAROP1(0xC7), false, 0, to, 4);
359 write32(from);
360 }
361
362 // mov imm64 to r64
MOV64ItoR(x86IntRegType to,u64 from)363 void MOV64ItoR( x86IntRegType to, u64 from)
364 {
365 RexB(1, to);
366 write8( 0xB8 | (to & 0x7) );
367 write64( from );
368 }
369
370 /* mov imm32 to r64 */
MOV64I32toR(x86IntRegType to,s32 from)371 void MOV64I32toR( x86IntRegType to, s32 from )
372 {
373 RexB(1, to);
374 write8( 0xC7 );
375 ModRM( 0, 0, to );
376 write32( from );
377 }
378
379 // mov imm64 to [r64+off]
MOV64ItoRmOffset(x86IntRegType to,u32 from,int offset)380 void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset)
381 {
382 RexB(1,to);
383 write8( 0xC7 );
384 WriteRmOffset(to, offset);
385 write32(from);
386 }
387
388 // mov [r64+offset] to r64
MOV64RmOffsettoR(x86IntRegType to,x86IntRegType from,int offset)389 void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset )
390 {
391 RexRB(1, to, from);
392 write8( 0x8B );
393 WriteRmOffsetFrom(to, from, offset);
394 }
395
396 /* mov [r64][r64*scale] to r64 */
MOV64RmStoR(x86IntRegType to,x86IntRegType from,x86IntRegType from2,int scale)397 void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
398 RexRXB(1, to, from2, from);
399 write8( 0x8B );
400 ModRM( 0, to, 0x4 );
401 SibSB(scale, from2, from );
402 }
403
404 /* mov r64 to [r64+offset] */
MOV64RtoRmOffset(x86IntRegType to,x86IntRegType from,int offset)405 void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset )
406 {
407 RexRB(1,from,to);
408 write8( 0x89 );
409 WriteRmOffsetFrom(from, to, offset);
410 }
411
412 /* mov r64 to [r64][r64*scale] */
MOV64RtoRmS(x86IntRegType to,x86IntRegType from,x86IntRegType from2,int scale)413 void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
414 RexRXB(1, to, from2, from);
415 write8( 0x89 );
416 ModRM( 0, to, 0x4 );
417 SibSB(scale, from2, from );
418 }
419
420
421 /* mov r32 to r32 */
MOV32RtoR(x86IntRegType to,x86IntRegType from)422 void MOV32RtoR( x86IntRegType to, x86IntRegType from )
423 {
424 RexRB(0, from, to);
425 write8( 0x89 );
426 ModRM( 3, from, to );
427 }
428
429 /* mov r32 to m32 */
MOV32RtoM(uptr to,x86IntRegType from)430 void MOV32RtoM( uptr to, x86IntRegType from )
431 {
432 if (from == EAX)
433 {
434 write8(0xA3);
435 write64(to);
436 }
437 else
438 {
439 MEMADDR_OP(0, VAROP1(0x89), true, from, to, 0);
440 }
441 }
442
443 /* mov m32 to r32 */
MOV32MtoR(x86IntRegType to,uptr from)444 void MOV32MtoR( x86IntRegType to, uptr from )
445 {
446 if (to == RAX)
447 {
448 write8(0xA1);
449 write64(from);
450 }
451 else
452 {
453 MEMADDR_OP(0, VAROP1(0x8B), true, to, from, 0);
454 }
455 }
456
457 /* mov [r32] to r32 */
MOV32RmtoR(x86IntRegType to,x86IntRegType from)458 void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) {
459 RexRB(0, to, from);
460 write8(0x8B);
461 WriteRmOffsetFrom(to, from, 0);
462 }
463
MOV32RmtoROffset(x86IntRegType to,x86IntRegType from,int offset)464 void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) {
465 RexRB(0, to, from);
466 write8( 0x8B );
467 WriteRmOffsetFrom(to, from, offset);
468 }
469
470 /* mov [r32+r32*scale] to r32 */
MOV32RmStoR(x86IntRegType to,x86IntRegType from,x86IntRegType from2,int scale)471 void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
472 RexRXB(0,to,from2,from);
473 write8( 0x8B );
474 ModRM( 0, to, 0x4 );
475 SibSB(scale, from2, from );
476 }
477
478 // mov r32 to [r32<<scale+from2]
MOV32RmSOffsettoR(x86IntRegType to,x86IntRegType from1,int from2,int scale)479 void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale )
480 {
481 RexRXB(0,to,from1,0);
482 write8( 0x8B );
483 ModRM( 0, to, 0x4 );
484 ModRM( scale, from1, 5);
485 write32(from2);
486 }
487
488 /* mov r32 to [r32] */
MOV32RtoRm(x86IntRegType to,x86IntRegType from)489 void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) {
490 RexRB(0, from, to);
491 if ((to&7) == ESP) {
492 write8( 0x89 );
493 ModRM( 0, from, 0x4 );
494 SibSB( 0, 0x4, 0x4 );
495 } else {
496 write8( 0x89 );
497 ModRM( 0, from, to );
498 }
499 }
500
501 /* mov r32 to [r32][r32*scale] */
MOV32RtoRmS(x86IntRegType to,x86IntRegType from,x86IntRegType from2,int scale)502 void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
503 RexRXB(0, to, from2, from);
504 write8( 0x89 );
505 ModRM( 0, to, 0x4 );
506 SibSB(scale, from2, from );
507 }
508
509 /* mov imm32 to r32 */
MOV32ItoR(x86IntRegType to,u32 from)510 void MOV32ItoR( x86IntRegType to, u32 from )
511 {
512 RexB(0, to);
513 write8( 0xB8 | (to & 0x7) );
514 write32( from );
515 }
516
517 /* mov imm32 to m32 */
MOV32ItoM(uptr to,u32 from)518 void MOV32ItoM(uptr to, u32 from )
519 {
520 MEMADDR_OP(0, VAROP1(0xC7), false, 0, to, 4);
521 write32(from);
522 }
523
524 // mov imm32 to [r32+off]
MOV32ItoRmOffset(x86IntRegType to,u32 from,int offset)525 void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset)
526 {
527 RexB(0,to);
528 write8( 0xC7 );
529 WriteRmOffset(to, offset);
530 write32(from);
531 }
532
533 // mov r32 to [r32+off]
MOV32RtoRmOffset(x86IntRegType to,x86IntRegType from,int offset)534 void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
535 {
536 RexRB(0,from,to);
537 write8( 0x89 );
538 WriteRmOffsetFrom(from, to, offset);
539 }
540
541 /* mov r16 to m16 */
MOV16RtoM(uptr to,x86IntRegType from)542 void MOV16RtoM(uptr to, x86IntRegType from )
543 {
544 if (from == EAX)
545 {
546 write8(0x66);
547 write8(0xA3);
548 write64(to);
549 }
550 else
551 {
552 MEMADDR_OP(0, VAROP2(0x66, 0x89), true, from, to, 0);
553 }
554 }
555
556 /* mov m16 to r16 */
MOV16MtoR(x86IntRegType to,uptr from)557 void MOV16MtoR( x86IntRegType to, uptr from )
558 {
559 if (to == EAX)
560 {
561 write8(0x66);
562 write8(0xA1);
563 write64(from);
564 }
565 else
566 {
567 MEMADDR_OP(0, VAROP2(0x66, 0x8B), true, to, from, 0);
568 }
569 }
570
MOV16RmtoR(x86IntRegType to,x86IntRegType from)571 void MOV16RmtoR( x86IntRegType to, x86IntRegType from)
572 {
573 write8( 0x66 );
574 RexRB(0,to,from);
575 write8( 0x8B );
576 WriteRmOffsetFrom(to, from, 0);
577 }
578
MOV16RmtoROffset(x86IntRegType to,x86IntRegType from,int offset)579 void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset )
580 {
581 write8( 0x66 );
582 RexRB(0,to,from);
583 write8( 0x8B );
584 WriteRmOffsetFrom(to, from, offset);
585 }
586
MOV16RmSOffsettoR(x86IntRegType to,x86IntRegType from1,u32 from2,int scale)587 void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale )
588 {
589 write8(0x66);
590 RexRXB(0,to,from1,0);
591 write8( 0x8B );
592 ModRM( 0, to, 0x4 );
593 ModRM( scale, from1, 5);
594 write32(from2);
595 }
596
MOV16RtoRm(x86IntRegType to,x86IntRegType from)597 void MOV16RtoRm(x86IntRegType to, x86IntRegType from)
598 {
599 write8( 0x66 );
600 RexRB(0,from,to);
601 write8( 0x89 );
602 ModRM( 0, from, to );
603 }
604
605 /* mov imm16 to m16 */
MOV16ItoM(uptr to,u16 from)606 void MOV16ItoM( uptr to, u16 from )
607 {
608 MEMADDR_OP(0, VAROP2(0x66, 0xC7), false, 0, to, 2);
609 write16( from );
610 }
611
612 /* mov r16 to [r32][r32*scale] */
MOV16RtoRmS(x86IntRegType to,x86IntRegType from,x86IntRegType from2,int scale)613 void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
614 write8( 0x66 );
615 RexRXB(0,to,from2,from);
616 write8( 0x89 );
617 ModRM( 0, to, 0x4 );
618 SibSB(scale, from2, from );
619 }
620
MOV16ItoR(x86IntRegType to,u16 from)621 void MOV16ItoR( x86IntRegType to, u16 from )
622 {
623 RexB(0, to);
624 write16( 0xB866 | ((to & 0x7)<<8) );
625 write16( from );
626 }
627
628 // mov imm16 to [r16+off]
MOV16ItoRmOffset(x86IntRegType to,u16 from,u32 offset)629 void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset)
630 {
631 write8(0x66);
632 RexB(0,to);
633 write8( 0xC7 );
634 WriteRmOffset(to, offset);
635 write16(from);
636 }
637
638 // mov r16 to [r16+off]
MOV16RtoRmOffset(x86IntRegType to,x86IntRegType from,int offset)639 void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
640 {
641 write8(0x66);
642 RexRB(0,from,to);
643 write8( 0x89 );
644 WriteRmOffsetFrom(from, to, offset);
645 }
646
647 /* mov r8 to m8 */
MOV8RtoM(uptr to,x86IntRegType from)648 void MOV8RtoM( uptr to, x86IntRegType from )
649 {
650 if (from == EAX)
651 {
652 write8(0xA2);
653 write64(to);
654 }
655 else
656 {
657 MEMADDR_OP(0, VAROP1(0x88), true, from, to, 0);
658 }
659 }
660
661 /* mov m8 to r8 */
MOV8MtoR(x86IntRegType to,uptr from)662 void MOV8MtoR( x86IntRegType to, uptr from )
663 {
664 if (to == EAX)
665 {
666 write8(0xA0);
667 write64(from);
668 }
669 else
670 {
671 MEMADDR_OP(0, VAROP1(0x8A), true, to, from, 0);
672 }
673 }
674
675 /* mov [r32] to r8 */
MOV8RmtoR(x86IntRegType to,x86IntRegType from)676 void MOV8RmtoR(x86IntRegType to, x86IntRegType from)
677 {
678 RexRB(0,to,from);
679 write8( 0x8A );
680 WriteRmOffsetFrom(to, from, 0);
681 }
682
MOV8RmtoROffset(x86IntRegType to,x86IntRegType from,int offset)683 void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset)
684 {
685 RexRB(0,to,from);
686 write8( 0x8A );
687 WriteRmOffsetFrom(to, from, offset);
688 }
689
MOV8RtoRm(x86IntRegType to,x86IntRegType from)690 void MOV8RtoRm(x86IntRegType to, x86IntRegType from)
691 {
692 RexRB(0,from,to);
693 write8( 0x88 );
694 WriteRmOffsetFrom(from, to, 0);
695 }
696
697 /* mov imm8 to m8 */
MOV8ItoM(uptr to,u8 from)698 void MOV8ItoM( uptr to, u8 from )
699 {
700 MEMADDR_OP(0, VAROP1(0xC6), false, 0, to, 1);
701 write8( from );
702 }
703
704 // mov imm8 to r8
MOV8ItoR(x86IntRegType to,u8 from)705 void MOV8ItoR( x86IntRegType to, u8 from )
706 {
707 RexB(0, to);
708 write8( 0xB0 | (to & 0x7) );
709 write8( from );
710 }
711
712 // mov imm8 to [r8+off]
MOV8ItoRmOffset(x86IntRegType to,u8 from,int offset)713 void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset)
714 {
715 assert( to != ESP );
716 RexB(0,to);
717 write8( 0xC6 );
718 WriteRmOffset(to,offset);
719 write8(from);
720 }
721
722 // mov r8 to [r8+off]
MOV8RtoRmOffset(x86IntRegType to,x86IntRegType from,int offset)723 void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
724 {
725 assert( to != ESP );
726 RexRB(0,from,to);
727 write8( 0x88 );
728 WriteRmOffsetFrom(from,to,offset);
729 }
730
731 /* movsx r8 to r32 */
MOVSX32R8toR(x86IntRegType to,x86IntRegType from)732 void MOVSX32R8toR( x86IntRegType to, x86IntRegType from )
733 {
734 RexRB(0,to,from);
735 write16( 0xBE0F );
736 ModRM( 3, to, from );
737 }
738
MOVSX32Rm8toR(x86IntRegType to,x86IntRegType from)739 void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from )
740 {
741 RexRB(0,to,from);
742 write16( 0xBE0F );
743 ModRM( 0, to, from );
744 }
745
MOVSX32Rm8toROffset(x86IntRegType to,x86IntRegType from,int offset)746 void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
747 {
748 RexRB(0,to,from);
749 write16( 0xBE0F );
750 WriteRmOffsetFrom(to,from,offset);
751 }
752
753 /* movsx m8 to r32 */
MOVSX32M8toR(x86IntRegType to,uptr from)754 void MOVSX32M8toR( x86IntRegType to, uptr from )
755 {
756 MEMADDR_OP(0, VAROP2(0x0F, 0xBE), true, to, from, 0);
757 }
758
759 /* movsx r16 to r32 */
MOVSX32R16toR(x86IntRegType to,x86IntRegType from)760 void MOVSX32R16toR( x86IntRegType to, x86IntRegType from )
761 {
762 RexRB(0,to,from);
763 write16( 0xBF0F );
764 ModRM( 3, to, from );
765 }
766
MOVSX32Rm16toR(x86IntRegType to,x86IntRegType from)767 void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from )
768 {
769 RexRB(0,to,from);
770 write16( 0xBF0F );
771 ModRM( 0, to, from );
772 }
773
MOVSX32Rm16toROffset(x86IntRegType to,x86IntRegType from,int offset)774 void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
775 {
776 RexRB(0,to,from);
777 write16( 0xBF0F );
778 WriteRmOffsetFrom(to,from,offset);
779 }
780
781 /* movsx m16 to r32 */
MOVSX32M16toR(x86IntRegType to,uptr from)782 void MOVSX32M16toR( x86IntRegType to, uptr from )
783 {
784 MEMADDR_OP(0, VAROP2(0x0F, 0xBF), true, to, from, 0);
785 }
786
787 /* movzx r8 to r32 */
MOVZX32R8toR(x86IntRegType to,x86IntRegType from)788 void MOVZX32R8toR( x86IntRegType to, x86IntRegType from )
789 {
790 RexRB(0,to,from);
791 write16( 0xB60F );
792 ModRM( 3, to, from );
793 }
794
MOVZX32Rm8toR(x86IntRegType to,x86IntRegType from)795 void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from )
796 {
797 RexRB(0,to,from);
798 write16( 0xB60F );
799 ModRM( 0, to, from );
800 }
801
MOVZX32Rm8toROffset(x86IntRegType to,x86IntRegType from,int offset)802 void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
803 {
804 RexRB(0,to,from);
805 write16( 0xB60F );
806 WriteRmOffsetFrom(to,from,offset);
807 }
808
809 /* movzx m8 to r32 */
MOVZX32M8toR(x86IntRegType to,uptr from)810 void MOVZX32M8toR( x86IntRegType to, uptr from )
811 {
812 MEMADDR_OP(0, VAROP2(0x0F, 0xB6), true, to, from, 0);
813 }
814
815 /* movzx r16 to r32 */
MOVZX32R16toR(x86IntRegType to,x86IntRegType from)816 void MOVZX32R16toR( x86IntRegType to, x86IntRegType from )
817 {
818 RexRB(0,to,from);
819 write16( 0xB70F );
820 ModRM( 3, to, from );
821 }
822
MOVZX32Rm16toR(x86IntRegType to,x86IntRegType from)823 void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from )
824 {
825 RexRB(0,to,from);
826 write16( 0xB70F );
827 ModRM( 0, to, from );
828 }
829
MOVZX32Rm16toROffset(x86IntRegType to,x86IntRegType from,int offset)830 void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
831 {
832 RexRB(0,to,from);
833 write16( 0xB70F );
834 WriteRmOffsetFrom(to,from,offset);
835 }
836
837 /* movzx m16 to r32 */
MOVZX32M16toR(x86IntRegType to,uptr from)838 void MOVZX32M16toR( x86IntRegType to, uptr from )
839 {
840 MEMADDR_OP(0, VAROP2(0x0F, 0xB7), true, to, from, 0);
841 }
842
843 #ifdef __x86_64__
844
845 /* movzx r8 to r64 */
MOVZX64R8toR(x86IntRegType to,x86IntRegType from)846 void MOVZX64R8toR( x86IntRegType to, x86IntRegType from )
847 {
848 RexRB(1,to,from);
849 write16( 0xB60F );
850 ModRM( 3, to, from );
851 }
852
MOVZX64Rm8toR(x86IntRegType to,x86IntRegType from)853 void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from )
854 {
855 RexRB(1,to,from);
856 write16( 0xB60F );
857 ModRM( 0, to, from );
858 }
859
MOVZX64Rm8toROffset(x86IntRegType to,x86IntRegType from,int offset)860 void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
861 {
862 RexRB(1,to,from);
863 write16( 0xB60F );
864 WriteRmOffsetFrom(to,from,offset);
865 }
866
867 /* movzx m8 to r64 */
MOVZX64M8toR(x86IntRegType to,uptr from)868 void MOVZX64M8toR( x86IntRegType to, uptr from )
869 {
870 MEMADDR_OP(1, VAROP2(0x0F, 0xB6), true, to, from, 0);
871 }
872
873 /* movzx r16 to r64 */
MOVZX64R16toR(x86IntRegType to,x86IntRegType from)874 void MOVZX64R16toR( x86IntRegType to, x86IntRegType from )
875 {
876 RexRB(1,to,from);
877 write16( 0xB70F );
878 ModRM( 3, to, from );
879 }
880
MOVZX64Rm16toR(x86IntRegType to,x86IntRegType from)881 void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from )
882 {
883 RexRB(1,to,from);
884 write16( 0xB70F );
885 ModRM( 0, to, from );
886 }
887
MOVZX64Rm16toROffset(x86IntRegType to,x86IntRegType from,int offset)888 void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
889 {
890 RexRB(1,to,from);
891 write16( 0xB70F );
892 WriteRmOffsetFrom(to,from,offset);
893 }
894
895 /* movzx m16 to r64 */
MOVZX64M16toR(x86IntRegType to,uptr from)896 void MOVZX64M16toR( x86IntRegType to, uptr from )
897 {
898 MEMADDR_OP(1, VAROP2(0x0F, 0xB7), true, to, from, 0);
899 }
900 #endif
901
902 /* cmovbe r32 to r32 */
CMOVBE32RtoR(x86IntRegType to,x86IntRegType from)903 void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from )
904 {
905 CMOV32RtoR( 0x46, to, from );
906 }
907
908 /* cmovbe m32 to r32*/
CMOVBE32MtoR(x86IntRegType to,uptr from)909 void CMOVBE32MtoR( x86IntRegType to, uptr from )
910 {
911 CMOV32MtoR( 0x46, to, from );
912 }
913
914 /* cmovb r32 to r32 */
CMOVB32RtoR(x86IntRegType to,x86IntRegType from)915 void CMOVB32RtoR( x86IntRegType to, x86IntRegType from )
916 {
917 CMOV32RtoR( 0x42, to, from );
918 }
919
920 /* cmovb m32 to r32*/
CMOVB32MtoR(x86IntRegType to,uptr from)921 void CMOVB32MtoR( x86IntRegType to, uptr from )
922 {
923 CMOV32MtoR( 0x42, to, from );
924 }
925
926 /* cmovae r32 to r32 */
CMOVAE32RtoR(x86IntRegType to,x86IntRegType from)927 void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from )
928 {
929 CMOV32RtoR( 0x43, to, from );
930 }
931
932 /* cmovae m32 to r32*/
CMOVAE32MtoR(x86IntRegType to,uptr from)933 void CMOVAE32MtoR( x86IntRegType to, uptr from )
934 {
935 CMOV32MtoR( 0x43, to, from );
936 }
937
938 /* cmova r32 to r32 */
CMOVA32RtoR(x86IntRegType to,x86IntRegType from)939 void CMOVA32RtoR( x86IntRegType to, x86IntRegType from )
940 {
941 CMOV32RtoR( 0x47, to, from );
942 }
943
944 /* cmova m32 to r32*/
CMOVA32MtoR(x86IntRegType to,uptr from)945 void CMOVA32MtoR( x86IntRegType to, uptr from )
946 {
947 CMOV32MtoR( 0x47, to, from );
948 }
949
950 /* cmovo r32 to r32 */
CMOVO32RtoR(x86IntRegType to,x86IntRegType from)951 void CMOVO32RtoR( x86IntRegType to, x86IntRegType from )
952 {
953 CMOV32RtoR( 0x40, to, from );
954 }
955
956 /* cmovo m32 to r32 */
CMOVO32MtoR(x86IntRegType to,uptr from)957 void CMOVO32MtoR( x86IntRegType to, uptr from )
958 {
959 CMOV32MtoR( 0x40, to, from );
960 }
961
962 /* cmovp r32 to r32 */
CMOVP32RtoR(x86IntRegType to,x86IntRegType from)963 void CMOVP32RtoR( x86IntRegType to, x86IntRegType from )
964 {
965 CMOV32RtoR( 0x4A, to, from );
966 }
967
968 /* cmovp m32 to r32 */
CMOVP32MtoR(x86IntRegType to,uptr from)969 void CMOVP32MtoR( x86IntRegType to, uptr from )
970 {
971 CMOV32MtoR( 0x4A, to, from );
972 }
973
974 /* cmovs r32 to r32 */
CMOVS32RtoR(x86IntRegType to,x86IntRegType from)975 void CMOVS32RtoR( x86IntRegType to, x86IntRegType from )
976 {
977 CMOV32RtoR( 0x48, to, from );
978 }
979
980 /* cmovs m32 to r32 */
CMOVS32MtoR(x86IntRegType to,uptr from)981 void CMOVS32MtoR( x86IntRegType to, uptr from )
982 {
983 CMOV32MtoR( 0x48, to, from );
984 }
985
986 /* cmovno r32 to r32 */
CMOVNO32RtoR(x86IntRegType to,x86IntRegType from)987 void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from )
988 {
989 CMOV32RtoR( 0x41, to, from );
990 }
991
992 /* cmovno m32 to r32 */
CMOVNO32MtoR(x86IntRegType to,uptr from)993 void CMOVNO32MtoR( x86IntRegType to, uptr from )
994 {
995 CMOV32MtoR( 0x41, to, from );
996 }
997
998 /* cmovnp r32 to r32 */
CMOVNP32RtoR(x86IntRegType to,x86IntRegType from)999 void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from )
1000 {
1001 CMOV32RtoR( 0x4B, to, from );
1002 }
1003
1004 /* cmovnp m32 to r32 */
CMOVNP32MtoR(x86IntRegType to,uptr from)1005 void CMOVNP32MtoR( x86IntRegType to, uptr from )
1006 {
1007 CMOV32MtoR( 0x4B, to, from );
1008 }
1009
1010 /* cmovns r32 to r32 */
CMOVNS32RtoR(x86IntRegType to,x86IntRegType from)1011 void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from )
1012 {
1013 CMOV32RtoR( 0x49, to, from );
1014 }
1015
1016 /* cmovns m32 to r32 */
CMOVNS32MtoR(x86IntRegType to,uptr from)1017 void CMOVNS32MtoR( x86IntRegType to, uptr from )
1018 {
1019 CMOV32MtoR( 0x49, to, from );
1020 }
1021
1022 /* cmovne r32 to r32 */
CMOVNE32RtoR(x86IntRegType to,x86IntRegType from)1023 void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from )
1024 {
1025 CMOV32RtoR( 0x45, to, from );
1026 }
1027
1028 /* cmovne m32 to r32*/
CMOVNE32MtoR(x86IntRegType to,uptr from)1029 void CMOVNE32MtoR( x86IntRegType to, uptr from )
1030 {
1031 CMOV32MtoR( 0x45, to, from );
1032 }
1033
1034 /* cmove r32 to r32*/
CMOVE32RtoR(x86IntRegType to,x86IntRegType from)1035 void CMOVE32RtoR( x86IntRegType to, x86IntRegType from )
1036 {
1037 CMOV32RtoR( 0x44, to, from );
1038 }
1039
1040 /* cmove m32 to r32*/
CMOVE32MtoR(x86IntRegType to,uptr from)1041 void CMOVE32MtoR( x86IntRegType to, uptr from )
1042 {
1043 CMOV32MtoR( 0x44, to, from );
1044 }
1045
1046 /* cmovg r32 to r32*/
CMOVG32RtoR(x86IntRegType to,x86IntRegType from)1047 void CMOVG32RtoR( x86IntRegType to, x86IntRegType from )
1048 {
1049 CMOV32RtoR( 0x4F, to, from );
1050 }
1051
1052 /* cmovg m32 to r32*/
CMOVG32MtoR(x86IntRegType to,uptr from)1053 void CMOVG32MtoR( x86IntRegType to, uptr from )
1054 {
1055 CMOV32MtoR( 0x4F, to, from );
1056 }
1057
1058 /* cmovge r32 to r32*/
CMOVGE32RtoR(x86IntRegType to,x86IntRegType from)1059 void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from )
1060 {
1061 CMOV32RtoR( 0x4D, to, from );
1062 }
1063
1064 /* cmovge m32 to r32*/
CMOVGE32MtoR(x86IntRegType to,uptr from)1065 void CMOVGE32MtoR( x86IntRegType to, uptr from )
1066 {
1067 CMOV32MtoR( 0x4D, to, from );
1068 }
1069
1070 /* cmovl r32 to r32*/
CMOVL32RtoR(x86IntRegType to,x86IntRegType from)1071 void CMOVL32RtoR( x86IntRegType to, x86IntRegType from )
1072 {
1073 CMOV32RtoR( 0x4C, to, from );
1074 }
1075
1076 /* cmovl m32 to r32*/
CMOVL32MtoR(x86IntRegType to,uptr from)1077 void CMOVL32MtoR( x86IntRegType to, uptr from )
1078 {
1079 CMOV32MtoR( 0x4C, to, from );
1080 }
1081
1082 /* cmovle r32 to r32*/
CMOVLE32RtoR(x86IntRegType to,x86IntRegType from)1083 void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from )
1084 {
1085 CMOV32RtoR( 0x4E, to, from );
1086 }
1087
1088 /* cmovle m32 to r32*/
CMOVLE32MtoR(x86IntRegType to,uptr from)1089 void CMOVLE32MtoR( x86IntRegType to, uptr from )
1090 {
1091 CMOV32MtoR( 0x4E, to, from );
1092 }
1093
1094 ////////////////////////////////////
1095 // arithmetic instructions /
1096 ////////////////////////////////////
1097
1098 /* add imm32 to r64 */
ADD64ItoR(x86IntRegType to,u32 from)1099 void ADD64ItoR( x86IntRegType to, u32 from )
1100 {
1101 RexB(1, to);
1102 if (from <= 0x7f)
1103 {
1104 write8(0x83);
1105 ModRM( 3, 0, to );
1106 write8(from);
1107 }
1108 else
1109 {
1110 if (to == RAX) {
1111 write8( 0x05 );
1112 } else {
1113 write8( 0x81 );
1114 ModRM( 3, 0, to );
1115 }
1116 write32( from );
1117 }
1118 }
1119
1120 /* add m64 to r64 */
ADD64MtoR(x86IntRegType to,uptr from)1121 void ADD64MtoR( x86IntRegType to, uptr from )
1122 {
1123 MEMADDR_OP(1, VAROP1(0x03), true, to, from, 0);
1124 }
1125
1126 /* add r64 to r64 */
ADD64RtoR(x86IntRegType to,x86IntRegType from)1127 void ADD64RtoR( x86IntRegType to, x86IntRegType from )
1128 {
1129 RexRB(1, from, to);
1130 write8( 0x01 );
1131 ModRM( 3, from, to );
1132 }
1133
1134 /* add imm32 to r32 */
ADD32ItoR(x86IntRegType to,u32 from)1135 void ADD32ItoR( x86IntRegType to, u32 from )
1136 {
1137 RexB(0, to);
1138 if ( to == EAX) {
1139 write8( 0x05 );
1140 }
1141 else {
1142 write8( 0x81 );
1143 ModRM( 3, 0, to );
1144 }
1145 write32( from );
1146 }
1147
1148 /* add imm32 to m32 */
ADD32ItoM(uptr to,u32 from)1149 void ADD32ItoM( uptr to, u32 from )
1150 {
1151 MEMADDR_OP(0, VAROP1(0x81), false, 0, to, 4);
1152 write32(from);
1153 }
1154
1155 // add imm32 to [r32+off]
ADD32ItoRmOffset(x86IntRegType to,u32 from,int offset)1156 void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset)
1157 {
1158 RexB(0,to);
1159 write8( 0x81 );
1160 WriteRmOffset(to,offset);
1161 write32(from);
1162 }
1163
1164 /* add r32 to r32 */
ADD32RtoR(x86IntRegType to,x86IntRegType from)1165 void ADD32RtoR( x86IntRegType to, x86IntRegType from )
1166 {
1167 RexRB(0, from, to);
1168 write8( 0x01 );
1169 ModRM( 3, from, to );
1170 }
1171
1172 /* add r32 to m32 */
ADD32RtoM(uptr to,x86IntRegType from)1173 void ADD32RtoM(uptr to, x86IntRegType from )
1174 {
1175 MEMADDR_OP(0, VAROP1(0x01), true, from, to, 0);
1176 }
1177
1178 /* add m32 to r32 */
ADD32MtoR(x86IntRegType to,uptr from)1179 void ADD32MtoR( x86IntRegType to, uptr from )
1180 {
1181 MEMADDR_OP(0, VAROP1(0x03), true, to, from, 0);
1182 }
1183
1184 // add r16 to r16
ADD16RtoR(x86IntRegType to,x86IntRegType from)1185 void ADD16RtoR( x86IntRegType to , x86IntRegType from )
1186 {
1187 write8(0x66);
1188 RexRB(0,to,from);
1189 write8( 0x03 );
1190 ModRM( 3, to, from );
1191 }
1192
1193 /* add imm16 to r16 */
ADD16ItoR(x86IntRegType to,u16 from)1194 void ADD16ItoR( x86IntRegType to, u16 from )
1195 {
1196 write8( 0x66 );
1197 RexB(0,to);
1198 if ( to == EAX)
1199 {
1200 write8( 0x05 );
1201 }
1202 else
1203 {
1204 write8( 0x81 );
1205 ModRM( 3, 0, to );
1206 }
1207 write16( from );
1208 }
1209
1210 /* add imm16 to m16 */
ADD16ItoM(uptr to,u16 from)1211 void ADD16ItoM( uptr to, u16 from )
1212 {
1213 MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 0, to, 2);
1214 write16( from );
1215 }
1216
1217 /* add r16 to m16 */
ADD16RtoM(uptr to,x86IntRegType from)1218 void ADD16RtoM(uptr to, x86IntRegType from )
1219 {
1220 MEMADDR_OP(0, VAROP2(0x66, 0x01), true, from, to, 0);
1221 }
1222
1223 /* add m16 to r16 */
ADD16MtoR(x86IntRegType to,uptr from)1224 void ADD16MtoR( x86IntRegType to, uptr from )
1225 {
1226 MEMADDR_OP(0, VAROP2(0x66, 0x03), true, to, from, 0);
1227 }
1228
1229 // add m8 to r8
ADD8MtoR(x86IntRegType to,uptr from)1230 void ADD8MtoR( x86IntRegType to, uptr from )
1231 {
1232 MEMADDR_OP(0, VAROP1(0x02), true, to, from, 0);
1233 }
1234
1235 /* adc imm32 to r32 */
ADC32ItoR(x86IntRegType to,u32 from)1236 void ADC32ItoR( x86IntRegType to, u32 from )
1237 {
1238 RexB(0,to);
1239 if ( to == EAX ) {
1240 write8( 0x15 );
1241 }
1242 else {
1243 write8( 0x81 );
1244 ModRM( 3, 2, to );
1245 }
1246 write32( from );
1247 }
1248
1249 /* adc imm32 to m32 */
ADC32ItoM(uptr to,u32 from)1250 void ADC32ItoM( uptr to, u32 from )
1251 {
1252 MEMADDR_OP(0, VAROP1(0x81), false, 2, to, 4);
1253 write32(from);
1254 }
1255
1256 /* adc r32 to r32 */
ADC32RtoR(x86IntRegType to,x86IntRegType from)1257 void ADC32RtoR( x86IntRegType to, x86IntRegType from )
1258 {
1259 RexRB(0,from,to);
1260 write8( 0x11 );
1261 ModRM( 3, from, to );
1262 }
1263
1264 /* adc m32 to r32 */
ADC32MtoR(x86IntRegType to,uptr from)1265 void ADC32MtoR( x86IntRegType to, uptr from )
1266 {
1267 MEMADDR_OP(0, VAROP1(0x13), true, to, from, 0);
1268 }
1269
1270 // adc r32 to m32
ADC32RtoM(uptr to,x86IntRegType from)1271 void ADC32RtoM( uptr to, x86IntRegType from )
1272 {
1273 MEMADDR_OP(0, VAROP1(0x11), true, from, to, 0);
1274 }
1275
1276
1277 #ifdef __x86_64__
INC32R(x86IntRegType to)1278 void INC32R( x86IntRegType to )
1279 {
1280 write8( 0xFF );
1281 ModRM(3,0,to);
1282 }
1283 #else
1284 /* inc r32 */
INC32R(x86IntRegType to)1285 void INC32R( x86IntRegType to )
1286 {
1287 X86_64ASSERT();
1288 write8( 0x40 + to );
1289 }
1290 #endif
1291 /* inc m32 */
INC32M(uptr to)1292 void INC32M( uptr to )
1293 {
1294 MEMADDR_OP(0, VAROP1(0xFF), false, 0, to, 0);
1295 }
1296
1297 /* inc r16 */
INC16R(x86IntRegType to)1298 void INC16R( x86IntRegType to )
1299 {
1300 X86_64ASSERT();
1301 write8( 0x66 );
1302 write8( 0x40 + to );
1303 }
1304
1305 /* inc m16 */
INC16M(uptr to)1306 void INC16M( uptr to )
1307 {
1308 MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 0, to, 0);
1309 }
1310
1311
1312 /* sub imm32 to r64 */
SUB64ItoR(x86IntRegType to,u32 from)1313 void SUB64ItoR( x86IntRegType to, u32 from )
1314 {
1315 RexB(1, to);
1316 if (from <= 0x7f)
1317 {
1318 write8(0x83);
1319 ModRM( 3, 5, to );
1320 write8(from);
1321 }
1322 else
1323 {
1324 if ( to == RAX ) {
1325 write8( 0x2D );
1326 }
1327 else {
1328 write8( 0x81 );
1329 ModRM( 3, 5, to );
1330 }
1331 write32( from );
1332 }
1333 }
1334
1335 /* sub r64 to r64 */
SUB64RtoR(x86IntRegType to,x86IntRegType from)1336 void SUB64RtoR( x86IntRegType to, x86IntRegType from )
1337 {
1338 RexRB(1, from, to);
1339 write8( 0x29 );
1340 ModRM( 3, from, to );
1341 }
1342
1343 /* sub m64 to r64 */
SUB64MtoR(x86IntRegType to,uptr from)1344 void SUB64MtoR( x86IntRegType to, uptr from )
1345 {
1346 MEMADDR_OP(1, VAROP1(0x2B), true, to, from, 0);
1347 }
1348
1349 /* sub imm32 to r32 */
SUB32ItoR(x86IntRegType to,u32 from)1350 void SUB32ItoR( x86IntRegType to, u32 from )
1351 {
1352 RexB(0,to);
1353 if ( to == EAX ) {
1354 write8( 0x2D );
1355 }
1356 else {
1357 write8( 0x81 );
1358 ModRM( 3, 5, to );
1359 }
1360 write32( from );
1361 }
1362
1363 /* sub imm32 to m32 */
SUB32ItoM(uptr to,u32 from)1364 void SUB32ItoM( uptr to, u32 from )
1365 {
1366 MEMADDR_OP(0, VAROP1(0x81), false, 5, to, 4);
1367 write32(from);
1368 }
1369
1370 /* sub r32 to r32 */
SUB32RtoR(x86IntRegType to,x86IntRegType from)1371 void SUB32RtoR( x86IntRegType to, x86IntRegType from )
1372 {
1373 RexRB(0, from, to);
1374 write8( 0x29 );
1375 ModRM( 3, from, to );
1376 }
1377
1378 /* sub m32 to r32 */
SUB32MtoR(x86IntRegType to,uptr from)1379 void SUB32MtoR( x86IntRegType to, uptr from )
1380 {
1381 MEMADDR_OP(0, VAROP1(0x2B), true, to, from, 0);
1382 }
1383
1384 // sub r32 to m32
SUB32RtoM(uptr to,x86IntRegType from)1385 void SUB32RtoM( uptr to, x86IntRegType from )
1386 {
1387 MEMADDR_OP(0, VAROP1(0x29), true, from, to, 0);
1388 }
1389
1390 // sub r16 to r16
SUB16RtoR(x86IntRegType to,u16 from)1391 void SUB16RtoR( x86IntRegType to, u16 from )
1392 {
1393 write8(0x66);
1394 RexRB(0,to,from);
1395 write8( 0x2b );
1396 ModRM( 3, to, from );
1397 }
1398
1399 /* sub imm16 to r16 */
SUB16ItoR(x86IntRegType to,u16 from)1400 void SUB16ItoR( x86IntRegType to, u16 from ) {
1401 write8( 0x66 );
1402 RexB(0,to);
1403 if ( to == EAX ) {
1404 write8( 0x2D );
1405 } else {
1406 write8( 0x81 );
1407 ModRM( 3, 5, to );
1408 }
1409 write16( from );
1410 }
1411
1412 /* sub imm16 to m16 */
SUB16ItoM(uptr to,u16 from)1413 void SUB16ItoM( uptr to, u16 from ) {
1414 MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 5, to, 2);
1415 write16( from );
1416 }
1417
1418 /* sub m16 to r16 */
SUB16MtoR(x86IntRegType to,uptr from)1419 void SUB16MtoR( x86IntRegType to, uptr from ) {
1420 MEMADDR_OP(0, VAROP2(0x66, 0x2B), true, to, from, 0);
1421 }
1422
1423 /* sbb r64 to r64 */
SBB64RtoR(x86IntRegType to,x86IntRegType from)1424 void SBB64RtoR( x86IntRegType to, x86IntRegType from ) {
1425 RexRB(1, from,to);
1426 write8( 0x19 );
1427 ModRM( 3, from, to );
1428 }
1429
1430 /* sbb imm32 to r32 */
SBB32ItoR(x86IntRegType to,u32 from)1431 void SBB32ItoR( x86IntRegType to, u32 from ) {
1432 RexB(0,to);
1433 if ( to == EAX ) {
1434 write8( 0x1D );
1435 } else {
1436 write8( 0x81 );
1437 ModRM( 3, 3, to );
1438 }
1439 write32( from );
1440 }
1441
1442 /* sbb imm32 to m32 */
SBB32ItoM(uptr to,u32 from)1443 void SBB32ItoM( uptr to, u32 from ) {
1444 MEMADDR_OP(0, VAROP1(0x81), false, 3, to, 4);
1445 write32( from );
1446 }
1447
1448 /* sbb r32 to r32 */
SBB32RtoR(x86IntRegType to,x86IntRegType from)1449 void SBB32RtoR( x86IntRegType to, x86IntRegType from )
1450 {
1451 RexRB(0,from,to);
1452 write8( 0x19 );
1453 ModRM( 3, from, to );
1454 }
1455
1456 /* sbb m32 to r32 */
SBB32MtoR(x86IntRegType to,uptr from)1457 void SBB32MtoR( x86IntRegType to, uptr from )
1458 {
1459 MEMADDR_OP(0, VAROP1(0x1B), true, to, from, 0);
1460 }
1461
1462 /* sbb r32 to m32 */
SBB32RtoM(uptr to,x86IntRegType from)1463 void SBB32RtoM( uptr to, x86IntRegType from )
1464 {
1465 MEMADDR_OP(0, VAROP1(0x19), true, from, to, 0);
1466 }
1467
1468 #ifdef __x86_64__
DEC32R(x86IntRegType to)1469 void DEC32R( x86IntRegType to )
1470 {
1471 write8( 0xFF );
1472 ModRM(3,1,to);
1473 }
1474 #else
1475 /* dec r32 */
DEC32R(x86IntRegType to)1476 void DEC32R( x86IntRegType to )
1477 {
1478 X86_64ASSERT();
1479 write8( 0x48 + to );
1480 }
1481 #endif
1482
1483 /* dec m32 */
DEC32M(uptr to)1484 void DEC32M( uptr to )
1485 {
1486 MEMADDR_OP(0, VAROP1(0xFF), false, 1, to, 0);
1487 }
1488
1489 /* dec r16 */
DEC16R(x86IntRegType to)1490 void DEC16R( x86IntRegType to )
1491 {
1492 X86_64ASSERT();
1493 write8( 0x66 );
1494 write8( 0x48 + to );
1495 }
1496
1497 /* dec m16 */
DEC16M(uptr to)1498 void DEC16M( uptr to )
1499 {
1500 MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 1, to, 0);
1501 }
1502
1503 /* mul eax by r32 to edx:eax */
MUL32R(x86IntRegType from)1504 void MUL32R( x86IntRegType from )
1505 {
1506 RexB(0,from);
1507 write8( 0xF7 );
1508 ModRM( 3, 4, from );
1509 }
1510
1511 /* imul eax by r32 to edx:eax */
IMUL32R(x86IntRegType from)1512 void IMUL32R( x86IntRegType from )
1513 {
1514 RexB(0,from);
1515 write8( 0xF7 );
1516 ModRM( 3, 5, from );
1517 }
1518
1519 /* mul eax by m32 to edx:eax */
MUL32M(uptr from)1520 void MUL32M( uptr from )
1521 {
1522 MEMADDR_OP(0, VAROP1(0xF7), false, 4, from, 0);
1523 }
1524
1525 /* imul eax by m32 to edx:eax */
IMUL32M(uptr from)1526 void IMUL32M( uptr from )
1527 {
1528 MEMADDR_OP(0, VAROP1(0xF7), false, 5, from, 0);
1529 }
1530
1531 /* imul r32 by r32 to r32 */
IMUL32RtoR(x86IntRegType to,x86IntRegType from)1532 void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
1533 {
1534 RexRB(0,to,from);
1535 write16( 0xAF0F );
1536 ModRM( 3, to, from );
1537 }
1538
1539 /* div eax by r32 to edx:eax */
DIV32R(x86IntRegType from)1540 void DIV32R( x86IntRegType from )
1541 {
1542 RexB(0,from);
1543 write8( 0xF7 );
1544 ModRM( 3, 6, from );
1545 }
1546
1547 /* idiv eax by r32 to edx:eax */
IDIV32R(x86IntRegType from)1548 void IDIV32R( x86IntRegType from )
1549 {
1550 RexB(0,from);
1551 write8( 0xF7 );
1552 ModRM( 3, 7, from );
1553 }
1554
1555 /* div eax by m32 to edx:eax */
DIV32M(uptr from)1556 void DIV32M( uptr from )
1557 {
1558 MEMADDR_OP(0, VAROP1(0xF7), false, 6, from, 0);
1559 }
1560
1561 /* idiv eax by m32 to edx:eax */
IDIV32M(uptr from)1562 void IDIV32M( uptr from )
1563 {
1564 MEMADDR_OP(0, VAROP1(0xF7), false, 7, from, 0);
1565 }
1566
1567 ////////////////////////////////////
1568 // shifting instructions /
1569 ////////////////////////////////////
1570
1571 /* shl imm8 to r64 */
SHL64ItoR(x86IntRegType to,u8 from)1572 void SHL64ItoR( x86IntRegType to, u8 from )
1573 {
1574 RexB(1, to);
1575 if ( from == 1 )
1576 {
1577 write8( 0xD1 );
1578 ModRM( 3, 4, to );
1579 return;
1580 }
1581 write8( 0xC1 );
1582 ModRM( 3, 4, to );
1583 write8( from );
1584 }
1585
1586 /* shl cl to r64 */
SHL64CLtoR(x86IntRegType to)1587 void SHL64CLtoR( x86IntRegType to )
1588 {
1589 RexB(1, to);
1590 write8( 0xD3 );
1591 ModRM( 3, 4, to );
1592 }
1593
1594 /* shr imm8 to r64 */
SHR64ItoR(x86IntRegType to,u8 from)1595 void SHR64ItoR( x86IntRegType to, u8 from )
1596 {
1597 RexB(1,to);
1598 if ( from == 1 ) {
1599 write8( 0xD1 );
1600 ModRM( 3, 5, to );
1601 return;
1602 }
1603 write8( 0xC1 );
1604 ModRM( 3, 5, to );
1605 write8( from );
1606 }
1607
1608 /* shr cl to r64 */
SHR64CLtoR(x86IntRegType to)1609 void SHR64CLtoR( x86IntRegType to )
1610 {
1611 RexB(1, to);
1612 write8( 0xD3 );
1613 ModRM( 3, 5, to );
1614 }
1615
1616 /* shl imm8 to r32 */
SHL32ItoR(x86IntRegType to,u8 from)1617 void SHL32ItoR( x86IntRegType to, u8 from )
1618 {
1619 RexB(0, to);
1620 if ( from == 1 )
1621 {
1622 write8( 0xD1 );
1623 write8( 0xE0 | (to & 0x7) );
1624 return;
1625 }
1626 write8( 0xC1 );
1627 ModRM( 3, 4, to );
1628 write8( from );
1629 }
1630
1631 /* shl imm8 to m32 */
SHL32ItoM(uptr to,u8 from)1632 void SHL32ItoM( uptr to, u8 from )
1633 {
1634 if ( from == 1 )
1635 {
1636 MEMADDR_OP(0, VAROP1(0xD1), false, 4, to, 0);
1637 }
1638 else
1639 {
1640 MEMADDR_OP(0, VAROP1(0xC1), false, 4, to, 1);
1641 write8( from );
1642 }
1643 }
1644
1645 /* shl cl to r32 */
SHL32CLtoR(x86IntRegType to)1646 void SHL32CLtoR( x86IntRegType to )
1647 {
1648 RexB(0,to);
1649 write8( 0xD3 );
1650 ModRM( 3, 4, to );
1651 }
1652
1653 // shl imm8 to r16
SHL16ItoR(x86IntRegType to,u8 from)1654 void SHL16ItoR( x86IntRegType to, u8 from )
1655 {
1656 write8(0x66);
1657 RexB(0,to);
1658 if ( from == 1 )
1659 {
1660 write8( 0xD1 );
1661 write8( 0xE0 | (to & 0x7) );
1662 return;
1663 }
1664 write8( 0xC1 );
1665 ModRM( 3, 4, to );
1666 write8( from );
1667 }
1668
1669 // shl imm8 to r8
SHL8ItoR(x86IntRegType to,u8 from)1670 void SHL8ItoR( x86IntRegType to, u8 from )
1671 {
1672 RexB(0,to);
1673 if ( from == 1 )
1674 {
1675 write8( 0xD0 );
1676 write8( 0xE0 | (to & 0x7) );
1677 return;
1678 }
1679 write8( 0xC0 );
1680 ModRM( 3, 4, to );
1681 write8( from );
1682 }
1683
1684 /* shr imm8 to r32 */
SHR32ItoR(x86IntRegType to,u8 from)1685 void SHR32ItoR( x86IntRegType to, u8 from ) {
1686 RexB(0,to);
1687 if ( from == 1 )
1688 {
1689 write8( 0xD1 );
1690 write8( 0xE8 | (to & 0x7) );
1691 }
1692 else
1693 {
1694 write8( 0xC1 );
1695 ModRM( 3, 5, to );
1696 write8( from );
1697 }
1698 }
1699
1700 /* shr imm8 to m32 */
SHR32ItoM(uptr to,u8 from)1701 void SHR32ItoM( uptr to, u8 from )
1702 {
1703 if ( from == 1 )
1704 {
1705 MEMADDR_OP(0, VAROP1(0xD1), false, 5, to, 0);
1706 }
1707 else
1708 {
1709 MEMADDR_OP(0, VAROP1(0xC1), false, 5, to, 1);
1710 write8( from );
1711 }
1712 }
1713
1714 /* shr cl to r32 */
SHR32CLtoR(x86IntRegType to)1715 void SHR32CLtoR( x86IntRegType to )
1716 {
1717 RexB(0,to);
1718 write8( 0xD3 );
1719 ModRM( 3, 5, to );
1720 }
1721
1722 // shr imm8 to r8
SHR8ItoR(x86IntRegType to,u8 from)1723 void SHR8ItoR( x86IntRegType to, u8 from )
1724 {
1725 RexB(0,to);
1726 if ( from == 1 )
1727 {
1728 write8( 0xD0 );
1729 write8( 0xE8 | (to & 0x7) );
1730 }
1731 else
1732 {
1733 write8( 0xC0 );
1734 ModRM( 3, 5, to );
1735 write8( from );
1736 }
1737 }
1738
1739 /* sar imm8 to r64 */
SAR64ItoR(x86IntRegType to,u8 from)1740 void SAR64ItoR( x86IntRegType to, u8 from )
1741 {
1742 RexB(1,to);
1743 if ( from == 1 )
1744 {
1745 write8( 0xD1 );
1746 ModRM( 3, 7, to );
1747 return;
1748 }
1749 write8( 0xC1 );
1750 ModRM( 3, 7, to );
1751 write8( from );
1752 }
1753
1754 /* sar cl to r64 */
SAR64CLtoR(x86IntRegType to)1755 void SAR64CLtoR( x86IntRegType to )
1756 {
1757 RexB(1, to);
1758 write8( 0xD3 );
1759 ModRM( 3, 7, to );
1760 }
1761
1762 /* sar imm8 to r32 */
SAR32ItoR(x86IntRegType to,u8 from)1763 void SAR32ItoR( x86IntRegType to, u8 from )
1764 {
1765 RexB(0,to);
1766 if ( from == 1 )
1767 {
1768 write8( 0xD1 );
1769 ModRM( 3, 7, to );
1770 return;
1771 }
1772 write8( 0xC1 );
1773 ModRM( 3, 7, to );
1774 write8( from );
1775 }
1776
1777 /* sar imm8 to m32 */
SAR32ItoM(uptr to,u8 from)1778 void SAR32ItoM( uptr to, u8 from )
1779 {
1780 if (from == 1)
1781 {
1782 MEMADDR_OP(0, VAROP1(0xD1), false, 7, to, 0);
1783 }
1784 else
1785 {
1786 MEMADDR_OP(0, VAROP1(0xC1), false, 7, to, 1);
1787 write8( from );
1788 }
1789 }
1790
1791 /* sar cl to r32 */
SAR32CLtoR(x86IntRegType to)1792 void SAR32CLtoR( x86IntRegType to )
1793 {
1794 RexB(0,to);
1795 write8( 0xD3 );
1796 ModRM( 3, 7, to );
1797 }
1798
1799 // sar imm8 to r16
SAR16ItoR(x86IntRegType to,u8 from)1800 void SAR16ItoR( x86IntRegType to, u8 from )
1801 {
1802 write8(0x66);
1803 RexB(0,to);
1804 if ( from == 1 )
1805 {
1806 write8( 0xD1 );
1807 ModRM( 3, 7, to );
1808 return;
1809 }
1810 write8( 0xC1 );
1811 ModRM( 3, 7, to );
1812 write8( from );
1813 }
1814
ROR32ItoR(x86IntRegType to,u8 from)1815 void ROR32ItoR( x86IntRegType to,u8 from )
1816 {
1817 RexB(0,to);
1818 if ( from == 1 ) {
1819 write8( 0xd1 );
1820 write8( 0xc8 | to );
1821 }
1822 else
1823 {
1824 write8( 0xc1 );
1825 write8( 0xc8 | to );
1826 write8( from );
1827 }
1828 }
1829
RCR32ItoR(x86IntRegType to,u8 from)1830 void RCR32ItoR( x86IntRegType to, u8 from )
1831 {
1832 RexB(0,to);
1833 if ( from == 1 ) {
1834 write8( 0xd1 );
1835 write8( 0xd8 | to );
1836 }
1837 else
1838 {
1839 write8( 0xc1 );
1840 write8( 0xd8 | to );
1841 write8( from );
1842 }
1843 }
1844
1845 // shld imm8 to r32
SHLD32ItoR(x86IntRegType to,x86IntRegType from,u8 shift)1846 void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
1847 {
1848 RexRB(0,from,to);
1849 write8( 0x0F );
1850 write8( 0xA4 );
1851 ModRM( 3, from, to );
1852 write8( shift );
1853 }
1854
1855 // shrd imm8 to r32
SHRD32ItoR(x86IntRegType to,x86IntRegType from,u8 shift)1856 void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
1857 {
1858 RexRB(0,from,to);
1859 write8( 0x0F );
1860 write8( 0xAC );
1861 ModRM( 3, from, to );
1862 write8( shift );
1863 }
1864
1865 ////////////////////////////////////
1866 // logical instructions /
1867 ////////////////////////////////////
1868
1869 /* or imm32 to r32 */
OR64ItoR(x86IntRegType to,u32 from)1870 void OR64ItoR( x86IntRegType to, u32 from )
1871 {
1872 RexB(1, to);
1873 if ( to == EAX ) {
1874 write8( 0x0D );
1875 } else {
1876 write8( 0x81 );
1877 ModRM( 3, 1, to );
1878 }
1879 write32( from );
1880 }
1881
1882 /* or m64 to r64 */
OR64MtoR(x86IntRegType to,uptr from)1883 void OR64MtoR( x86IntRegType to, uptr from )
1884 {
1885 MEMADDR_OP(1, VAROP1(0x0B), true, to, from, 0);
1886 }
1887
1888 /* or r64 to r64 */
OR64RtoR(x86IntRegType to,x86IntRegType from)1889 void OR64RtoR( x86IntRegType to, x86IntRegType from )
1890 {
1891 RexRB(1, from, to);
1892 write8( 0x09 );
1893 ModRM( 3, from, to );
1894 }
1895
1896 // or r32 to m64
OR64RtoM(uptr to,x86IntRegType from)1897 void OR64RtoM(uptr to, x86IntRegType from )
1898 {
1899 MEMADDR_OP(1, VAROP1(0x09), true, from, to, 0);
1900 }
1901
1902 /* or imm32 to r32 */
OR32ItoR(x86IntRegType to,u32 from)1903 void OR32ItoR( x86IntRegType to, u32 from )
1904 {
1905 RexB(0,to);
1906 if ( to == EAX ) {
1907 write8( 0x0D );
1908 }
1909 else {
1910 write8( 0x81 );
1911 ModRM( 3, 1, to );
1912 }
1913 write32( from );
1914 }
1915
1916 /* or imm32 to m32 */
OR32ItoM(uptr to,u32 from)1917 void OR32ItoM(uptr to, u32 from )
1918 {
1919 MEMADDR_OP(0, VAROP1(0x81), false, 1, to, 4);
1920 write32(from);
1921 }
1922
1923 /* or r32 to r32 */
OR32RtoR(x86IntRegType to,x86IntRegType from)1924 void OR32RtoR( x86IntRegType to, x86IntRegType from )
1925 {
1926 RexRB(0,from,to);
1927 write8( 0x09 );
1928 ModRM( 3, from, to );
1929 }
1930
1931 /* or r32 to m32 */
OR32RtoM(uptr to,x86IntRegType from)1932 void OR32RtoM(uptr to, x86IntRegType from )
1933 {
1934 MEMADDR_OP(0, VAROP1(0x09), true, from, to, 0);
1935 }
1936
1937 /* or m32 to r32 */
OR32MtoR(x86IntRegType to,uptr from)1938 void OR32MtoR( x86IntRegType to, uptr from )
1939 {
1940 MEMADDR_OP(0, VAROP1(0x0B), true, to, from, 0);
1941 }
1942
1943 // or r16 to r16
OR16RtoR(x86IntRegType to,x86IntRegType from)1944 void OR16RtoR( x86IntRegType to, x86IntRegType from )
1945 {
1946 write8(0x66);
1947 RexRB(0,from,to);
1948 write8( 0x09 );
1949 ModRM( 3, from, to );
1950 }
1951
1952 // or imm16 to r16
OR16ItoR(x86IntRegType to,u16 from)1953 void OR16ItoR( x86IntRegType to, u16 from )
1954 {
1955 write8(0x66);
1956 RexB(0,to);
1957 if ( to == EAX ) {
1958 write8( 0x0D );
1959 }
1960 else {
1961 write8( 0x81 );
1962 ModRM( 3, 1, to );
1963 }
1964 write16( from );
1965 }
1966
1967 // or imm16 to m316
OR16ItoM(uptr to,u16 from)1968 void OR16ItoM( uptr to, u16 from )
1969 {
1970 MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 1, to, 2);
1971 write16( from );
1972 }
1973
1974 /* or m16 to r16 */
OR16MtoR(x86IntRegType to,uptr from)1975 void OR16MtoR( x86IntRegType to, uptr from )
1976 {
1977 MEMADDR_OP(0, VAROP2(0x66, 0x0B), true, to, from, 0);
1978 }
1979
1980 // or r16 to m16
OR16RtoM(uptr to,x86IntRegType from)1981 void OR16RtoM( uptr to, x86IntRegType from )
1982 {
1983 MEMADDR_OP(0, VAROP2(0x66, 0x09), true, from, to, 0);
1984 }
1985
1986 // or r8 to r8
OR8RtoR(x86IntRegType to,x86IntRegType from)1987 void OR8RtoR( x86IntRegType to, x86IntRegType from )
1988 {
1989 RexRB(0,from,to);
1990 write8( 0x08 );
1991 ModRM( 3, from, to );
1992 }
1993
1994 // or r8 to m8
OR8RtoM(uptr to,x86IntRegType from)1995 void OR8RtoM( uptr to, x86IntRegType from )
1996 {
1997 MEMADDR_OP(0, VAROP1(0x08), true, from, to, 0);
1998 }
1999
2000 // or imm8 to m8
OR8ItoM(uptr to,u8 from)2001 void OR8ItoM( uptr to, u8 from )
2002 {
2003 MEMADDR_OP(0, VAROP1(0x80), false, 1, to, 1);
2004 write8( from );
2005 }
2006
2007 // or m8 to r8
OR8MtoR(x86IntRegType to,uptr from)2008 void OR8MtoR( x86IntRegType to, uptr from )
2009 {
2010 MEMADDR_OP(0, VAROP1(0x0A), true, to, from, 0);
2011 }
2012
2013 /* xor imm32 to r64 */
XOR64ItoR(x86IntRegType to,u32 from)2014 void XOR64ItoR( x86IntRegType to, u32 from )
2015 {
2016 RexB(1,to);
2017 if ( to == EAX ) {
2018 write8( 0x35 );
2019 } else {
2020 write8( 0x81 );
2021 ModRM( 3, 6, to );
2022 }
2023 write32( from );
2024 }
2025
2026 /* xor r64 to r64 */
XOR64RtoR(x86IntRegType to,x86IntRegType from)2027 void XOR64RtoR( x86IntRegType to, x86IntRegType from )
2028 {
2029 RexRB(1, from, to);
2030 write8( 0x31 );
2031 ModRM( 3, from, to );
2032 }
2033
2034 /* xor m64 to r64 */
XOR64MtoR(x86IntRegType to,uptr from)2035 void XOR64MtoR( x86IntRegType to, uptr from )
2036 {
2037 MEMADDR_OP(1, VAROP1(0x33), true, to, from, 0);
2038 }
2039
2040 /* xor r64 to m64 */
XOR64RtoM(uptr to,x86IntRegType from)2041 void XOR64RtoM( uptr to, x86IntRegType from )
2042 {
2043 MEMADDR_OP(1, VAROP1(0x31), true, from, to, 0);
2044 }
2045
2046 /* xor imm32 to r32 */
XOR32ItoR(x86IntRegType to,u32 from)2047 void XOR32ItoR( x86IntRegType to, u32 from )
2048 {
2049 RexB(0,to);
2050 if ( to == EAX ) {
2051 write8( 0x35 );
2052 }
2053 else {
2054 write8( 0x81 );
2055 ModRM( 3, 6, to );
2056 }
2057 write32( from );
2058 }
2059
2060 /* xor imm32 to m32 */
XOR32ItoM(uptr to,u32 from)2061 void XOR32ItoM( uptr to, u32 from )
2062 {
2063 MEMADDR_OP(0, VAROP1(0x81), false, 6, to, 4);
2064 write32( from );
2065 }
2066
2067 /* xor r32 to r32 */
XOR32RtoR(x86IntRegType to,x86IntRegType from)2068 void XOR32RtoR( x86IntRegType to, x86IntRegType from )
2069 {
2070 RexRB(0,from,to);
2071 write8( 0x31 );
2072 ModRM( 3, from, to );
2073 }
2074
2075 /* xor r16 to r16 */
XOR16RtoR(x86IntRegType to,x86IntRegType from)2076 void XOR16RtoR( x86IntRegType to, x86IntRegType from )
2077 {
2078 write8( 0x66 );
2079 RexRB(0,from,to);
2080 write8( 0x31 );
2081 ModRM( 3, from, to );
2082 }
2083
2084 /* xor r32 to m32 */
XOR32RtoM(uptr to,x86IntRegType from)2085 void XOR32RtoM( uptr to, x86IntRegType from )
2086 {
2087 MEMADDR_OP(0, VAROP1(0x31), true, from, to, 0);
2088 }
2089
2090 /* xor m32 to r32 */
XOR32MtoR(x86IntRegType to,uptr from)2091 void XOR32MtoR( x86IntRegType to, uptr from )
2092 {
2093 MEMADDR_OP(0, VAROP1(0x33), true, to, from, 0);
2094 }
2095
2096 // xor imm16 to r16
XOR16ItoR(x86IntRegType to,u16 from)2097 void XOR16ItoR( x86IntRegType to, u16 from )
2098 {
2099 write8(0x66);
2100 RexB(0,to);
2101 if ( to == EAX ) {
2102 write8( 0x35 );
2103 }
2104 else {
2105 write8( 0x81 );
2106 ModRM( 3, 6, to );
2107 }
2108 write16( from );
2109 }
2110
2111 // xor r16 to m16
XOR16RtoM(uptr to,x86IntRegType from)2112 void XOR16RtoM( uptr to, x86IntRegType from )
2113 {
2114 MEMADDR_OP(0, VAROP2(0x66, 0x31), true, from, to, 0);
2115 }
2116
2117 /* and imm32 to r64 */
AND64I32toR(x86IntRegType to,u32 from)2118 void AND64I32toR( x86IntRegType to, u32 from )
2119 {
2120 RexB(1, to);
2121 if ( to == EAX ) {
2122 write8( 0x25 );
2123 } else {
2124 write8( 0x81 );
2125 ModRM( 3, 0x4, to );
2126 }
2127 write32( from );
2128 }
2129
2130 /* and m64 to r64 */
AND64MtoR(x86IntRegType to,uptr from)2131 void AND64MtoR( x86IntRegType to, uptr from )
2132 {
2133 MEMADDR_OP(1, VAROP1(0x23), true, to, from, 0);
2134 }
2135
2136 /* and r64 to m64 */
AND64RtoM(uptr to,x86IntRegType from)2137 void AND64RtoM( uptr to, x86IntRegType from )
2138 {
2139 MEMADDR_OP(1, VAROP1(0x21), true, from, to, 0);
2140 }
2141
2142 /* and r64 to r64 */
AND64RtoR(x86IntRegType to,x86IntRegType from)2143 void AND64RtoR( x86IntRegType to, x86IntRegType from )
2144 {
2145 RexRB(1, from, to);
2146 write8( 0x21 );
2147 ModRM( 3, from, to );
2148 }
2149
2150 /* and imm32 to m64 */
AND64I32toM(uptr to,u32 from)2151 void AND64I32toM( uptr to, u32 from )
2152 {
2153 MEMADDR_OP(1, VAROP1(0x81), false, 4, to, 4);
2154 write32( from );
2155 }
2156
2157 /* and imm32 to r32 */
AND32ItoR(x86IntRegType to,u32 from)2158 void AND32ItoR( x86IntRegType to, u32 from )
2159 {
2160 RexB(0,to);
2161 if ( to == EAX ) {
2162 write8( 0x25 );
2163 } else {
2164 write8( 0x81 );
2165 ModRM( 3, 0x4, to );
2166 }
2167 write32( from );
2168 }
2169
2170 /* and sign ext imm8 to r32 */
AND32I8toR(x86IntRegType to,u8 from)2171 void AND32I8toR( x86IntRegType to, u8 from )
2172 {
2173 RexB(0,to);
2174 write8( 0x83 );
2175 ModRM( 3, 0x4, to );
2176 write8( from );
2177 }
2178
2179 /* and imm32 to m32 */
AND32ItoM(uptr to,u32 from)2180 void AND32ItoM( uptr to, u32 from )
2181 {
2182 MEMADDR_OP(0, VAROP1(0x81), false, 4, to, 4);
2183 write32(from);
2184 }
2185
2186 /* and sign ext imm8 to m32 */
AND32I8toM(uptr to,u8 from)2187 void AND32I8toM( uptr to, u8 from )
2188 {
2189 MEMADDR_OP(0, VAROP1(0x83), false, 4, to, 1);
2190 write8( from );
2191 }
2192
2193 /* and r32 to r32 */
AND32RtoR(x86IntRegType to,x86IntRegType from)2194 void AND32RtoR( x86IntRegType to, x86IntRegType from )
2195 {
2196 RexRB(0,from,to);
2197 write8( 0x21 );
2198 ModRM( 3, from, to );
2199 }
2200
2201 /* and r32 to m32 */
AND32RtoM(uptr to,x86IntRegType from)2202 void AND32RtoM( uptr to, x86IntRegType from )
2203 {
2204 MEMADDR_OP(0, VAROP1(0x21), true, from, to, 0);
2205 }
2206
2207 /* and m32 to r32 */
AND32MtoR(x86IntRegType to,uptr from)2208 void AND32MtoR( x86IntRegType to, uptr from )
2209 {
2210 MEMADDR_OP(0, VAROP1(0x23), true, to, from, 0);
2211 }
2212
2213 // and r16 to r16
AND16RtoR(x86IntRegType to,x86IntRegType from)2214 void AND16RtoR( x86IntRegType to, x86IntRegType from )
2215 {
2216 write8(0x66);
2217 RexRB(0,to,from);
2218 write8( 0x23 );
2219 ModRM( 3, to, from );
2220 }
2221
2222 /* and imm16 to r16 */
AND16ItoR(x86IntRegType to,u16 from)2223 void AND16ItoR( x86IntRegType to, u16 from )
2224 {
2225 write8(0x66);
2226 RexB(0,to);
2227 if ( to == EAX ) {
2228 write8( 0x25 );
2229 } else {
2230 write8( 0x81 );
2231 ModRM( 3, 0x4, to );
2232 }
2233 write16( from );
2234 }
2235
2236 /* and imm16 to m16 */
AND16ItoM(uptr to,u16 from)2237 void AND16ItoM( uptr to, u16 from )
2238 {
2239 MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 4, to, 2);
2240 write16( from );
2241 }
2242
2243 /* and r16 to m16 */
AND16RtoM(uptr to,x86IntRegType from)2244 void AND16RtoM( uptr to, x86IntRegType from )
2245 {
2246 MEMADDR_OP(0, VAROP2(0x66, 0x21), true, from, to, 0);
2247 }
2248
2249 /* and m16 to r16 */
AND16MtoR(x86IntRegType to,uptr from)2250 void AND16MtoR( x86IntRegType to, uptr from )
2251 {
2252 MEMADDR_OP(0, VAROP2(0x66, 0x23), true, to, from, 0);
2253 }
2254
2255 /* and imm8 to r8 */
AND8ItoR(x86IntRegType to,u8 from)2256 void AND8ItoR( x86IntRegType to, u8 from )
2257 {
2258 RexB(0,to);
2259 if ( to == EAX ) {
2260 write8( 0x24 );
2261 } else {
2262 write8( 0x80 );
2263 ModRM( 3, 0x4, to );
2264 }
2265 write8( from );
2266 }
2267
2268 /* and imm8 to m8 */
AND8ItoM(uptr to,u8 from)2269 void AND8ItoM( uptr to, u8 from )
2270 {
2271 MEMADDR_OP(0, VAROP1(0x80), false, 4, to, 1);
2272 write8( from );
2273 }
2274
2275 // and r8 to r8
AND8RtoR(x86IntRegType to,x86IntRegType from)2276 void AND8RtoR( x86IntRegType to, x86IntRegType from )
2277 {
2278 RexRB(0,to,from);
2279 write8( 0x22 );
2280 ModRM( 3, to, from );
2281 }
2282
2283 /* and r8 to m8 */
AND8RtoM(uptr to,x86IntRegType from)2284 void AND8RtoM( uptr to, x86IntRegType from )
2285 {
2286 MEMADDR_OP(0, VAROP1(0x20), true, from, to, 0);
2287 }
2288
2289 /* and m8 to r8 */
AND8MtoR(x86IntRegType to,uptr from)2290 void AND8MtoR( x86IntRegType to, uptr from )
2291 {
2292 MEMADDR_OP(0, VAROP1(0x22), true, to, from, 0);
2293 }
2294
2295 /* not r64 */
NOT64R(x86IntRegType from)2296 void NOT64R( x86IntRegType from )
2297 {
2298 RexB(1, from);
2299 write8( 0xF7 );
2300 ModRM( 3, 2, from );
2301 }
2302
2303 /* not r32 */
NOT32R(x86IntRegType from)2304 void NOT32R( x86IntRegType from )
2305 {
2306 RexB(0,from);
2307 write8( 0xF7 );
2308 ModRM( 3, 2, from );
2309 }
2310
2311 // not m32
NOT32M(uptr from)2312 void NOT32M( uptr from )
2313 {
2314 MEMADDR_OP(0, VAROP1(0xF7), false, 2, from, 0);
2315 }
2316
2317 /* neg r64 */
NEG64R(x86IntRegType from)2318 void NEG64R( x86IntRegType from )
2319 {
2320 RexB(1, from);
2321 write8( 0xF7 );
2322 ModRM( 3, 3, from );
2323 }
2324
2325 /* neg r32 */
NEG32R(x86IntRegType from)2326 void NEG32R( x86IntRegType from )
2327 {
2328 RexB(0,from);
2329 write8( 0xF7 );
2330 ModRM( 3, 3, from );
2331 }
2332
NEG32M(uptr from)2333 void NEG32M( uptr from )
2334 {
2335 MEMADDR_OP(0, VAROP1(0xF7), false, 3, from, 0);
2336 }
2337
2338 /* neg r16 */
NEG16R(x86IntRegType from)2339 void NEG16R( x86IntRegType from )
2340 {
2341 write8( 0x66 );
2342 RexB(0,from);
2343 write8( 0xF7 );
2344 ModRM( 3, 3, from );
2345 }
2346
2347 ////////////////////////////////////
2348 // jump instructions /
2349 ////////////////////////////////////
2350
JMP(uptr to)2351 u8* JMP( uptr to ) {
2352 uptr jump = ( x86Ptr - (s8*)to ) - 1;
2353
2354 if ( jump > 0x7f ) {
2355 assert( to <= 0xffffffff );
2356 return (u8*)JMP32( to );
2357 } else {
2358 return (u8*)JMP8( to );
2359 }
2360 }
2361
2362 /* jmp rel8 */
JMP8(u8 to)2363 u8* JMP8( u8 to )
2364 {
2365 write8( 0xEB );
2366 write8( to );
2367 return x86Ptr - 1;
2368 }
2369
2370 /* jmp rel32 */
JMP32(uptr to)2371 u32* JMP32( uptr to )
2372 {
2373 assert(SPTR32((sptr)to));
2374 write8( 0xE9 );
2375 write32( (sptr)to );
2376 return (u32*)(x86Ptr - 4 );
2377 }
2378
2379 /* jmp r32/r64 */
JMPR(x86IntRegType to)2380 void JMPR( x86IntRegType to )
2381 {
2382 RexB(0, to);
2383 write8( 0xFF );
2384 ModRM( 3, 4, to );
2385 }
2386
2387 // jmp m32
JMP32M(uptr to)2388 void JMP32M( uptr to )
2389 {
2390 /* FIXME */
2391 MEMADDR_OP(0, VAROP1(0xFF), false, 4, to, 0);
2392 }
2393
2394 /* jp rel8 */
JP8(u8 to)2395 u8* JP8( u8 to ) {
2396 return J8Rel( 0x7A, to );
2397 }
2398
2399 /* jnp rel8 */
JNP8(u8 to)2400 u8* JNP8( u8 to ) {
2401 return J8Rel( 0x7B, to );
2402 }
2403
2404 /* je rel8 */
JE8(u8 to)2405 u8* JE8( u8 to ) {
2406 return J8Rel( 0x74, to );
2407 }
2408
2409 /* jz rel8 */
JZ8(u8 to)2410 u8* JZ8( u8 to )
2411 {
2412 return J8Rel( 0x74, to );
2413 }
2414
2415 /* js rel8 */
JS8(u8 to)2416 u8* JS8( u8 to )
2417 {
2418 return J8Rel( 0x78, to );
2419 }
2420
2421 /* jns rel8 */
JNS8(u8 to)2422 u8* JNS8( u8 to )
2423 {
2424 return J8Rel( 0x79, to );
2425 }
2426
2427 /* jg rel8 */
JG8(u8 to)2428 u8* JG8( u8 to )
2429 {
2430 return J8Rel( 0x7F, to );
2431 }
2432
2433 /* jge rel8 */
JGE8(u8 to)2434 u8* JGE8( u8 to )
2435 {
2436 return J8Rel( 0x7D, to );
2437 }
2438
2439 /* jl rel8 */
JL8(u8 to)2440 u8* JL8( u8 to )
2441 {
2442 return J8Rel( 0x7C, to );
2443 }
2444
2445 /* ja rel8 */
JA8(u8 to)2446 u8* JA8( u8 to )
2447 {
2448 return J8Rel( 0x77, to );
2449 }
2450
JAE8(u8 to)2451 u8* JAE8( u8 to )
2452 {
2453 return J8Rel( 0x73, to );
2454 }
2455
2456 /* jb rel8 */
JB8(u8 to)2457 u8* JB8( u8 to )
2458 {
2459 return J8Rel( 0x72, to );
2460 }
2461
2462 /* jbe rel8 */
JBE8(u8 to)2463 u8* JBE8( u8 to )
2464 {
2465 return J8Rel( 0x76, to );
2466 }
2467
2468 /* jle rel8 */
JLE8(u8 to)2469 u8* JLE8( u8 to )
2470 {
2471 return J8Rel( 0x7E, to );
2472 }
2473
2474 /* jne rel8 */
JNE8(u8 to)2475 u8* JNE8( u8 to )
2476 {
2477 return J8Rel( 0x75, to );
2478 }
2479
2480 /* jnz rel8 */
JNZ8(u8 to)2481 u8* JNZ8( u8 to )
2482 {
2483 return J8Rel( 0x75, to );
2484 }
2485
2486 /* jng rel8 */
JNG8(u8 to)2487 u8* JNG8( u8 to )
2488 {
2489 return J8Rel( 0x7E, to );
2490 }
2491
2492 /* jnge rel8 */
JNGE8(u8 to)2493 u8* JNGE8( u8 to )
2494 {
2495 return J8Rel( 0x7C, to );
2496 }
2497
2498 /* jnl rel8 */
JNL8(u8 to)2499 u8* JNL8( u8 to )
2500 {
2501 return J8Rel( 0x7D, to );
2502 }
2503
2504 /* jnle rel8 */
JNLE8(u8 to)2505 u8* JNLE8( u8 to )
2506 {
2507 return J8Rel( 0x7F, to );
2508 }
2509
2510 /* jo rel8 */
JO8(u8 to)2511 u8* JO8( u8 to )
2512 {
2513 return J8Rel( 0x70, to );
2514 }
2515
2516 /* jno rel8 */
JNO8(u8 to)2517 u8* JNO8( u8 to )
2518 {
2519 return J8Rel( 0x71, to );
2520 }
2521
2522 // jb rel8
JB16(u16 to)2523 u16* JB16( u16 to )
2524 {
2525 return J16Rel( 0x82, to );
2526 }
2527
2528 // jb rel32
JB32(u32 to)2529 u32* JB32( u32 to )
2530 {
2531 return J32Rel( 0x82, to );
2532 }
2533
2534 /* je rel32 */
JE32(u32 to)2535 u32* JE32( u32 to )
2536 {
2537 return J32Rel( 0x84, to );
2538 }
2539
2540 /* jz rel32 */
JZ32(u32 to)2541 u32* JZ32( u32 to )
2542 {
2543 return J32Rel( 0x84, to );
2544 }
2545
2546 /* jg rel32 */
JG32(u32 to)2547 u32* JG32( u32 to )
2548 {
2549 return J32Rel( 0x8F, to );
2550 }
2551
2552 /* jge rel32 */
JGE32(u32 to)2553 u32* JGE32( u32 to )
2554 {
2555 return J32Rel( 0x8D, to );
2556 }
2557
2558 /* jl rel32 */
JL32(u32 to)2559 u32* JL32( u32 to )
2560 {
2561 return J32Rel( 0x8C, to );
2562 }
2563
2564 /* jle rel32 */
JLE32(u32 to)2565 u32* JLE32( u32 to )
2566 {
2567 return J32Rel( 0x8E, to );
2568 }
2569
2570 /* jae rel32 */
JAE32(u32 to)2571 u32* JAE32( u32 to )
2572 {
2573 return J32Rel( 0x83, to );
2574 }
2575
2576 /* jne rel32 */
JNE32(u32 to)2577 u32* JNE32( u32 to )
2578 {
2579 return J32Rel( 0x85, to );
2580 }
2581
2582 /* jnz rel32 */
JNZ32(u32 to)2583 u32* JNZ32( u32 to )
2584 {
2585 return J32Rel( 0x85, to );
2586 }
2587
2588 /* jng rel32 */
JNG32(u32 to)2589 u32* JNG32( u32 to )
2590 {
2591 return J32Rel( 0x8E, to );
2592 }
2593
2594 /* jnge rel32 */
JNGE32(u32 to)2595 u32* JNGE32( u32 to )
2596 {
2597 return J32Rel( 0x8C, to );
2598 }
2599
2600 /* jnl rel32 */
JNL32(u32 to)2601 u32* JNL32( u32 to )
2602 {
2603 return J32Rel( 0x8D, to );
2604 }
2605
2606 /* jnle rel32 */
JNLE32(u32 to)2607 u32* JNLE32( u32 to )
2608 {
2609 return J32Rel( 0x8F, to );
2610 }
2611
2612 /* jo rel32 */
JO32(u32 to)2613 u32* JO32( u32 to )
2614 {
2615 return J32Rel( 0x80, to );
2616 }
2617
2618 /* jno rel32 */
JNO32(u32 to)2619 u32* JNO32( u32 to )
2620 {
2621 return J32Rel( 0x81, to );
2622 }
2623
2624 // js rel32
JS32(u32 to)2625 u32* JS32( u32 to )
2626 {
2627 return J32Rel( 0x88, to );
2628 }
2629
2630
2631 /* call func */
CALLFunc(uptr func)2632 void CALLFunc( uptr func )
2633 {
2634 sptr p = MEMADDR_(func, 5);
2635 if (SPTR32(p))
2636 {
2637 CALL32(p);
2638 }
2639 else
2640 {
2641 MOV64ItoR(X86_TEMP, func);
2642 CALL64R(X86_TEMP);
2643 }
2644 }
2645
2646 /* call rel32 */
CALL32(s32 to)2647 void CALL32( s32 to )
2648 {
2649 write8( 0xE8 );
2650 write32( to );
2651 }
2652
2653 /* call r32 */
CALL32R(x86IntRegType to)2654 void CALL32R( x86IntRegType to )
2655 {
2656 RexB(0, to);
2657 write8( 0xFF );
2658 ModRM( 3, 2, to );
2659 }
2660
2661 /* call r64 */
CALL64R(x86IntRegType to)2662 void CALL64R( x86IntRegType to )
2663 {
2664 RexB(0, to);
2665 write8( 0xFF );
2666 ModRM( 3, 2, to );
2667 }
2668
2669 ////////////////////////////////////
2670 // misc instructions /
2671 ////////////////////////////////////
2672
2673 /* cmp imm32 to r64 */
CMP64I32toR(x86IntRegType to,u32 from)2674 void CMP64I32toR( x86IntRegType to, u32 from )
2675 {
2676 RexB(1, to);
2677 if ( to == EAX ) {
2678 write8( 0x3D );
2679 }
2680 else {
2681 write8( 0x81 );
2682 ModRM( 3, 7, to );
2683 }
2684 write32( from );
2685 }
2686
2687 /* cmp m64 to r64 */
CMP64MtoR(x86IntRegType to,uptr from)2688 void CMP64MtoR( x86IntRegType to, uptr from )
2689 {
2690 MEMADDR_OP(1, VAROP1(0x3B), true, 2, from, 0);
2691 }
2692
2693 // cmp r64 to r64
CMP64RtoR(x86IntRegType to,x86IntRegType from)2694 void CMP64RtoR( x86IntRegType to, x86IntRegType from )
2695 {
2696 RexRB(1,from,to);
2697 write8( 0x39 );
2698 ModRM( 3, from, to );
2699 }
2700
2701 /* cmp imm32 to r32 */
CMP32ItoR(x86IntRegType to,u32 from)2702 void CMP32ItoR( x86IntRegType to, u32 from )
2703 {
2704 RexB(0,to);
2705 if ( to == EAX ) {
2706 write8( 0x3D );
2707 }
2708 else {
2709 write8( 0x81 );
2710 ModRM( 3, 7, to );
2711 }
2712 write32( from );
2713 }
2714
2715 /* cmp imm32 to m32 */
CMP32ItoM(uptr to,u32 from)2716 void CMP32ItoM( uptr to, u32 from )
2717 {
2718 MEMADDR_OP(0, VAROP1(0x81), false, 7, to, 4);
2719 write32(from);
2720 }
2721
2722 /* cmp r32 to r32 */
CMP32RtoR(x86IntRegType to,x86IntRegType from)2723 void CMP32RtoR( x86IntRegType to, x86IntRegType from )
2724 {
2725 RexRB(0,from,to);
2726 write8( 0x39 );
2727 ModRM( 3, from, to );
2728 }
2729
2730 /* cmp m32 to r32 */
CMP32MtoR(x86IntRegType to,uptr from)2731 void CMP32MtoR( x86IntRegType to, uptr from )
2732 {
2733 MEMADDR_OP(0, VAROP1(0x3B), true, to, from, 0);
2734 }
2735
2736 // cmp imm8 to [r32]
CMP32I8toRm(x86IntRegType to,u8 from)2737 void CMP32I8toRm( x86IntRegType to, u8 from)
2738 {
2739 RexB(0,to);
2740 write8( 0x83 );
2741 ModRM( 0, 7, to );
2742 write8(from);
2743 }
2744
2745 // cmp imm32 to [r32+off]
CMP32I8toRmOffset8(x86IntRegType to,u8 from,u8 off)2746 void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off)
2747 {
2748 RexB(0,to);
2749 write8( 0x83 );
2750 ModRM( 1, 7, to );
2751 write8(off);
2752 write8(from);
2753 }
2754
2755 // cmp imm8 to [r32]
CMP32I8toM(uptr to,u8 from)2756 void CMP32I8toM( uptr to, u8 from)
2757 {
2758 MEMADDR_OP(0, VAROP1(0x83), false, 7, to, 1);
2759 write8( from );
2760 }
2761
2762 /* cmp imm16 to r16 */
CMP16ItoR(x86IntRegType to,u16 from)2763 void CMP16ItoR( x86IntRegType to, u16 from )
2764 {
2765 write8( 0x66 );
2766 RexB(0,to);
2767 if ( to == EAX )
2768 {
2769 write8( 0x3D );
2770 }
2771 else
2772 {
2773 write8( 0x81 );
2774 ModRM( 3, 7, to );
2775 }
2776 write16( from );
2777 }
2778
2779 /* cmp imm16 to m16 */
CMP16ItoM(uptr to,u16 from)2780 void CMP16ItoM( uptr to, u16 from )
2781 {
2782 MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 7, to, 2);
2783 write16( from );
2784 }
2785
2786 /* cmp r16 to r16 */
CMP16RtoR(x86IntRegType to,x86IntRegType from)2787 void CMP16RtoR( x86IntRegType to, x86IntRegType from )
2788 {
2789 write8( 0x66 );
2790 RexRB(0,from,to);
2791 write8( 0x39 );
2792 ModRM( 3, from, to );
2793 }
2794
2795 /* cmp m16 to r16 */
CMP16MtoR(x86IntRegType to,uptr from)2796 void CMP16MtoR( x86IntRegType to, uptr from )
2797 {
2798 MEMADDR_OP(0, VAROP2(0x66, 0x3B), true, to, from, 0);
2799 }
2800
2801 // cmp imm8 to r8
CMP8ItoR(x86IntRegType to,u8 from)2802 void CMP8ItoR( x86IntRegType to, u8 from )
2803 {
2804 RexB(0,to);
2805 if ( to == EAX )
2806 {
2807 write8( 0x3C );
2808 }
2809 else
2810 {
2811 write8( 0x80 );
2812 ModRM( 3, 7, to );
2813 }
2814 write8( from );
2815 }
2816
2817 // cmp m8 to r8
CMP8MtoR(x86IntRegType to,uptr from)2818 void CMP8MtoR( x86IntRegType to, uptr from )
2819 {
2820 MEMADDR_OP(0, VAROP1(0x3A), true, to, from, 0);
2821 }
2822
2823 /* test r64 to r64 */
TEST64RtoR(x86IntRegType to,x86IntRegType from)2824 void TEST64RtoR( x86IntRegType to, x86IntRegType from )
2825 {
2826 RexRB(1, from, to);
2827 write8( 0x85 );
2828 ModRM( 3, from, to );
2829 }
2830
2831 /* test imm32 to r32 */
TEST32ItoR(x86IntRegType to,u32 from)2832 void TEST32ItoR( x86IntRegType to, u32 from )
2833 {
2834 RexB(0,to);
2835 if ( to == EAX )
2836 {
2837 write8( 0xA9 );
2838 }
2839 else
2840 {
2841 write8( 0xF7 );
2842 ModRM( 3, 0, to );
2843 }
2844 write32( from );
2845 }
2846
TEST32ItoM(uptr to,u32 from)2847 void TEST32ItoM( uptr to, u32 from )
2848 {
2849 MEMADDR_OP(0, VAROP1(0xF7), false, 0, to, 4);
2850 write32( from );
2851 }
2852
2853 /* test r32 to r32 */
TEST32RtoR(x86IntRegType to,x86IntRegType from)2854 void TEST32RtoR( x86IntRegType to, x86IntRegType from )
2855 {
2856 RexRB(0,from,to);
2857 write8( 0x85 );
2858 ModRM( 3, from, to );
2859 }
2860
2861 // test imm32 to [r32]
TEST32ItoRm(x86IntRegType to,u32 from)2862 void TEST32ItoRm( x86IntRegType to, u32 from )
2863 {
2864 RexB(0,to);
2865 write8( 0xF7 );
2866 ModRM( 0, 0, to );
2867 write32(from);
2868 }
2869
2870 // test imm16 to r16
TEST16ItoR(x86IntRegType to,u16 from)2871 void TEST16ItoR( x86IntRegType to, u16 from )
2872 {
2873 write8(0x66);
2874 RexB(0,to);
2875 if ( to == EAX )
2876 {
2877 write8( 0xA9 );
2878 }
2879 else
2880 {
2881 write8( 0xF7 );
2882 ModRM( 3, 0, to );
2883 }
2884 write16( from );
2885 }
2886
2887 // test r16 to r16
TEST16RtoR(x86IntRegType to,x86IntRegType from)2888 void TEST16RtoR( x86IntRegType to, x86IntRegType from )
2889 {
2890 write8(0x66);
2891 RexRB(0,from,to);
2892 write16( 0x85 );
2893 ModRM( 3, from, to );
2894 }
2895
2896 // test imm8 to r8
TEST8ItoR(x86IntRegType to,u8 from)2897 void TEST8ItoR( x86IntRegType to, u8 from )
2898 {
2899 RexB(0,to);
2900 if ( to == EAX )
2901 {
2902 write8( 0xA8 );
2903 }
2904 else
2905 {
2906 write8( 0xF6 );
2907 ModRM( 3, 0, to );
2908 }
2909 write8( from );
2910 }
2911
2912 // test imm8 to r8
TEST8ItoM(uptr to,u8 from)2913 void TEST8ItoM( uptr to, u8 from )
2914 {
2915 MEMADDR_OP(0, VAROP1(0xF6), false, 0, to, 1);
2916 write8( from );
2917 }
2918
2919 /* sets r8 */
SETS8R(x86IntRegType to)2920 void SETS8R( x86IntRegType to )
2921 {
2922 SET8R( 0x98, to );
2923 }
2924
2925 /* setl r8 */
SETL8R(x86IntRegType to)2926 void SETL8R( x86IntRegType to )
2927 {
2928 SET8R( 0x9C, to );
2929 }
2930
2931 // setge r8
SETGE8R(x86IntRegType to)2932 void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); }
2933 // setg r8
SETG8R(x86IntRegType to)2934 void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); }
2935 // seta r8
SETA8R(x86IntRegType to)2936 void SETA8R( x86IntRegType to ) { SET8R(0x97, to); }
2937 // setae r8
SETAE8R(x86IntRegType to)2938 void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); }
2939 /* setb r8 */
SETB8R(x86IntRegType to)2940 void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); }
2941 /* setb r8 */
SETNZ8R(x86IntRegType to)2942 void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); }
2943 // setz r8
SETZ8R(x86IntRegType to)2944 void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); }
2945 // sete r8
SETE8R(x86IntRegType to)2946 void SETE8R( x86IntRegType to ) { SET8R(0x94, to); }
2947
2948 /* push imm32 */
PUSH32I(u32 from)2949 void PUSH32I( u32 from )
2950 {
2951 //X86_64ASSERT(); //becomes sign extended in x86_64
2952 write8( 0x68 );
2953 write32( from );
2954 }
2955
2956 #ifdef __x86_64__
2957
2958 /* push r64 */
PUSH64R(x86IntRegType from)2959 void PUSH64R( x86IntRegType from )
2960 {
2961 RexB(0,from);
2962 //write8( 0x51 | from );
2963 write8( 0x50 | from );
2964 }
2965
2966 /* push m64 */
PUSH64M(uptr from)2967 void PUSH64M( uptr from )
2968 {
2969 MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
2970 }
2971
2972 /* pop r64 */
POP64R(x86IntRegType from)2973 void POP64R( x86IntRegType from ) {
2974 RexB(0,from);
2975 //write8( 0x59 | from );
2976 write8( 0x58 | from );
2977 }
2978
PUSHR(x86IntRegType from)2979 void PUSHR(x86IntRegType from) { PUSH64R(from); }
POPR(x86IntRegType from)2980 void POPR(x86IntRegType from) { POP64R(from); }
2981
2982 #else
2983
2984 /* push r32 */
PUSH32R(x86IntRegType from)2985 void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); }
2986
2987 /* push m32 */
PUSH32M(uptr from)2988 void PUSH32M( uptr from )
2989 {
2990 MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
2991 }
2992
2993 /* pop r32 */
POP32R(x86IntRegType from)2994 void POP32R( x86IntRegType from ) { write8( 0x58 | from ); }
2995
2996 /* pushad */
PUSHA32(void)2997 void PUSHA32( void ) { write8( 0x60 ); }
2998
2999 /* popad */
POPA32(void)3000 void POPA32( void ) { write8( 0x61 ); }
3001
PUSHR(x86IntRegType from)3002 void PUSHR(x86IntRegType from) { PUSH32R(from); }
POPR(x86IntRegType from)3003 void POPR(x86IntRegType from) { POP32R(from); }
3004
3005 #endif
3006
3007
3008 /* pushfd */
PUSHFD(void)3009 void PUSHFD( void ) { write8( 0x9C ); }
3010 /* popfd */
POPFD(void)3011 void POPFD( void ) { write8( 0x9D ); }
3012
RET(void)3013 void RET( void ) { write8( 0xC3 ); }
RET2(void)3014 void RET2( void ) { write16( 0xc3f3 ); }
3015
CBW(void)3016 void CBW( void ) { write16( 0x9866 ); }
CWD(void)3017 void CWD( void ) { write8( 0x98 ); }
CDQ(void)3018 void CDQ( void ) { write8( 0x99 ); }
CWDE()3019 void CWDE() { write8(0x98); }
3020
3021 #ifdef __x86_64__
CDQE(void)3022 void CDQE( void ) { RexR(1,0); write8( 0x98 ); }
3023 #endif
3024
LAHF()3025 void LAHF() { write8(0x9f); }
SAHF()3026 void SAHF() { write8(0x9e); }
3027
BT32ItoR(x86IntRegType to,x86IntRegType from)3028 void BT32ItoR( x86IntRegType to, x86IntRegType from )
3029 {
3030 write16( 0xBA0F );
3031 write8( 0xE0 | to );
3032 write8( from );
3033 }
3034
BSRRtoR(x86IntRegType to,x86IntRegType from)3035 void BSRRtoR(x86IntRegType to, x86IntRegType from)
3036 {
3037 write16( 0xBD0F );
3038 ModRM( 3, from, to );
3039 }
3040
BSWAP32R(x86IntRegType to)3041 void BSWAP32R( x86IntRegType to )
3042 {
3043 write8( 0x0F );
3044 write8( 0xC8 + to );
3045 }
3046
3047 // to = from + offset
LEA16RtoR(x86IntRegType to,x86IntRegType from,u16 offset)3048 void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset)
3049 {
3050 write8(0x66);
3051 LEA32RtoR(to, from, offset);
3052 }
3053
LEA32RtoR(x86IntRegType to,x86IntRegType from,u32 offset)3054 void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
3055 {
3056 RexRB(0,to,from);
3057 write8(0x8d);
3058
3059 if( (from&7) == ESP ) {
3060 if( offset == 0 ) {
3061 ModRM(1, to, from);
3062 write8(0x24);
3063 }
3064 else if( offset < 128 ) {
3065 ModRM(1, to, from);
3066 write8(0x24);
3067 write8(offset);
3068 }
3069 else {
3070 ModRM(2, to, from);
3071 write8(0x24);
3072 write32(offset);
3073 }
3074 }
3075 else {
3076 if( offset == 0 && from != EBP && from!=ESP ) {
3077 ModRM(0, to, from);
3078 }
3079 else if( offset < 128 ) {
3080 ModRM(1, to, from);
3081 write8(offset);
3082 }
3083 else {
3084 ModRM(2, to, from);
3085 write32(offset);
3086 }
3087 }
3088 }
3089
3090 // to = from0 + from1
LEA16RRtoR(x86IntRegType to,x86IntRegType from0,x86IntRegType from1)3091 void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
3092 {
3093 write8(0x66);
3094 LEA32RRtoR(to, from0, from1);
3095 }
3096
LEA32RRtoR(x86IntRegType to,x86IntRegType from0,x86IntRegType from1)3097 void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
3098 {
3099 RexRXB(0, to, from0, from1);
3100 write8(0x8d);
3101
3102 if( (from1&7) == EBP ) {
3103 ModRM(1, to, 4);
3104 ModRM(0, from0, from1);
3105 write8(0);
3106 }
3107 else {
3108 ModRM(0, to, 4);
3109 ModRM(0, from0, from1);
3110 }
3111 }
3112
3113 // to = from << scale (max is 3)
LEA16RStoR(x86IntRegType to,x86IntRegType from,u32 scale)3114 void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
3115 {
3116 write8(0x66);
3117 LEA32RStoR(to, from, scale);
3118 }
3119
LEA32RStoR(x86IntRegType to,x86IntRegType from,u32 scale)3120 void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
3121 {
3122 if( to == from ) {
3123 SHL32ItoR(to, scale);
3124 return;
3125 }
3126
3127 if( from != ESP ) {
3128 RexRXB(0,to,from,0);
3129 write8(0x8d);
3130 ModRM(0, to, 4);
3131 ModRM(scale, from, 5);
3132 write32(0);
3133 }
3134 else {
3135 assert( to != ESP );
3136 MOV32RtoR(to, from);
3137 LEA32RStoR(to, to, scale);
3138 }
3139 }
3140
3141 #endif
3142
3143 #endif
3144