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