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