improve ARM feature detection
[pcsx_rearmed.git] / libpcsxcore / ix86_64 / ix86-64.c
CommitLineData
ef79bbde
P
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
21x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 };
22x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX };
23
24// arranged in savedreg -> tempreg order
25x86IntRegType 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)
31x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 };
32// temp registers that need to be saved across calls
33x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI };
34
35// arranged in savedreg -> tempreg order
36x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI };
37
38#endif
39
40x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 };
41x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI };
42
43#endif // __x86_64__
44
45s8 *x86Ptr;
46u8 *j8Ptr[32];
47u32 *j32Ptr[32];
48
49void 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
82void 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
116void CheckX86Ptr( void )
117{
118}
119
120void 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
139void 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
170void SET8R( int cc, int to )
171{
172 RexB(0, to);
173 write8( 0x0F );
174 write8( cc );
175 write8( 0xC0 | ( to ) );
176}
177
178u8* J8Rel( int cc, int to )
179{
180 write8( cc );
181 write8( to );
182 return x86Ptr - 1;
183}
184
185u16* J16Rel( int cc, u32 to )
186{
187 write16( 0x0F66 );
188 write8( cc );
189 write16( to );
190 return (u16*)( x86Ptr - 2 );
191}
192
193u32* J32Rel( int cc, u32 to )
194{
195 write8( 0x0F );
196 write8( cc );
197 write32( to );
198 return (u32*)( x86Ptr - 4 );
199}
200
201void 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
209void CMOV32MtoR( int cc, x86IntRegType to, uptr from )
210{
211 MEMADDR_OP(0, VAROP2(0x0F, cc), true, to, from, 0);
212}
213
214////////////////////////////////////////////////////
215void x86SetPtr( char* ptr )
216{
217 x86Ptr = ptr;
218}
219
220////////////////////////////////////////////////////
221void x86Shutdown( void )
222{
223}
224
225////////////////////////////////////////////////////
226void 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
237void 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
258void 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
270void x86SetJ16A( u16 *j16 )
271{
272 if( ((uptr)x86Ptr&0xf) > 4 ) {
273 while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
274 }
275 x86SetJ16(j16);
276}
277
278////////////////////////////////////////////////////
279void x86SetJ32( u32* j32 )
280{
281 *j32 = ( x86Ptr - (s8*)j32 ) - 4;
282}
283
284void x86SetJ32A( u32* j32 )
285{
286 while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
287 x86SetJ32(j32);
288}
289
290////////////////////////////////////////////////////
291void x86Align( int bytes )
292{
293 // fordward align
294 x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) );
295}
296
297/********************/
298/* IX86 intructions */
299/********************/
300
301void STC( void )
302{
303 write8( 0xF9 );
304}
305
306void CLC( void )
307{
308 write8( 0xF8 );
309}
310
311////////////////////////////////////
312// mov instructions /
313////////////////////////////////////
314
315/* mov r64 to r64 */
316void 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 */
324void 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 */
339void 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 */
354void 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
361void 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 */
369void 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]
378void 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
387void 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 */
395void 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] */
403void 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] */
411void 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 */
420void 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 */
428void 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 */
442void 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 */
456void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) {
457 RexRB(0, to, from);
458 write8(0x8B);
459 WriteRmOffsetFrom(to, from, 0);
460}
461
462void 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 */
469void 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]
477void 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] */
487void 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] */
500void 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 */
508void 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 */
516void 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]
523void 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]
532void 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 */
540void 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 */
555void 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
569void MOV16RmtoR( x86IntRegType to, x86IntRegType from)
570{
571 write8( 0x66 );
572 RexRB(0,to,from);
573 write8( 0x8B );
574 WriteRmOffsetFrom(to, from, 0);
575}
576
577void 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
585void 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
595void 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 */
604void 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] */
611void 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
619void 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]
627void 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]
637void 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 */
646void 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 */
660void 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 */
674void MOV8RmtoR(x86IntRegType to, x86IntRegType from)
675{
676 RexRB(0,to,from);
677 write8( 0x8A );
678 WriteRmOffsetFrom(to, from, 0);
679}
680
681void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset)
682{
683 RexRB(0,to,from);
684 write8( 0x8A );
685 WriteRmOffsetFrom(to, from, offset);
686}
687
688void 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 */
696void 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
703void 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]
711void 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]
721void 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 */
730void MOVSX32R8toR( x86IntRegType to, x86IntRegType from )
731{
732 RexRB(0,to,from);
733 write16( 0xBE0F );
734 ModRM( 3, to, from );
735}
736
737void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from )
738{
739 RexRB(0,to,from);
740 write16( 0xBE0F );
741 ModRM( 0, to, from );
742}
743
744void 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 */
752void MOVSX32M8toR( x86IntRegType to, uptr from )
753{
754 MEMADDR_OP(0, VAROP2(0x0F, 0xBE), true, to, from, 0);
755}
756
757/* movsx r16 to r32 */
758void MOVSX32R16toR( x86IntRegType to, x86IntRegType from )
759{
760 RexRB(0,to,from);
761 write16( 0xBF0F );
762 ModRM( 3, to, from );
763}
764
765void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from )
766{
767 RexRB(0,to,from);
768 write16( 0xBF0F );
769 ModRM( 0, to, from );
770}
771
772void 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 */
780void MOVSX32M16toR( x86IntRegType to, uptr from )
781{
782 MEMADDR_OP(0, VAROP2(0x0F, 0xBF), true, to, from, 0);
783}
784
785/* movzx r8 to r32 */
786void MOVZX32R8toR( x86IntRegType to, x86IntRegType from )
787{
788 RexRB(0,to,from);
789 write16( 0xB60F );
790 ModRM( 3, to, from );
791}
792
793void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from )
794{
795 RexRB(0,to,from);
796 write16( 0xB60F );
797 ModRM( 0, to, from );
798}
799
800void 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 */
808void MOVZX32M8toR( x86IntRegType to, uptr from )
809{
810 MEMADDR_OP(0, VAROP2(0x0F, 0xB6), true, to, from, 0);
811}
812
813/* movzx r16 to r32 */
814void MOVZX32R16toR( x86IntRegType to, x86IntRegType from )
815{
816 RexRB(0,to,from);
817 write16( 0xB70F );
818 ModRM( 3, to, from );
819}
820
821void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from )
822{
823 RexRB(0,to,from);
824 write16( 0xB70F );
825 ModRM( 0, to, from );
826}
827
828void 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 */
836void 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 */
844void MOVZX64R8toR( x86IntRegType to, x86IntRegType from )
845{
846 RexRB(1,to,from);
847 write16( 0xB60F );
848 ModRM( 3, to, from );
849}
850
851void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from )
852{
853 RexRB(1,to,from);
854 write16( 0xB60F );
855 ModRM( 0, to, from );
856}
857
858void 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 */
866void MOVZX64M8toR( x86IntRegType to, uptr from )
867{
868 MEMADDR_OP(1, VAROP2(0x0F, 0xB6), true, to, from, 0);
869}
870
871/* movzx r16 to r64 */
872void MOVZX64R16toR( x86IntRegType to, x86IntRegType from )
873{
874 RexRB(1,to,from);
875 write16( 0xB70F );
876 ModRM( 3, to, from );
877}
878
879void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from )
880{
881 RexRB(1,to,from);
882 write16( 0xB70F );
883 ModRM( 0, to, from );
884}
885
886void 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 */
894void 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 */
901void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from )
902{
903 CMOV32RtoR( 0x46, to, from );
904}
905
906/* cmovbe m32 to r32*/
907void CMOVBE32MtoR( x86IntRegType to, uptr from )
908{
909 CMOV32MtoR( 0x46, to, from );
910}
911
912/* cmovb r32 to r32 */
913void CMOVB32RtoR( x86IntRegType to, x86IntRegType from )
914{
915 CMOV32RtoR( 0x42, to, from );
916}
917
918/* cmovb m32 to r32*/
919void CMOVB32MtoR( x86IntRegType to, uptr from )
920{
921 CMOV32MtoR( 0x42, to, from );
922}
923
924/* cmovae r32 to r32 */
925void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from )
926{
927 CMOV32RtoR( 0x43, to, from );
928}
929
930/* cmovae m32 to r32*/
931void CMOVAE32MtoR( x86IntRegType to, uptr from )
932{
933 CMOV32MtoR( 0x43, to, from );
934}
935
936/* cmova r32 to r32 */
937void CMOVA32RtoR( x86IntRegType to, x86IntRegType from )
938{
939 CMOV32RtoR( 0x47, to, from );
940}
941
942/* cmova m32 to r32*/
943void CMOVA32MtoR( x86IntRegType to, uptr from )
944{
945 CMOV32MtoR( 0x47, to, from );
946}
947
948/* cmovo r32 to r32 */
949void CMOVO32RtoR( x86IntRegType to, x86IntRegType from )
950{
951 CMOV32RtoR( 0x40, to, from );
952}
953
954/* cmovo m32 to r32 */
955void CMOVO32MtoR( x86IntRegType to, uptr from )
956{
957 CMOV32MtoR( 0x40, to, from );
958}
959
960/* cmovp r32 to r32 */
961void CMOVP32RtoR( x86IntRegType to, x86IntRegType from )
962{
963 CMOV32RtoR( 0x4A, to, from );
964}
965
966/* cmovp m32 to r32 */
967void CMOVP32MtoR( x86IntRegType to, uptr from )
968{
969 CMOV32MtoR( 0x4A, to, from );
970}
971
972/* cmovs r32 to r32 */
973void CMOVS32RtoR( x86IntRegType to, x86IntRegType from )
974{
975 CMOV32RtoR( 0x48, to, from );
976}
977
978/* cmovs m32 to r32 */
979void CMOVS32MtoR( x86IntRegType to, uptr from )
980{
981 CMOV32MtoR( 0x48, to, from );
982}
983
984/* cmovno r32 to r32 */
985void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from )
986{
987 CMOV32RtoR( 0x41, to, from );
988}
989
990/* cmovno m32 to r32 */
991void CMOVNO32MtoR( x86IntRegType to, uptr from )
992{
993 CMOV32MtoR( 0x41, to, from );
994}
995
996/* cmovnp r32 to r32 */
997void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from )
998{
999 CMOV32RtoR( 0x4B, to, from );
1000}
1001
1002/* cmovnp m32 to r32 */
1003void CMOVNP32MtoR( x86IntRegType to, uptr from )
1004{
1005 CMOV32MtoR( 0x4B, to, from );
1006}
1007
1008/* cmovns r32 to r32 */
1009void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from )
1010{
1011 CMOV32RtoR( 0x49, to, from );
1012}
1013
1014/* cmovns m32 to r32 */
1015void CMOVNS32MtoR( x86IntRegType to, uptr from )
1016{
1017 CMOV32MtoR( 0x49, to, from );
1018}
1019
1020/* cmovne r32 to r32 */
1021void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from )
1022{
1023 CMOV32RtoR( 0x45, to, from );
1024}
1025
1026/* cmovne m32 to r32*/
1027void CMOVNE32MtoR( x86IntRegType to, uptr from )
1028{
1029 CMOV32MtoR( 0x45, to, from );
1030}
1031
1032/* cmove r32 to r32*/
1033void CMOVE32RtoR( x86IntRegType to, x86IntRegType from )
1034{
1035 CMOV32RtoR( 0x44, to, from );
1036}
1037
1038/* cmove m32 to r32*/
1039void CMOVE32MtoR( x86IntRegType to, uptr from )
1040{
1041 CMOV32MtoR( 0x44, to, from );
1042}
1043
1044/* cmovg r32 to r32*/
1045void CMOVG32RtoR( x86IntRegType to, x86IntRegType from )
1046{
1047 CMOV32RtoR( 0x4F, to, from );
1048}
1049
1050/* cmovg m32 to r32*/
1051void CMOVG32MtoR( x86IntRegType to, uptr from )
1052{
1053 CMOV32MtoR( 0x4F, to, from );
1054}
1055
1056/* cmovge r32 to r32*/
1057void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from )
1058{
1059 CMOV32RtoR( 0x4D, to, from );
1060}
1061
1062/* cmovge m32 to r32*/
1063void CMOVGE32MtoR( x86IntRegType to, uptr from )
1064{
1065 CMOV32MtoR( 0x4D, to, from );
1066}
1067
1068/* cmovl r32 to r32*/
1069void CMOVL32RtoR( x86IntRegType to, x86IntRegType from )
1070{
1071 CMOV32RtoR( 0x4C, to, from );
1072}
1073
1074/* cmovl m32 to r32*/
1075void CMOVL32MtoR( x86IntRegType to, uptr from )
1076{
1077 CMOV32MtoR( 0x4C, to, from );
1078}
1079
1080/* cmovle r32 to r32*/
1081void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from )
1082{
1083 CMOV32RtoR( 0x4E, to, from );
1084}
1085
1086/* cmovle m32 to r32*/
1087void CMOVLE32MtoR( x86IntRegType to, uptr from )
1088{
1089 CMOV32MtoR( 0x4E, to, from );
1090}
1091
1092////////////////////////////////////
1093// arithmetic instructions /
1094////////////////////////////////////
1095
1096/* add imm32 to r64 */
1097void 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 */
1119void ADD64MtoR( x86IntRegType to, uptr from )
1120{
1121 MEMADDR_OP(1, VAROP1(0x03), true, to, from, 0);
1122}
1123
1124/* add r64 to r64 */
1125void 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 */
1133void 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 */
1147void 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]
1154void 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 */
1163void 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 */
1171void ADD32RtoM(uptr to, x86IntRegType from )
1172{
1173 MEMADDR_OP(0, VAROP1(0x01), true, from, to, 0);
1174}
1175
1176/* add m32 to r32 */
1177void ADD32MtoR( x86IntRegType to, uptr from )
1178{
1179 MEMADDR_OP(0, VAROP1(0x03), true, to, from, 0);
1180}
1181
1182// add r16 to r16
1183void 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 */
1192void 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 */
1209void 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 */
1216void ADD16RtoM(uptr to, x86IntRegType from )
1217{
1218 MEMADDR_OP(0, VAROP2(0x66, 0x01), true, from, to, 0);
1219}
1220
1221/* add m16 to r16 */
1222void ADD16MtoR( x86IntRegType to, uptr from )
1223{
1224 MEMADDR_OP(0, VAROP2(0x66, 0x03), true, to, from, 0);
1225}
1226
1227// add m8 to r8
1228void ADD8MtoR( x86IntRegType to, uptr from )
1229{
1230 MEMADDR_OP(0, VAROP1(0x02), true, to, from, 0);
1231}
1232
1233/* adc imm32 to r32 */
1234void 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 */
1248void 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 */
1255void 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 */
1263void ADC32MtoR( x86IntRegType to, uptr from )
1264{
1265 MEMADDR_OP(0, VAROP1(0x13), true, to, from, 0);
1266}
1267
1268// adc r32 to m32
1269void ADC32RtoM( uptr to, x86IntRegType from )
1270{
1271 MEMADDR_OP(0, VAROP1(0x11), true, from, to, 0);
1272}
1273
1274
1275#ifdef __x86_64__
1276void INC32R( x86IntRegType to )
1277{
1278 write8( 0xFF );
1279 ModRM(3,0,to);
1280}
1281#else
1282/* inc r32 */
1283void INC32R( x86IntRegType to )
1284{
1285 X86_64ASSERT();
1286 write8( 0x40 + to );
1287}
1288#endif
1289/* inc m32 */
1290void INC32M( uptr to )
1291{
1292 MEMADDR_OP(0, VAROP1(0xFF), false, 0, to, 0);
1293}
1294
1295/* inc r16 */
1296void INC16R( x86IntRegType to )
1297{
1298 X86_64ASSERT();
1299 write8( 0x66 );
1300 write8( 0x40 + to );
1301}
1302
1303/* inc m16 */
1304void INC16M( uptr to )
1305{
1306 MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 0, to, 0);
1307}
1308
1309
1310/* sub imm32 to r64 */
1311void 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 */
1334void 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 */
1342void SUB64MtoR( x86IntRegType to, uptr from )
1343{
1344 MEMADDR_OP(1, VAROP1(0x2B), true, to, from, 0);
1345}
1346
1347/* sub imm32 to r32 */
1348void 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 */
1362void 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 */
1369void 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 */
1377void SUB32MtoR( x86IntRegType to, uptr from )
1378{
1379 MEMADDR_OP(0, VAROP1(0x2B), true, to, from, 0);
1380}
1381
1382// sub r32 to m32
1383void SUB32RtoM( uptr to, x86IntRegType from )
1384{
1385 MEMADDR_OP(0, VAROP1(0x29), true, from, to, 0);
1386}
1387
1388// sub r16 to r16
1389void 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 */
1398void 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 */
1411void 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 */
1417void SUB16MtoR( x86IntRegType to, uptr from ) {
1418 MEMADDR_OP(0, VAROP2(0x66, 0x2B), true, to, from, 0);
1419}
1420
1421/* sbb r64 to r64 */
1422void 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 */
1429void 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 */
1441void 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 */
1447void 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 */
1455void SBB32MtoR( x86IntRegType to, uptr from )
1456{
1457 MEMADDR_OP(0, VAROP1(0x1B), true, to, from, 0);
1458}
1459
1460/* sbb r32 to m32 */
1461void SBB32RtoM( uptr to, x86IntRegType from )
1462{
1463 MEMADDR_OP(0, VAROP1(0x19), true, from, to, 0);
1464}
1465
1466#ifdef __x86_64__
1467void DEC32R( x86IntRegType to )
1468{
1469 write8( 0xFF );
1470 ModRM(3,1,to);
1471}
1472#else
1473/* dec r32 */
1474void DEC32R( x86IntRegType to )
1475{
1476 X86_64ASSERT();
1477 write8( 0x48 + to );
1478}
1479#endif
1480
1481/* dec m32 */
1482void DEC32M( uptr to )
1483{
1484 MEMADDR_OP(0, VAROP1(0xFF), false, 1, to, 0);
1485}
1486
1487/* dec r16 */
1488void DEC16R( x86IntRegType to )
1489{
1490 X86_64ASSERT();
1491 write8( 0x66 );
1492 write8( 0x48 + to );
1493}
1494
1495/* dec m16 */
1496void 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 */
1502void 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 */
1510void 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 */
1518void MUL32M( uptr from )
1519{
1520 MEMADDR_OP(0, VAROP1(0xF7), false, 4, from, 0);
1521}
1522
1523/* imul eax by m32 to edx:eax */
1524void IMUL32M( uptr from )
1525{
1526 MEMADDR_OP(0, VAROP1(0xF7), false, 5, from, 0);
1527}
1528
1529/* imul r32 by r32 to r32 */
1530void 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 */
1538void 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 */
1546void 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 */
1554void DIV32M( uptr from )
1555{
1556 MEMADDR_OP(0, VAROP1(0xF7), false, 6, from, 0);
1557}
1558
1559/* idiv eax by m32 to edx:eax */
1560void 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 */
1570void 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 */
1585void SHL64CLtoR( x86IntRegType to )
1586{
1587 RexB(1, to);
1588 write8( 0xD3 );
1589 ModRM( 3, 4, to );
1590}
1591
1592/* shr imm8 to r64 */
1593void 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 */
1607void SHR64CLtoR( x86IntRegType to )
1608{
1609 RexB(1, to);
1610 write8( 0xD3 );
1611 ModRM( 3, 5, to );
1612}
1613
1614/* shl imm8 to r32 */
1615void 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 */
1630void 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 */
1644void SHL32CLtoR( x86IntRegType to )
1645{
1646 RexB(0,to);
1647 write8( 0xD3 );
1648 ModRM( 3, 4, to );
1649}
1650
1651// shl imm8 to r16
1652void 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
1668void 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 */
1683void 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 */
1699void 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 */
1713void SHR32CLtoR( x86IntRegType to )
1714{
1715 RexB(0,to);
1716 write8( 0xD3 );
1717 ModRM( 3, 5, to );
1718}
1719
1720// shr imm8 to r8
1721void 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 */
1738void 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 */
1753void SAR64CLtoR( x86IntRegType to )
1754{
1755 RexB(1, to);
1756 write8( 0xD3 );
1757 ModRM( 3, 7, to );
1758}
1759
1760/* sar imm8 to r32 */
1761void 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 */
1776void 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 */
1790void SAR32CLtoR( x86IntRegType to )
1791{
1792 RexB(0,to);
1793 write8( 0xD3 );
1794 ModRM( 3, 7, to );
1795}
1796
1797// sar imm8 to r16
1798void 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
1813void 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
1828void 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
1844void 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
1854void 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 */
1868void 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 */
1881void OR64MtoR( x86IntRegType to, uptr from )
1882{
1883 MEMADDR_OP(1, VAROP1(0x0B), true, to, from, 0);
1884}
1885
1886/* or r64 to r64 */
1887void 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
1895void OR64RtoM(uptr to, x86IntRegType from )
1896{
1897 MEMADDR_OP(1, VAROP1(0x09), true, from, to, 0);
1898}
1899
1900/* or imm32 to r32 */
1901void 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 */
1915void 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 */
1922void 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 */
1930void OR32RtoM(uptr to, x86IntRegType from )
1931{
1932 MEMADDR_OP(0, VAROP1(0x09), true, from, to, 0);
1933}
1934
1935/* or m32 to r32 */
1936void OR32MtoR( x86IntRegType to, uptr from )
1937{
1938 MEMADDR_OP(0, VAROP1(0x0B), true, to, from, 0);
1939}
1940
1941// or r16 to r16
1942void 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
1951void 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
1966void 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 */
1973void OR16MtoR( x86IntRegType to, uptr from )
1974{
1975 MEMADDR_OP(0, VAROP2(0x66, 0x0B), true, to, from, 0);
1976}
1977
1978// or r16 to m16
1979void OR16RtoM( uptr to, x86IntRegType from )
1980{
1981 MEMADDR_OP(0, VAROP2(0x66, 0x09), true, from, to, 0);
1982}
1983
1984// or r8 to r8
1985void 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
1993void OR8RtoM( uptr to, x86IntRegType from )
1994{
1995 MEMADDR_OP(0, VAROP1(0x08), true, from, to, 0);
1996}
1997
1998// or imm8 to m8
1999void 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
2006void OR8MtoR( x86IntRegType to, uptr from )
2007{
2008 MEMADDR_OP(0, VAROP1(0x0A), true, to, from, 0);
2009}
2010
2011/* xor imm32 to r64 */
2012void 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 */
2025void 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 */
2033void XOR64MtoR( x86IntRegType to, uptr from )
2034{
2035 MEMADDR_OP(1, VAROP1(0x33), true, to, from, 0);
2036}
2037
2038/* xor r64 to m64 */
2039void XOR64RtoM( uptr to, x86IntRegType from )
2040{
2041 MEMADDR_OP(1, VAROP1(0x31), true, from, to, 0);
2042}
2043
2044/* xor imm32 to r32 */
2045void 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 */
2059void 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 */
2066void 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 */
2074void 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 */
2083void XOR32RtoM( uptr to, x86IntRegType from )
2084{
2085 MEMADDR_OP(0, VAROP1(0x31), true, from, to, 0);
2086}
2087
2088/* xor m32 to r32 */
2089void XOR32MtoR( x86IntRegType to, uptr from )
2090{
2091 MEMADDR_OP(0, VAROP1(0x33), true, to, from, 0);
2092}
2093
2094// xor imm16 to r16
2095void 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
2110void XOR16RtoM( uptr to, x86IntRegType from )
2111{
2112 MEMADDR_OP(0, VAROP2(0x66, 0x31), true, from, to, 0);
2113}
2114
2115/* and imm32 to r64 */
2116void 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 */
2129void AND64MtoR( x86IntRegType to, uptr from )
2130{
2131 MEMADDR_OP(1, VAROP1(0x23), true, to, from, 0);
2132}
2133
2134/* and r64 to m64 */
2135void AND64RtoM( uptr to, x86IntRegType from )
2136{
2137 MEMADDR_OP(1, VAROP1(0x21), true, from, to, 0);
2138}
2139
2140/* and r64 to r64 */
2141void 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 */
2149void 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 */
2156void 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 */
2169void 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 */
2178void 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 */
2185void 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 */
2192void 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 */
2200void AND32RtoM( uptr to, x86IntRegType from )
2201{
2202 MEMADDR_OP(0, VAROP1(0x21), true, from, to, 0);
2203}
2204
2205/* and m32 to r32 */
2206void AND32MtoR( x86IntRegType to, uptr from )
2207{
2208 MEMADDR_OP(0, VAROP1(0x23), true, to, from, 0);
2209}
2210
2211// and r16 to r16
2212void 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 */
2221void 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 */
2235void 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 */
2242void AND16RtoM( uptr to, x86IntRegType from )
2243{
2244 MEMADDR_OP(0, VAROP2(0x66, 0x21), true, from, to, 0);
2245}
2246
2247/* and m16 to r16 */
2248void AND16MtoR( x86IntRegType to, uptr from )
2249{
2250 MEMADDR_OP(0, VAROP2(0x66, 0x23), true, to, from, 0);
2251}
2252
2253/* and imm8 to r8 */
2254void 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 */
2267void 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
2274void 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 */
2282void AND8RtoM( uptr to, x86IntRegType from )
2283{
2284 MEMADDR_OP(0, VAROP1(0x20), true, from, to, 0);
2285}
2286
2287/* and m8 to r8 */
2288void AND8MtoR( x86IntRegType to, uptr from )
2289{
2290 MEMADDR_OP(0, VAROP1(0x22), true, to, from, 0);
2291}
2292
2293/* not r64 */
2294void NOT64R( x86IntRegType from )
2295{
2296 RexB(1, from);
2297 write8( 0xF7 );
2298 ModRM( 3, 2, from );
2299}
2300
2301/* not r32 */
2302void NOT32R( x86IntRegType from )
2303{
2304 RexB(0,from);
2305 write8( 0xF7 );
2306 ModRM( 3, 2, from );
2307}
2308
2309// not m32
2310void NOT32M( uptr from )
2311{
2312 MEMADDR_OP(0, VAROP1(0xF7), false, 2, from, 0);
2313}
2314
2315/* neg r64 */
2316void NEG64R( x86IntRegType from )
2317{
2318 RexB(1, from);
2319 write8( 0xF7 );
2320 ModRM( 3, 3, from );
2321}
2322
2323/* neg r32 */
2324void NEG32R( x86IntRegType from )
2325{
2326 RexB(0,from);
2327 write8( 0xF7 );
2328 ModRM( 3, 3, from );
2329}
2330
2331void NEG32M( uptr from )
2332{
2333 MEMADDR_OP(0, VAROP1(0xF7), false, 3, from, 0);
2334}
2335
2336/* neg r16 */
2337void 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
2349u8* 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 */
2361u8* JMP8( u8 to )
2362{
2363 write8( 0xEB );
2364 write8( to );
2365 return x86Ptr - 1;
2366}
2367
2368/* jmp rel32 */
2369u32* 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 */
2378void JMPR( x86IntRegType to )
2379{
2380 RexB(0, to);
2381 write8( 0xFF );
2382 ModRM( 3, 4, to );
2383}
2384
2385// jmp m32
2386void JMP32M( uptr to )
2387{
2388 /* FIXME */
2389 MEMADDR_OP(0, VAROP1(0xFF), false, 4, to, 0);
2390}
2391
2392/* jp rel8 */
2393u8* JP8( u8 to ) {
2394 return J8Rel( 0x7A, to );
2395}
2396
2397/* jnp rel8 */
2398u8* JNP8( u8 to ) {
2399 return J8Rel( 0x7B, to );
2400}
2401
2402/* je rel8 */
2403u8* JE8( u8 to ) {
2404 return J8Rel( 0x74, to );
2405}
2406
2407/* jz rel8 */
2408u8* JZ8( u8 to )
2409{
2410 return J8Rel( 0x74, to );
2411}
2412
2413/* js rel8 */
2414u8* JS8( u8 to )
2415{
2416 return J8Rel( 0x78, to );
2417}
2418
2419/* jns rel8 */
2420u8* JNS8( u8 to )
2421{
2422 return J8Rel( 0x79, to );
2423}
2424
2425/* jg rel8 */
2426u8* JG8( u8 to )
2427{
2428 return J8Rel( 0x7F, to );
2429}
2430
2431/* jge rel8 */
2432u8* JGE8( u8 to )
2433{
2434 return J8Rel( 0x7D, to );
2435}
2436
2437/* jl rel8 */
2438u8* JL8( u8 to )
2439{
2440 return J8Rel( 0x7C, to );
2441}
2442
2443/* ja rel8 */
2444u8* JA8( u8 to )
2445{
2446 return J8Rel( 0x77, to );
2447}
2448
2449u8* JAE8( u8 to )
2450{
2451 return J8Rel( 0x73, to );
2452}
2453
2454/* jb rel8 */
2455u8* JB8( u8 to )
2456{
2457 return J8Rel( 0x72, to );
2458}
2459
2460/* jbe rel8 */
2461u8* JBE8( u8 to )
2462{
2463 return J8Rel( 0x76, to );
2464}
2465
2466/* jle rel8 */
2467u8* JLE8( u8 to )
2468{
2469 return J8Rel( 0x7E, to );
2470}
2471
2472/* jne rel8 */
2473u8* JNE8( u8 to )
2474{
2475 return J8Rel( 0x75, to );
2476}
2477
2478/* jnz rel8 */
2479u8* JNZ8( u8 to )
2480{
2481 return J8Rel( 0x75, to );
2482}
2483
2484/* jng rel8 */
2485u8* JNG8( u8 to )
2486{
2487 return J8Rel( 0x7E, to );
2488}
2489
2490/* jnge rel8 */
2491u8* JNGE8( u8 to )
2492{
2493 return J8Rel( 0x7C, to );
2494}
2495
2496/* jnl rel8 */
2497u8* JNL8( u8 to )
2498{
2499 return J8Rel( 0x7D, to );
2500}
2501
2502/* jnle rel8 */
2503u8* JNLE8( u8 to )
2504{
2505 return J8Rel( 0x7F, to );
2506}
2507
2508/* jo rel8 */
2509u8* JO8( u8 to )
2510{
2511 return J8Rel( 0x70, to );
2512}
2513
2514/* jno rel8 */
2515u8* JNO8( u8 to )
2516{
2517 return J8Rel( 0x71, to );
2518}
2519
2520// jb rel8
2521u16* JB16( u16 to )
2522{
2523 return J16Rel( 0x82, to );
2524}
2525
2526// jb rel32
2527u32* JB32( u32 to )
2528{
2529 return J32Rel( 0x82, to );
2530}
2531
2532/* je rel32 */
2533u32* JE32( u32 to )
2534{
2535 return J32Rel( 0x84, to );
2536}
2537
2538/* jz rel32 */
2539u32* JZ32( u32 to )
2540{
2541 return J32Rel( 0x84, to );
2542}
2543
2544/* jg rel32 */
2545u32* JG32( u32 to )
2546{
2547 return J32Rel( 0x8F, to );
2548}
2549
2550/* jge rel32 */
2551u32* JGE32( u32 to )
2552{
2553 return J32Rel( 0x8D, to );
2554}
2555
2556/* jl rel32 */
2557u32* JL32( u32 to )
2558{
2559 return J32Rel( 0x8C, to );
2560}
2561
2562/* jle rel32 */
2563u32* JLE32( u32 to )
2564{
2565 return J32Rel( 0x8E, to );
2566}
2567
2568/* jae rel32 */
2569u32* JAE32( u32 to )
2570{
2571 return J32Rel( 0x83, to );
2572}
2573
2574/* jne rel32 */
2575u32* JNE32( u32 to )
2576{
2577 return J32Rel( 0x85, to );
2578}
2579
2580/* jnz rel32 */
2581u32* JNZ32( u32 to )
2582{
2583 return J32Rel( 0x85, to );
2584}
2585
2586/* jng rel32 */
2587u32* JNG32( u32 to )
2588{
2589 return J32Rel( 0x8E, to );
2590}
2591
2592/* jnge rel32 */
2593u32* JNGE32( u32 to )
2594{
2595 return J32Rel( 0x8C, to );
2596}
2597
2598/* jnl rel32 */
2599u32* JNL32( u32 to )
2600{
2601 return J32Rel( 0x8D, to );
2602}
2603
2604/* jnle rel32 */
2605u32* JNLE32( u32 to )
2606{
2607 return J32Rel( 0x8F, to );
2608}
2609
2610/* jo rel32 */
2611u32* JO32( u32 to )
2612{
2613 return J32Rel( 0x80, to );
2614}
2615
2616/* jno rel32 */
2617u32* JNO32( u32 to )
2618{
2619 return J32Rel( 0x81, to );
2620}
2621
2622// js rel32
2623u32* JS32( u32 to )
2624{
2625 return J32Rel( 0x88, to );
2626}
2627
2628
2629/* call func */
2630void 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 */
2645void CALL32( s32 to )
2646{
2647 write8( 0xE8 );
2648 write32( to );
2649}
2650
2651/* call r32 */
2652void CALL32R( x86IntRegType to )
2653{
2654 RexB(0, to);
2655 write8( 0xFF );
2656 ModRM( 3, 2, to );
2657}
2658
2659/* call r64 */
2660void 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 */
2672void 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 */
2686void CMP64MtoR( x86IntRegType to, uptr from )
2687{
2688 MEMADDR_OP(1, VAROP1(0x3B), true, 2, from, 0);
2689}
2690
2691// cmp r64 to r64
2692void 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 */
2700void 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 */
2714void 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 */
2721void 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 */
2729void CMP32MtoR( x86IntRegType to, uptr from )
2730{
2731 MEMADDR_OP(0, VAROP1(0x3B), true, to, from, 0);
2732}
2733
2734// cmp imm8 to [r32]
2735void 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]
2744void 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]
2754void 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 */
2761void 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 */
2778void 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 */
2785void 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 */
2794void CMP16MtoR( x86IntRegType to, uptr from )
2795{
2796 MEMADDR_OP(0, VAROP2(0x66, 0x3B), true, to, from, 0);
2797}
2798
2799// cmp imm8 to r8
2800void 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
2816void CMP8MtoR( x86IntRegType to, uptr from )
2817{
2818 MEMADDR_OP(0, VAROP1(0x3A), true, to, from, 0);
2819}
2820
2821/* test r64 to r64 */
2822void 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 */
2830void 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
2845void 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 */
2852void 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]
2860void 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
2869void 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
2886void 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
2895void 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
2911void TEST8ItoM( uptr to, u8 from )
2912{
2913 MEMADDR_OP(0, VAROP1(0xF6), false, 0, to, 1);
2914 write8( from );
2915}
2916
2917/* sets r8 */
2918void SETS8R( x86IntRegType to )
2919{
2920 SET8R( 0x98, to );
2921}
2922
2923/* setl r8 */
2924void SETL8R( x86IntRegType to )
2925{
2926 SET8R( 0x9C, to );
2927}
2928
2929// setge r8
2930void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); }
2931// setg r8
2932void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); }
2933// seta r8
2934void SETA8R( x86IntRegType to ) { SET8R(0x97, to); }
2935// setae r8
2936void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); }
2937/* setb r8 */
2938void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); }
2939/* setb r8 */
2940void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); }
2941// setz r8
2942void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); }
2943// sete r8
2944void SETE8R( x86IntRegType to ) { SET8R(0x94, to); }
2945
2946/* push imm32 */
2947void 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 */
2957void PUSH64R( x86IntRegType from )
2958{
2959 RexB(0,from);
2960 //write8( 0x51 | from );
2961 write8( 0x50 | from );
2962}
2963
2964/* push m64 */
2965void PUSH64M( uptr from )
2966{
2967 MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
2968}
2969
2970/* pop r64 */
2971void POP64R( x86IntRegType from ) {
2972 RexB(0,from);
2973 //write8( 0x59 | from );
2974 write8( 0x58 | from );
2975}
2976
2977void PUSHR(x86IntRegType from) { PUSH64R(from); }
2978void POPR(x86IntRegType from) { POP64R(from); }
2979
2980#else
2981
2982/* push r32 */
2983void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); }
2984
2985/* push m32 */
2986void PUSH32M( uptr from )
2987{
2988 MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
2989}
2990
2991/* pop r32 */
2992void POP32R( x86IntRegType from ) { write8( 0x58 | from ); }
2993
2994/* pushad */
2995void PUSHA32( void ) { write8( 0x60 ); }
2996
2997/* popad */
2998void POPA32( void ) { write8( 0x61 ); }
2999
3000void PUSHR(x86IntRegType from) { PUSH32R(from); }
3001void POPR(x86IntRegType from) { POP32R(from); }
3002
3003#endif
3004
3005
3006/* pushfd */
3007void PUSHFD( void ) { write8( 0x9C ); }
3008/* popfd */
3009void POPFD( void ) { write8( 0x9D ); }
3010
3011void RET( void ) { write8( 0xC3 ); }
3012void RET2( void ) { write16( 0xc3f3 ); }
3013
3014void CBW( void ) { write16( 0x9866 ); }
3015void CWD( void ) { write8( 0x98 ); }
3016void CDQ( void ) { write8( 0x99 ); }
3017void CWDE() { write8(0x98); }
3018
3019#ifdef __x86_64__
3020void CDQE( void ) { RexR(1,0); write8( 0x98 ); }
3021#endif
3022
3023void LAHF() { write8(0x9f); }
3024void SAHF() { write8(0x9e); }
3025
3026void BT32ItoR( x86IntRegType to, x86IntRegType from )
3027{
3028 write16( 0xBA0F );
3029 write8( 0xE0 | to );
3030 write8( from );
3031}
3032
3033void BSRRtoR(x86IntRegType to, x86IntRegType from)
3034{
3035 write16( 0xBD0F );
3036 ModRM( 3, from, to );
3037}
3038
3039void BSWAP32R( x86IntRegType to )
3040{
3041 write8( 0x0F );
3042 write8( 0xC8 + to );
3043}
3044
3045// to = from + offset
3046void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset)
3047{
3048 write8(0x66);
3049 LEA32RtoR(to, from, offset);
3050}
3051
3052void 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
3089void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
3090{
3091 write8(0x66);
3092 LEA32RRtoR(to, from0, from1);
3093}
3094
3095void 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)
3112void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
3113{
3114 write8(0x66);
3115 LEA32RStoR(to, from, scale);
3116}
3117
3118void 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