aboutsummaryrefslogtreecommitdiff
path: root/libpcsxcore/ix86_64/ix86-64.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpcsxcore/ix86_64/ix86-64.c')
-rw-r--r--libpcsxcore/ix86_64/ix86-64.c3139
1 files changed, 3139 insertions, 0 deletions
diff --git a/libpcsxcore/ix86_64/ix86-64.c b/libpcsxcore/ix86_64/ix86-64.c
new file mode 100644
index 0000000..0582f35
--- /dev/null
+++ b/libpcsxcore/ix86_64/ix86-64.c
@@ -0,0 +1,3139 @@
+/*
+ * ix86 core v0.6.2
+ * Authors: linuzappz <linuzappz@pcsx.net>
+ * alexey silinov
+ * goldfinger
+ * zerofrog(@gmail.com)
+ */
+
+// stop compiling if NORECBUILD build (only for Visual Studio)
+#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "ix86-64.h"
+
+#ifdef __x86_64__
+
+#ifdef _MSC_VER
+// visual studio calling convention
+x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 };
+x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX };
+
+// arranged in savedreg -> tempreg order
+x86IntRegType g_x86allregs[14] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15, R8, R9, R10, R11, RDX, RCX };
+
+#else
+// standard calling convention
+
+// registers saved by called functions (no need to flush them across calls)
+x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 };
+// temp registers that need to be saved across calls
+x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI };
+
+// arranged in savedreg -> tempreg order
+x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI };
+
+#endif
+
+x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 };
+x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI };
+
+#endif // __x86_64__
+
+s8 *x86Ptr;
+u8 *j8Ptr[32];
+u32 *j32Ptr[32];
+
+void WriteRmOffset(x86IntRegType to, int offset)
+{
+ if( (to&7) == ESP ) {
+ if( offset == 0 ) {
+ ModRM( 0, 0, 4 );
+ ModRM( 0, ESP, 4 );
+ }
+ else if( offset < 128 && offset >= -128 ) {
+ ModRM( 1, 0, 4 );
+ ModRM( 0, ESP, 4 );
+ write8(offset);
+ }
+ else {
+ ModRM( 2, 0, 4 );
+ ModRM( 0, ESP, 4 );
+ write32(offset);
+ }
+ }
+ else {
+ if( offset == 0 ) {
+ ModRM( 0, 0, to );
+ }
+ else if( offset < 128 && offset >= -128 ) {
+ ModRM( 1, 0, to );
+ write8(offset);
+ }
+ else {
+ ModRM( 2, 0, to );
+ write32(offset);
+ }
+ }
+}
+
+void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset)
+{
+ if ((from&7) == ESP) {
+ if( offset == 0 ) {
+ ModRM( 0, to, 0x4 );
+ SibSB( 0, 0x4, 0x4 );
+ }
+ else if( offset < 128 && offset >= -128 ) {
+ ModRM( 1, to, 0x4 );
+ SibSB( 0, 0x4, 0x4 );
+ write8(offset);
+ }
+ else {
+ ModRM( 2, to, 0x4 );
+ SibSB( 0, 0x4, 0x4 );
+ write32(offset);
+ }
+ }
+ else {
+ if( offset == 0 ) {
+ ModRM( 0, to, from );
+ }
+ else if( offset < 128 && offset >= -128 ) {
+ ModRM( 1, to, from );
+ write8(offset);
+ }
+ else {
+ ModRM( 2, to, from );
+ write32(offset);
+ }
+ }
+}
+
+// This function is just for rec debugging purposes
+void CheckX86Ptr( void )
+{
+}
+
+void writeVAROP(unsigned opl, u64 op)
+{
+ while (opl--)
+ {
+ write8(op & 0xFF);
+ op >>= 8;
+ }
+}
+
+#define writeVARROP(REX, opl, op) ({ \
+ if (opl > 1 && ((op & 0xFF) == 0x66 || (op & 0xFF) == 0xF3 || (op & 0xFF) == 0xF2)) { \
+ write8(op & 0xFF); \
+ opl --; \
+ op >>= 8; \
+ } \
+ REX; \
+ writeVAROP(opl, op); \
+ })
+
+void MEMADDR_OP(bool w, unsigned opl, u64 op, bool isreg, int reg, uptr p, sptr off)
+{
+#ifdef __x86_64__
+ sptr pr = MEMADDR_(p, 5 + opl + (w || reg >= 8) + off);
+ if (SPTR32(pr))
+ {
+ writeVARROP(RexR(w, reg), opl, op);
+ ModRM(0, reg, DISP32);
+ write32(pr);
+ }
+ else if (UPTR32(p))
+ {
+ writeVARROP(RexR(w, reg), opl, op);
+ ModRM(0, reg, SIB);
+ SibSB(0, SIB, DISP32);
+ write32(p);
+ }
+ else
+ {
+ assert(!isreg || reg != X86_TEMP);
+ MOV64ItoR(X86_TEMP, p);
+ writeVARROP(RexRB(w, reg, X86_TEMP), opl, op);
+ ModRM(0, reg, X86_TEMP);
+ }
+#else
+ writeVARROP(RexR(w, reg), opl, op);
+ ModRM(0, reg, DISP32);
+ write32(p);
+#endif
+}
+
+void SET8R( int cc, int to )
+{
+ RexB(0, to);
+ write8( 0x0F );
+ write8( cc );
+ write8( 0xC0 | ( to ) );
+}
+
+u8* J8Rel( int cc, int to )
+{
+ write8( cc );
+ write8( to );
+ return x86Ptr - 1;
+}
+
+u16* J16Rel( int cc, u32 to )
+{
+ write16( 0x0F66 );
+ write8( cc );
+ write16( to );
+ return (u16*)( x86Ptr - 2 );
+}
+
+u32* J32Rel( int cc, u32 to )
+{
+ write8( 0x0F );
+ write8( cc );
+ write32( to );
+ return (u32*)( x86Ptr - 4 );
+}
+
+void CMOV32RtoR( int cc, int to, int from )
+{
+ RexRB(0,to, from);
+ write8( 0x0F );
+ write8( cc );
+ ModRM( 3, to, from );
+}
+
+void CMOV32MtoR( int cc, x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x0F, cc), true, to, from, 0);
+}
+
+////////////////////////////////////////////////////
+void x86SetPtr( char* ptr )
+{
+ x86Ptr = ptr;
+}
+
+////////////////////////////////////////////////////
+void x86Shutdown( void )
+{
+}
+
+////////////////////////////////////////////////////
+void x86SetJ8( u8* j8 )
+{
+ u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
+
+ if ( jump > 0x7f ) {
+ assert(0);
+ SysPrintf( "j8 greater than 0x7f!!\n" );
+ }
+ *j8 = (u8)jump;
+}
+
+void x86SetJ8A( u8* j8 )
+{
+ u32 jump = ( x86Ptr - (s8*)j8 ) - 1;
+
+ if ( jump > 0x7f ) {
+ assert(0);
+ SysPrintf( "j8 greater than 0x7f!!\n" );
+ }
+
+ if( ((uptr)x86Ptr&0xf) > 4 ) {
+
+ uptr newjump = jump + 16-((uptr)x86Ptr&0xf);
+
+ if( newjump <= 0x7f ) {
+ jump = newjump;
+ while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
+ }
+ }
+ *j8 = (u8)jump;
+}
+
+void x86SetJ16( u16 *j16 )
+{
+ // doesn't work
+ u32 jump = ( x86Ptr - (s8*)j16 ) - 2;
+
+ if ( jump > 0x7fff ) {
+ assert(0);
+ SysPrintf( "j16 greater than 0x7fff!!\n" );
+ }
+ *j16 = (u16)jump;
+}
+
+void x86SetJ16A( u16 *j16 )
+{
+ if( ((uptr)x86Ptr&0xf) > 4 ) {
+ while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
+ }
+ x86SetJ16(j16);
+}
+
+////////////////////////////////////////////////////
+void x86SetJ32( u32* j32 )
+{
+ *j32 = ( x86Ptr - (s8*)j32 ) - 4;
+}
+
+void x86SetJ32A( u32* j32 )
+{
+ while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90;
+ x86SetJ32(j32);
+}
+
+////////////////////////////////////////////////////
+void x86Align( int bytes )
+{
+ // fordward align
+ x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) );
+}
+
+/********************/
+/* IX86 intructions */
+/********************/
+
+void STC( void )
+{
+ write8( 0xF9 );
+}
+
+void CLC( void )
+{
+ write8( 0xF8 );
+}
+
+////////////////////////////////////
+// mov instructions /
+////////////////////////////////////
+
+/* mov r64 to r64 */
+void MOV64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x89 );
+ ModRM( 3, from, to );
+}
+
+/* mov r64 to m64 */
+void MOV64RtoM( uptr to, x86IntRegType from )
+{
+ if (from == RAX)
+ {
+ RexR(1, 0);
+ write8(0xA3);
+ write64(to);
+ }
+ else
+ {
+ MEMADDR_OP(1, VAROP1(0x89), true, from, to, 0);
+ }
+}
+
+/* mov m64 to r64 */
+void MOV64MtoR( x86IntRegType to, uptr from )
+{
+ if (to == RAX)
+ {
+ RexR(1, 0);
+ write8(0xA1);
+ write64(from);
+ }
+ else
+ {
+ MEMADDR_OP(1, VAROP1(0x8B), true, to, from, 0);
+ }
+}
+
+/* mov imm32 to m64 */
+void MOV64I32toM(uptr to, u32 from )
+{
+ MEMADDR_OP(1, VAROP1(0xC7), false, 0, to, 4);
+ write32(from);
+}
+
+// mov imm64 to r64
+void MOV64ItoR( x86IntRegType to, u64 from)
+{
+ RexB(1, to);
+ write8( 0xB8 | (to & 0x7) );
+ write64( from );
+}
+
+/* mov imm32 to r64 */
+void MOV64I32toR( x86IntRegType to, s32 from )
+{
+ RexB(1, to);
+ write8( 0xC7 );
+ ModRM( 0, 0, to );
+ write32( from );
+}
+
+// mov imm64 to [r64+off]
+void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset)
+{
+ RexB(1,to);
+ write8( 0xC7 );
+ WriteRmOffset(to, offset);
+ write32(from);
+}
+
+// mov [r64+offset] to r64
+void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(1, to, from);
+ write8( 0x8B );
+ WriteRmOffsetFrom(to, from, offset);
+}
+
+/* mov [r64][r64*scale] to r64 */
+void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
+ RexRXB(1, to, from2, from);
+ write8( 0x8B );
+ ModRM( 0, to, 0x4 );
+ SibSB(scale, from2, from );
+}
+
+/* mov r64 to [r64+offset] */
+void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(1,from,to);
+ write8( 0x89 );
+ WriteRmOffsetFrom(from, to, offset);
+}
+
+/* mov r64 to [r64][r64*scale] */
+void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
+ RexRXB(1, to, from2, from);
+ write8( 0x89 );
+ ModRM( 0, to, 0x4 );
+ SibSB(scale, from2, from );
+}
+
+
+/* mov r32 to r32 */
+void MOV32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0, from, to);
+ write8( 0x89 );
+ ModRM( 3, from, to );
+}
+
+/* mov r32 to m32 */
+void MOV32RtoM( uptr to, x86IntRegType from )
+{
+ if (from == EAX)
+ {
+ write8(0xA3);
+ write64(to);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0x89), true, from, to, 0);
+ }
+}
+
+/* mov m32 to r32 */
+void MOV32MtoR( x86IntRegType to, uptr from )
+{
+ if (to == RAX)
+ {
+ write8(0xA1);
+ write64(from);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0x8B), true, to, from, 0);
+ }
+}
+
+/* mov [r32] to r32 */
+void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) {
+ RexRB(0, to, from);
+ write8(0x8B);
+ WriteRmOffsetFrom(to, from, 0);
+}
+
+void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) {
+ RexRB(0, to, from);
+ write8( 0x8B );
+ WriteRmOffsetFrom(to, from, offset);
+}
+
+/* mov [r32+r32*scale] to r32 */
+void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
+ RexRXB(0,to,from2,from);
+ write8( 0x8B );
+ ModRM( 0, to, 0x4 );
+ SibSB(scale, from2, from );
+}
+
+// mov r32 to [r32<<scale+from2]
+void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, int from2, int scale )
+{
+ RexRXB(0,to,from1,0);
+ write8( 0x8B );
+ ModRM( 0, to, 0x4 );
+ ModRM( scale, from1, 5);
+ write32(from2);
+}
+
+/* mov r32 to [r32] */
+void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) {
+ RexRB(0, from, to);
+ if ((to&7) == ESP) {
+ write8( 0x89 );
+ ModRM( 0, from, 0x4 );
+ SibSB( 0, 0x4, 0x4 );
+ } else {
+ write8( 0x89 );
+ ModRM( 0, from, to );
+ }
+}
+
+/* mov r32 to [r32][r32*scale] */
+void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
+ RexRXB(0, to, from2, from);
+ write8( 0x89 );
+ ModRM( 0, to, 0x4 );
+ SibSB(scale, from2, from );
+}
+
+/* mov imm32 to r32 */
+void MOV32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0, to);
+ write8( 0xB8 | (to & 0x7) );
+ write32( from );
+}
+
+/* mov imm32 to m32 */
+void MOV32ItoM(uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0xC7), false, 0, to, 4);
+ write32(from);
+}
+
+// mov imm32 to [r32+off]
+void MOV32ItoRmOffset( x86IntRegType to, u32 from, int offset)
+{
+ RexB(0,to);
+ write8( 0xC7 );
+ WriteRmOffset(to, offset);
+ write32(from);
+}
+
+// mov r32 to [r32+off]
+void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
+{
+ RexRB(0,from,to);
+ write8( 0x89 );
+ WriteRmOffsetFrom(from, to, offset);
+}
+
+/* mov r16 to m16 */
+void MOV16RtoM(uptr to, x86IntRegType from )
+{
+ if (from == EAX)
+ {
+ write8(0x66);
+ write8(0xA3);
+ write64(to);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP2(0x66, 0x89), true, from, to, 0);
+ }
+}
+
+/* mov m16 to r16 */
+void MOV16MtoR( x86IntRegType to, uptr from )
+{
+ if (to == EAX)
+ {
+ write8(0x66);
+ write8(0xA1);
+ write64(from);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP2(0x66, 0x8B), true, to, from, 0);
+ }
+}
+
+void MOV16RmtoR( x86IntRegType to, x86IntRegType from)
+{
+ write8( 0x66 );
+ RexRB(0,to,from);
+ write8( 0x8B );
+ WriteRmOffsetFrom(to, from, 0);
+}
+
+void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ write8( 0x66 );
+ RexRB(0,to,from);
+ write8( 0x8B );
+ WriteRmOffsetFrom(to, from, offset);
+}
+
+void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale )
+{
+ write8(0x66);
+ RexRXB(0,to,from1,0);
+ write8( 0x8B );
+ ModRM( 0, to, 0x4 );
+ ModRM( scale, from1, 5);
+ write32(from2);
+}
+
+void MOV16RtoRm(x86IntRegType to, x86IntRegType from)
+{
+ write8( 0x66 );
+ RexRB(0,from,to);
+ write8( 0x89 );
+ ModRM( 0, from, to );
+}
+
+/* mov imm16 to m16 */
+void MOV16ItoM( uptr to, u16 from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0xC7), false, 0, to, 2);
+ write16( from );
+}
+
+/* mov r16 to [r32][r32*scale] */
+void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) {
+ write8( 0x66 );
+ RexRXB(0,to,from2,from);
+ write8( 0x89 );
+ ModRM( 0, to, 0x4 );
+ SibSB(scale, from2, from );
+}
+
+void MOV16ItoR( x86IntRegType to, u16 from )
+{
+ RexB(0, to);
+ write16( 0xB866 | ((to & 0x7)<<8) );
+ write16( from );
+}
+
+// mov imm16 to [r16+off]
+void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset)
+{
+ write8(0x66);
+ RexB(0,to);
+ write8( 0xC7 );
+ WriteRmOffset(to, offset);
+ write16(from);
+}
+
+// mov r16 to [r16+off]
+void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
+{
+ write8(0x66);
+ RexRB(0,from,to);
+ write8( 0x89 );
+ WriteRmOffsetFrom(from, to, offset);
+}
+
+/* mov r8 to m8 */
+void MOV8RtoM( uptr to, x86IntRegType from )
+{
+ if (from == EAX)
+ {
+ write8(0xA2);
+ write64(to);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0x88), true, from, to, 0);
+ }
+}
+
+/* mov m8 to r8 */
+void MOV8MtoR( x86IntRegType to, uptr from )
+{
+ if (to == EAX)
+ {
+ write8(0xA0);
+ write64(from);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0x8A), true, to, from, 0);
+ }
+}
+
+/* mov [r32] to r8 */
+void MOV8RmtoR(x86IntRegType to, x86IntRegType from)
+{
+ RexRB(0,to,from);
+ write8( 0x8A );
+ WriteRmOffsetFrom(to, from, 0);
+}
+
+void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset)
+{
+ RexRB(0,to,from);
+ write8( 0x8A );
+ WriteRmOffsetFrom(to, from, offset);
+}
+
+void MOV8RtoRm(x86IntRegType to, x86IntRegType from)
+{
+ RexRB(0,from,to);
+ write8( 0x88 );
+ WriteRmOffsetFrom(from, to, 0);
+}
+
+/* mov imm8 to m8 */
+void MOV8ItoM( uptr to, u8 from )
+{
+ MEMADDR_OP(0, VAROP1(0xC6), false, 0, to, 1);
+ write8( from );
+}
+
+// mov imm8 to r8
+void MOV8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0, to);
+ write8( 0xB0 | (to & 0x7) );
+ write8( from );
+}
+
+// mov imm8 to [r8+off]
+void MOV8ItoRmOffset( x86IntRegType to, u8 from, int offset)
+{
+ assert( to != ESP );
+ RexB(0,to);
+ write8( 0xC6 );
+ WriteRmOffset(to,offset);
+ write8(from);
+}
+
+// mov r8 to [r8+off]
+void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset)
+{
+ assert( to != ESP );
+ RexRB(0,from,to);
+ write8( 0x88 );
+ WriteRmOffsetFrom(from,to,offset);
+}
+
+/* movsx r8 to r32 */
+void MOVSX32R8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xBE0F );
+ ModRM( 3, to, from );
+}
+
+void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xBE0F );
+ ModRM( 0, to, from );
+}
+
+void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(0,to,from);
+ write16( 0xBE0F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movsx m8 to r32 */
+void MOVSX32M8toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x0F, 0xBE), true, to, from, 0);
+}
+
+/* movsx r16 to r32 */
+void MOVSX32R16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xBF0F );
+ ModRM( 3, to, from );
+}
+
+void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xBF0F );
+ ModRM( 0, to, from );
+}
+
+void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(0,to,from);
+ write16( 0xBF0F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movsx m16 to r32 */
+void MOVSX32M16toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x0F, 0xBF), true, to, from, 0);
+}
+
+/* movzx r8 to r32 */
+void MOVZX32R8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xB60F );
+ ModRM( 3, to, from );
+}
+
+void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xB60F );
+ ModRM( 0, to, from );
+}
+
+void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(0,to,from);
+ write16( 0xB60F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movzx m8 to r32 */
+void MOVZX32M8toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x0F, 0xB6), true, to, from, 0);
+}
+
+/* movzx r16 to r32 */
+void MOVZX32R16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xB70F );
+ ModRM( 3, to, from );
+}
+
+void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xB70F );
+ ModRM( 0, to, from );
+}
+
+void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(0,to,from);
+ write16( 0xB70F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movzx m16 to r32 */
+void MOVZX32M16toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x0F, 0xB7), true, to, from, 0);
+}
+
+#ifdef __x86_64__
+
+/* movzx r8 to r64 */
+void MOVZX64R8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1,to,from);
+ write16( 0xB60F );
+ ModRM( 3, to, from );
+}
+
+void MOVZX64Rm8toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1,to,from);
+ write16( 0xB60F );
+ ModRM( 0, to, from );
+}
+
+void MOVZX64Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(1,to,from);
+ write16( 0xB60F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movzx m8 to r64 */
+void MOVZX64M8toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP2(0x0F, 0xB6), true, to, from, 0);
+}
+
+/* movzx r16 to r64 */
+void MOVZX64R16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1,to,from);
+ write16( 0xB70F );
+ ModRM( 3, to, from );
+}
+
+void MOVZX64Rm16toR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1,to,from);
+ write16( 0xB70F );
+ ModRM( 0, to, from );
+}
+
+void MOVZX64Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset )
+{
+ RexRB(1,to,from);
+ write16( 0xB70F );
+ WriteRmOffsetFrom(to,from,offset);
+}
+
+/* movzx m16 to r64 */
+void MOVZX64M16toR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP2(0x0F, 0xB7), true, to, from, 0);
+}
+#endif
+
+/* cmovbe r32 to r32 */
+void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x46, to, from );
+}
+
+/* cmovbe m32 to r32*/
+void CMOVBE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x46, to, from );
+}
+
+/* cmovb r32 to r32 */
+void CMOVB32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x42, to, from );
+}
+
+/* cmovb m32 to r32*/
+void CMOVB32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x42, to, from );
+}
+
+/* cmovae r32 to r32 */
+void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x43, to, from );
+}
+
+/* cmovae m32 to r32*/
+void CMOVAE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x43, to, from );
+}
+
+/* cmova r32 to r32 */
+void CMOVA32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x47, to, from );
+}
+
+/* cmova m32 to r32*/
+void CMOVA32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x47, to, from );
+}
+
+/* cmovo r32 to r32 */
+void CMOVO32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x40, to, from );
+}
+
+/* cmovo m32 to r32 */
+void CMOVO32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x40, to, from );
+}
+
+/* cmovp r32 to r32 */
+void CMOVP32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4A, to, from );
+}
+
+/* cmovp m32 to r32 */
+void CMOVP32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4A, to, from );
+}
+
+/* cmovs r32 to r32 */
+void CMOVS32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x48, to, from );
+}
+
+/* cmovs m32 to r32 */
+void CMOVS32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x48, to, from );
+}
+
+/* cmovno r32 to r32 */
+void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x41, to, from );
+}
+
+/* cmovno m32 to r32 */
+void CMOVNO32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x41, to, from );
+}
+
+/* cmovnp r32 to r32 */
+void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4B, to, from );
+}
+
+/* cmovnp m32 to r32 */
+void CMOVNP32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4B, to, from );
+}
+
+/* cmovns r32 to r32 */
+void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x49, to, from );
+}
+
+/* cmovns m32 to r32 */
+void CMOVNS32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x49, to, from );
+}
+
+/* cmovne r32 to r32 */
+void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x45, to, from );
+}
+
+/* cmovne m32 to r32*/
+void CMOVNE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x45, to, from );
+}
+
+/* cmove r32 to r32*/
+void CMOVE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x44, to, from );
+}
+
+/* cmove m32 to r32*/
+void CMOVE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x44, to, from );
+}
+
+/* cmovg r32 to r32*/
+void CMOVG32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4F, to, from );
+}
+
+/* cmovg m32 to r32*/
+void CMOVG32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4F, to, from );
+}
+
+/* cmovge r32 to r32*/
+void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4D, to, from );
+}
+
+/* cmovge m32 to r32*/
+void CMOVGE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4D, to, from );
+}
+
+/* cmovl r32 to r32*/
+void CMOVL32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4C, to, from );
+}
+
+/* cmovl m32 to r32*/
+void CMOVL32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4C, to, from );
+}
+
+/* cmovle r32 to r32*/
+void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ CMOV32RtoR( 0x4E, to, from );
+}
+
+/* cmovle m32 to r32*/
+void CMOVLE32MtoR( x86IntRegType to, uptr from )
+{
+ CMOV32MtoR( 0x4E, to, from );
+}
+
+////////////////////////////////////
+// arithmetic instructions /
+////////////////////////////////////
+
+/* add imm32 to r64 */
+void ADD64ItoR( x86IntRegType to, u32 from )
+{
+ RexB(1, to);
+ if (from <= 0x7f)
+ {
+ write8(0x83);
+ ModRM( 3, 0, to );
+ write8(from);
+ }
+ else
+ {
+ if (to == RAX) {
+ write8( 0x05 );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 0, to );
+ }
+ write32( from );
+ }
+}
+
+/* add m64 to r64 */
+void ADD64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x03), true, to, from, 0);
+}
+
+/* add r64 to r64 */
+void ADD64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x01 );
+ ModRM( 3, from, to );
+}
+
+/* add imm32 to r32 */
+void ADD32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0, to);
+ if ( to == EAX) {
+ write8( 0x05 );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 0, to );
+ }
+ write32( from );
+}
+
+/* add imm32 to m32 */
+void ADD32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 0, to, 4);
+ write32(from);
+}
+
+// add imm32 to [r32+off]
+void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset)
+{
+ RexB(0,to);
+ write8( 0x81 );
+ WriteRmOffset(to,offset);
+ write32(from);
+}
+
+/* add r32 to r32 */
+void ADD32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0, from, to);
+ write8( 0x01 );
+ ModRM( 3, from, to );
+}
+
+/* add r32 to m32 */
+void ADD32RtoM(uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x01), true, from, to, 0);
+}
+
+/* add m32 to r32 */
+void ADD32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x03), true, to, from, 0);
+}
+
+// add r16 to r16
+void ADD16RtoR( x86IntRegType to , x86IntRegType from )
+{
+ write8(0x66);
+ RexRB(0,to,from);
+ write8( 0x03 );
+ ModRM( 3, to, from );
+}
+
+/* add imm16 to r16 */
+void ADD16ItoR( x86IntRegType to, u16 from )
+{
+ write8( 0x66 );
+ RexB(0,to);
+ if ( to == EAX)
+ {
+ write8( 0x05 );
+ }
+ else
+ {
+ write8( 0x81 );
+ ModRM( 3, 0, to );
+ }
+ write16( from );
+}
+
+/* add imm16 to m16 */
+void ADD16ItoM( uptr to, u16 from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 0, to, 2);
+ write16( from );
+}
+
+/* add r16 to m16 */
+void ADD16RtoM(uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x01), true, from, to, 0);
+}
+
+/* add m16 to r16 */
+void ADD16MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x03), true, to, from, 0);
+}
+
+// add m8 to r8
+void ADD8MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x02), true, to, from, 0);
+}
+
+/* adc imm32 to r32 */
+void ADC32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x15 );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 2, to );
+ }
+ write32( from );
+}
+
+/* adc imm32 to m32 */
+void ADC32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 2, to, 4);
+ write32(from);
+}
+
+/* adc r32 to r32 */
+void ADC32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x11 );
+ ModRM( 3, from, to );
+}
+
+/* adc m32 to r32 */
+void ADC32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x13), true, to, from, 0);
+}
+
+// adc r32 to m32
+void ADC32RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x11), true, from, to, 0);
+}
+
+
+#ifdef __x86_64__
+void INC32R( x86IntRegType to )
+{
+ write8( 0xFF );
+ ModRM(3,0,to);
+}
+#else
+/* inc r32 */
+void INC32R( x86IntRegType to )
+{
+ X86_64ASSERT();
+ write8( 0x40 + to );
+}
+#endif
+/* inc m32 */
+void INC32M( uptr to )
+{
+ MEMADDR_OP(0, VAROP1(0xFF), false, 0, to, 0);
+}
+
+/* inc r16 */
+void INC16R( x86IntRegType to )
+{
+ X86_64ASSERT();
+ write8( 0x66 );
+ write8( 0x40 + to );
+}
+
+/* inc m16 */
+void INC16M( uptr to )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 0, to, 0);
+}
+
+
+/* sub imm32 to r64 */
+void SUB64ItoR( x86IntRegType to, u32 from )
+{
+ RexB(1, to);
+ if (from <= 0x7f)
+ {
+ write8(0x83);
+ ModRM( 3, 5, to );
+ write8(from);
+ }
+ else
+ {
+ if ( to == RAX ) {
+ write8( 0x2D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 5, to );
+ }
+ write32( from );
+ }
+}
+
+/* sub r64 to r64 */
+void SUB64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x29 );
+ ModRM( 3, from, to );
+}
+
+/* sub m64 to r64 */
+void SUB64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x2B), true, to, from, 0);
+}
+
+/* sub imm32 to r32 */
+void SUB32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x2D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 5, to );
+ }
+ write32( from );
+}
+
+/* sub imm32 to m32 */
+void SUB32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 5, to, 4);
+ write32(from);
+}
+
+/* sub r32 to r32 */
+void SUB32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0, from, to);
+ write8( 0x29 );
+ ModRM( 3, from, to );
+}
+
+/* sub m32 to r32 */
+void SUB32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x2B), true, to, from, 0);
+}
+
+// sub r32 to m32
+void SUB32RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x29), true, from, to, 0);
+}
+
+// sub r16 to r16
+void SUB16RtoR( x86IntRegType to, u16 from )
+{
+ write8(0x66);
+ RexRB(0,to,from);
+ write8( 0x2b );
+ ModRM( 3, to, from );
+}
+
+/* sub imm16 to r16 */
+void SUB16ItoR( x86IntRegType to, u16 from ) {
+ write8( 0x66 );
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x2D );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 5, to );
+ }
+ write16( from );
+}
+
+/* sub imm16 to m16 */
+void SUB16ItoM( uptr to, u16 from ) {
+ MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 5, to, 2);
+ write16( from );
+}
+
+/* sub m16 to r16 */
+void SUB16MtoR( x86IntRegType to, uptr from ) {
+ MEMADDR_OP(0, VAROP2(0x66, 0x2B), true, to, from, 0);
+}
+
+/* sbb r64 to r64 */
+void SBB64RtoR( x86IntRegType to, x86IntRegType from ) {
+ RexRB(1, from,to);
+ write8( 0x19 );
+ ModRM( 3, from, to );
+}
+
+/* sbb imm32 to r32 */
+void SBB32ItoR( x86IntRegType to, u32 from ) {
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x1D );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 3, to );
+ }
+ write32( from );
+}
+
+/* sbb imm32 to m32 */
+void SBB32ItoM( uptr to, u32 from ) {
+ MEMADDR_OP(0, VAROP1(0x81), false, 3, to, 4);
+ write32( from );
+}
+
+/* sbb r32 to r32 */
+void SBB32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x19 );
+ ModRM( 3, from, to );
+}
+
+/* sbb m32 to r32 */
+void SBB32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x1B), true, to, from, 0);
+}
+
+/* sbb r32 to m32 */
+void SBB32RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x19), true, from, to, 0);
+}
+
+#ifdef __x86_64__
+void DEC32R( x86IntRegType to )
+{
+ write8( 0xFF );
+ ModRM(3,1,to);
+}
+#else
+/* dec r32 */
+void DEC32R( x86IntRegType to )
+{
+ X86_64ASSERT();
+ write8( 0x48 + to );
+}
+#endif
+
+/* dec m32 */
+void DEC32M( uptr to )
+{
+ MEMADDR_OP(0, VAROP1(0xFF), false, 1, to, 0);
+}
+
+/* dec r16 */
+void DEC16R( x86IntRegType to )
+{
+ X86_64ASSERT();
+ write8( 0x66 );
+ write8( 0x48 + to );
+}
+
+/* dec m16 */
+void DEC16M( uptr to )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0xFF), false, 1, to, 0);
+}
+
+/* mul eax by r32 to edx:eax */
+void MUL32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 4, from );
+}
+
+/* imul eax by r32 to edx:eax */
+void IMUL32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 5, from );
+}
+
+/* mul eax by m32 to edx:eax */
+void MUL32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 4, from, 0);
+}
+
+/* imul eax by m32 to edx:eax */
+void IMUL32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 5, from, 0);
+}
+
+/* imul r32 by r32 to r32 */
+void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write16( 0xAF0F );
+ ModRM( 3, to, from );
+}
+
+/* div eax by r32 to edx:eax */
+void DIV32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 6, from );
+}
+
+/* idiv eax by r32 to edx:eax */
+void IDIV32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 7, from );
+}
+
+/* div eax by m32 to edx:eax */
+void DIV32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 6, from, 0);
+}
+
+/* idiv eax by m32 to edx:eax */
+void IDIV32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 7, from, 0);
+}
+
+////////////////////////////////////
+// shifting instructions /
+////////////////////////////////////
+
+/* shl imm8 to r64 */
+void SHL64ItoR( x86IntRegType to, u8 from )
+{
+ RexB(1, to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ ModRM( 3, 4, to );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 4, to );
+ write8( from );
+}
+
+/* shl cl to r64 */
+void SHL64CLtoR( x86IntRegType to )
+{
+ RexB(1, to);
+ write8( 0xD3 );
+ ModRM( 3, 4, to );
+}
+
+/* shr imm8 to r64 */
+void SHR64ItoR( x86IntRegType to, u8 from )
+{
+ RexB(1,to);
+ if ( from == 1 ) {
+ write8( 0xD1 );
+ ModRM( 3, 5, to );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 5, to );
+ write8( from );
+}
+
+/* shr cl to r64 */
+void SHR64CLtoR( x86IntRegType to )
+{
+ RexB(1, to);
+ write8( 0xD3 );
+ ModRM( 3, 5, to );
+}
+
+/* shl imm8 to r32 */
+void SHL32ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0, to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ write8( 0xE0 | (to & 0x7) );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 4, to );
+ write8( from );
+}
+
+/* shl imm8 to m32 */
+void SHL32ItoM( uptr to, u8 from )
+{
+ if ( from == 1 )
+ {
+ MEMADDR_OP(0, VAROP1(0xD1), false, 4, to, 0);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0xC1), false, 4, to, 1);
+ write8( from );
+ }
+}
+
+/* shl cl to r32 */
+void SHL32CLtoR( x86IntRegType to )
+{
+ RexB(0,to);
+ write8( 0xD3 );
+ ModRM( 3, 4, to );
+}
+
+// shl imm8 to r16
+void SHL16ItoR( x86IntRegType to, u8 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ write8( 0xE0 | (to & 0x7) );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 4, to );
+ write8( from );
+}
+
+// shl imm8 to r8
+void SHL8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD0 );
+ write8( 0xE0 | (to & 0x7) );
+ return;
+ }
+ write8( 0xC0 );
+ ModRM( 3, 4, to );
+ write8( from );
+}
+
+/* shr imm8 to r32 */
+void SHR32ItoR( x86IntRegType to, u8 from ) {
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ write8( 0xE8 | (to & 0x7) );
+ }
+ else
+ {
+ write8( 0xC1 );
+ ModRM( 3, 5, to );
+ write8( from );
+ }
+}
+
+/* shr imm8 to m32 */
+void SHR32ItoM( uptr to, u8 from )
+{
+ if ( from == 1 )
+ {
+ MEMADDR_OP(0, VAROP1(0xD1), false, 5, to, 0);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0xC1), false, 5, to, 1);
+ write8( from );
+ }
+}
+
+/* shr cl to r32 */
+void SHR32CLtoR( x86IntRegType to )
+{
+ RexB(0,to);
+ write8( 0xD3 );
+ ModRM( 3, 5, to );
+}
+
+// shr imm8 to r8
+void SHR8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD0 );
+ write8( 0xE8 | (to & 0x7) );
+ }
+ else
+ {
+ write8( 0xC0 );
+ ModRM( 3, 5, to );
+ write8( from );
+ }
+}
+
+/* sar imm8 to r64 */
+void SAR64ItoR( x86IntRegType to, u8 from )
+{
+ RexB(1,to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ ModRM( 3, 7, to );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 7, to );
+ write8( from );
+}
+
+/* sar cl to r64 */
+void SAR64CLtoR( x86IntRegType to )
+{
+ RexB(1, to);
+ write8( 0xD3 );
+ ModRM( 3, 7, to );
+}
+
+/* sar imm8 to r32 */
+void SAR32ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ ModRM( 3, 7, to );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 7, to );
+ write8( from );
+}
+
+/* sar imm8 to m32 */
+void SAR32ItoM( uptr to, u8 from )
+{
+ if (from == 1)
+ {
+ MEMADDR_OP(0, VAROP1(0xD1), false, 7, to, 0);
+ }
+ else
+ {
+ MEMADDR_OP(0, VAROP1(0xC1), false, 7, to, 1);
+ write8( from );
+ }
+}
+
+/* sar cl to r32 */
+void SAR32CLtoR( x86IntRegType to )
+{
+ RexB(0,to);
+ write8( 0xD3 );
+ ModRM( 3, 7, to );
+}
+
+// sar imm8 to r16
+void SAR16ItoR( x86IntRegType to, u8 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( from == 1 )
+ {
+ write8( 0xD1 );
+ ModRM( 3, 7, to );
+ return;
+ }
+ write8( 0xC1 );
+ ModRM( 3, 7, to );
+ write8( from );
+}
+
+void ROR32ItoR( x86IntRegType to,u8 from )
+{
+ RexB(0,to);
+ if ( from == 1 ) {
+ write8( 0xd1 );
+ write8( 0xc8 | to );
+ }
+ else
+ {
+ write8( 0xc1 );
+ write8( 0xc8 | to );
+ write8( from );
+ }
+}
+
+void RCR32ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( from == 1 ) {
+ write8( 0xd1 );
+ write8( 0xd8 | to );
+ }
+ else
+ {
+ write8( 0xc1 );
+ write8( 0xd8 | to );
+ write8( from );
+ }
+}
+
+// shld imm8 to r32
+void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
+{
+ RexRB(0,from,to);
+ write8( 0x0F );
+ write8( 0xA4 );
+ ModRM( 3, from, to );
+ write8( shift );
+}
+
+// shrd imm8 to r32
+void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
+{
+ RexRB(0,from,to);
+ write8( 0x0F );
+ write8( 0xAC );
+ ModRM( 3, from, to );
+ write8( shift );
+}
+
+////////////////////////////////////
+// logical instructions /
+////////////////////////////////////
+
+/* or imm32 to r32 */
+void OR64ItoR( x86IntRegType to, u32 from )
+{
+ RexB(1, to);
+ if ( to == EAX ) {
+ write8( 0x0D );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 1, to );
+ }
+ write32( from );
+}
+
+/* or m64 to r64 */
+void OR64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x0B), true, to, from, 0);
+}
+
+/* or r64 to r64 */
+void OR64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x09 );
+ ModRM( 3, from, to );
+}
+
+// or r32 to m64
+void OR64RtoM(uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(1, VAROP1(0x09), true, from, to, 0);
+}
+
+/* or imm32 to r32 */
+void OR32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x0D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 1, to );
+ }
+ write32( from );
+}
+
+/* or imm32 to m32 */
+void OR32ItoM(uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 1, to, 4);
+ write32(from);
+}
+
+/* or r32 to r32 */
+void OR32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x09 );
+ ModRM( 3, from, to );
+}
+
+/* or r32 to m32 */
+void OR32RtoM(uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x09), true, from, to, 0);
+}
+
+/* or m32 to r32 */
+void OR32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x0B), true, to, from, 0);
+}
+
+// or r16 to r16
+void OR16RtoR( x86IntRegType to, x86IntRegType from )
+{
+ write8(0x66);
+ RexRB(0,from,to);
+ write8( 0x09 );
+ ModRM( 3, from, to );
+}
+
+// or imm16 to r16
+void OR16ItoR( x86IntRegType to, u16 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x0D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 1, to );
+ }
+ write16( from );
+}
+
+// or imm16 to m316
+void OR16ItoM( uptr to, u16 from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 1, to, 2);
+ write16( from );
+}
+
+/* or m16 to r16 */
+void OR16MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x0B), true, to, from, 0);
+}
+
+// or r16 to m16
+void OR16RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x09), true, from, to, 0);
+}
+
+// or r8 to r8
+void OR8RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x08 );
+ ModRM( 3, from, to );
+}
+
+// or r8 to m8
+void OR8RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x08), true, from, to, 0);
+}
+
+// or imm8 to m8
+void OR8ItoM( uptr to, u8 from )
+{
+ MEMADDR_OP(0, VAROP1(0x80), false, 1, to, 1);
+ write8( from );
+}
+
+// or m8 to r8
+void OR8MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x0A), true, to, from, 0);
+}
+
+/* xor imm32 to r64 */
+void XOR64ItoR( x86IntRegType to, u32 from )
+{
+ RexB(1,to);
+ if ( to == EAX ) {
+ write8( 0x35 );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 6, to );
+ }
+ write32( from );
+}
+
+/* xor r64 to r64 */
+void XOR64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x31 );
+ ModRM( 3, from, to );
+}
+
+/* xor m64 to r64 */
+void XOR64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x33), true, to, from, 0);
+}
+
+/* xor r64 to m64 */
+void XOR64RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(1, VAROP1(0x31), true, from, to, 0);
+}
+
+/* xor imm32 to r32 */
+void XOR32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x35 );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 6, to );
+ }
+ write32( from );
+}
+
+/* xor imm32 to m32 */
+void XOR32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 6, to, 4);
+ write32( from );
+}
+
+/* xor r32 to r32 */
+void XOR32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x31 );
+ ModRM( 3, from, to );
+}
+
+/* xor r16 to r16 */
+void XOR16RtoR( x86IntRegType to, x86IntRegType from )
+{
+ write8( 0x66 );
+ RexRB(0,from,to);
+ write8( 0x31 );
+ ModRM( 3, from, to );
+}
+
+/* xor r32 to m32 */
+void XOR32RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x31), true, from, to, 0);
+}
+
+/* xor m32 to r32 */
+void XOR32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x33), true, to, from, 0);
+}
+
+// xor imm16 to r16
+void XOR16ItoR( x86IntRegType to, u16 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x35 );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 6, to );
+ }
+ write16( from );
+}
+
+// xor r16 to m16
+void XOR16RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x31), true, from, to, 0);
+}
+
+/* and imm32 to r64 */
+void AND64I32toR( x86IntRegType to, u32 from )
+{
+ RexB(1, to);
+ if ( to == EAX ) {
+ write8( 0x25 );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 0x4, to );
+ }
+ write32( from );
+}
+
+/* and m64 to r64 */
+void AND64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x23), true, to, from, 0);
+}
+
+/* and r64 to m64 */
+void AND64RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(1, VAROP1(0x21), true, from, to, 0);
+}
+
+/* and r64 to r64 */
+void AND64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x21 );
+ ModRM( 3, from, to );
+}
+
+/* and imm32 to m64 */
+void AND64I32toM( uptr to, u32 from )
+{
+ MEMADDR_OP(1, VAROP1(0x81), false, 4, to, 4);
+ write32( from );
+}
+
+/* and imm32 to r32 */
+void AND32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x25 );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 0x4, to );
+ }
+ write32( from );
+}
+
+/* and sign ext imm8 to r32 */
+void AND32I8toR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ write8( 0x83 );
+ ModRM( 3, 0x4, to );
+ write8( from );
+}
+
+/* and imm32 to m32 */
+void AND32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 4, to, 4);
+ write32(from);
+}
+
+/* and sign ext imm8 to m32 */
+void AND32I8toM( uptr to, u8 from )
+{
+ MEMADDR_OP(0, VAROP1(0x83), false, 4, to, 1);
+ write8( from );
+}
+
+/* and r32 to r32 */
+void AND32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x21 );
+ ModRM( 3, from, to );
+}
+
+/* and r32 to m32 */
+void AND32RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x21), true, from, to, 0);
+}
+
+/* and m32 to r32 */
+void AND32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x23), true, to, from, 0);
+}
+
+// and r16 to r16
+void AND16RtoR( x86IntRegType to, x86IntRegType from )
+{
+ write8(0x66);
+ RexRB(0,to,from);
+ write8( 0x23 );
+ ModRM( 3, to, from );
+}
+
+/* and imm16 to r16 */
+void AND16ItoR( x86IntRegType to, u16 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x25 );
+ } else {
+ write8( 0x81 );
+ ModRM( 3, 0x4, to );
+ }
+ write16( from );
+}
+
+/* and imm16 to m16 */
+void AND16ItoM( uptr to, u16 from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 4, to, 2);
+ write16( from );
+}
+
+/* and r16 to m16 */
+void AND16RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x21), true, from, to, 0);
+}
+
+/* and m16 to r16 */
+void AND16MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x23), true, to, from, 0);
+}
+
+/* and imm8 to r8 */
+void AND8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x24 );
+ } else {
+ write8( 0x80 );
+ ModRM( 3, 0x4, to );
+ }
+ write8( from );
+}
+
+/* and imm8 to m8 */
+void AND8ItoM( uptr to, u8 from )
+{
+ MEMADDR_OP(0, VAROP1(0x80), false, 4, to, 1);
+ write8( from );
+}
+
+// and r8 to r8
+void AND8RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,to,from);
+ write8( 0x22 );
+ ModRM( 3, to, from );
+}
+
+/* and r8 to m8 */
+void AND8RtoM( uptr to, x86IntRegType from )
+{
+ MEMADDR_OP(0, VAROP1(0x20), true, from, to, 0);
+}
+
+/* and m8 to r8 */
+void AND8MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x22), true, to, from, 0);
+}
+
+/* not r64 */
+void NOT64R( x86IntRegType from )
+{
+ RexB(1, from);
+ write8( 0xF7 );
+ ModRM( 3, 2, from );
+}
+
+/* not r32 */
+void NOT32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 2, from );
+}
+
+// not m32
+void NOT32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 2, from, 0);
+}
+
+/* neg r64 */
+void NEG64R( x86IntRegType from )
+{
+ RexB(1, from);
+ write8( 0xF7 );
+ ModRM( 3, 3, from );
+}
+
+/* neg r32 */
+void NEG32R( x86IntRegType from )
+{
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 3, from );
+}
+
+void NEG32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 3, from, 0);
+}
+
+/* neg r16 */
+void NEG16R( x86IntRegType from )
+{
+ write8( 0x66 );
+ RexB(0,from);
+ write8( 0xF7 );
+ ModRM( 3, 3, from );
+}
+
+////////////////////////////////////
+// jump instructions /
+////////////////////////////////////
+
+u8* JMP( uptr to ) {
+ uptr jump = ( x86Ptr - (s8*)to ) - 1;
+
+ if ( jump > 0x7f ) {
+ assert( to <= 0xffffffff );
+ return (u8*)JMP32( to );
+ } else {
+ return (u8*)JMP8( to );
+ }
+}
+
+/* jmp rel8 */
+u8* JMP8( u8 to )
+{
+ write8( 0xEB );
+ write8( to );
+ return x86Ptr - 1;
+}
+
+/* jmp rel32 */
+u32* JMP32( uptr to )
+{
+ assert(SPTR32((sptr)to));
+ write8( 0xE9 );
+ write32( (sptr)to );
+ return (u32*)(x86Ptr - 4 );
+}
+
+/* jmp r32/r64 */
+void JMPR( x86IntRegType to )
+{
+ RexB(0, to);
+ write8( 0xFF );
+ ModRM( 3, 4, to );
+}
+
+// jmp m32
+void JMP32M( uptr to )
+{
+ /* FIXME */
+ MEMADDR_OP(0, VAROP1(0xFF), false, 4, to, 0);
+}
+
+/* jp rel8 */
+u8* JP8( u8 to ) {
+ return J8Rel( 0x7A, to );
+}
+
+/* jnp rel8 */
+u8* JNP8( u8 to ) {
+ return J8Rel( 0x7B, to );
+}
+
+/* je rel8 */
+u8* JE8( u8 to ) {
+ return J8Rel( 0x74, to );
+}
+
+/* jz rel8 */
+u8* JZ8( u8 to )
+{
+ return J8Rel( 0x74, to );
+}
+
+/* js rel8 */
+u8* JS8( u8 to )
+{
+ return J8Rel( 0x78, to );
+}
+
+/* jns rel8 */
+u8* JNS8( u8 to )
+{
+ return J8Rel( 0x79, to );
+}
+
+/* jg rel8 */
+u8* JG8( u8 to )
+{
+ return J8Rel( 0x7F, to );
+}
+
+/* jge rel8 */
+u8* JGE8( u8 to )
+{
+ return J8Rel( 0x7D, to );
+}
+
+/* jl rel8 */
+u8* JL8( u8 to )
+{
+ return J8Rel( 0x7C, to );
+}
+
+/* ja rel8 */
+u8* JA8( u8 to )
+{
+ return J8Rel( 0x77, to );
+}
+
+u8* JAE8( u8 to )
+{
+ return J8Rel( 0x73, to );
+}
+
+/* jb rel8 */
+u8* JB8( u8 to )
+{
+ return J8Rel( 0x72, to );
+}
+
+/* jbe rel8 */
+u8* JBE8( u8 to )
+{
+ return J8Rel( 0x76, to );
+}
+
+/* jle rel8 */
+u8* JLE8( u8 to )
+{
+ return J8Rel( 0x7E, to );
+}
+
+/* jne rel8 */
+u8* JNE8( u8 to )
+{
+ return J8Rel( 0x75, to );
+}
+
+/* jnz rel8 */
+u8* JNZ8( u8 to )
+{
+ return J8Rel( 0x75, to );
+}
+
+/* jng rel8 */
+u8* JNG8( u8 to )
+{
+ return J8Rel( 0x7E, to );
+}
+
+/* jnge rel8 */
+u8* JNGE8( u8 to )
+{
+ return J8Rel( 0x7C, to );
+}
+
+/* jnl rel8 */
+u8* JNL8( u8 to )
+{
+ return J8Rel( 0x7D, to );
+}
+
+/* jnle rel8 */
+u8* JNLE8( u8 to )
+{
+ return J8Rel( 0x7F, to );
+}
+
+/* jo rel8 */
+u8* JO8( u8 to )
+{
+ return J8Rel( 0x70, to );
+}
+
+/* jno rel8 */
+u8* JNO8( u8 to )
+{
+ return J8Rel( 0x71, to );
+}
+
+// jb rel8
+u16* JB16( u16 to )
+{
+ return J16Rel( 0x82, to );
+}
+
+// jb rel32
+u32* JB32( u32 to )
+{
+ return J32Rel( 0x82, to );
+}
+
+/* je rel32 */
+u32* JE32( u32 to )
+{
+ return J32Rel( 0x84, to );
+}
+
+/* jz rel32 */
+u32* JZ32( u32 to )
+{
+ return J32Rel( 0x84, to );
+}
+
+/* jg rel32 */
+u32* JG32( u32 to )
+{
+ return J32Rel( 0x8F, to );
+}
+
+/* jge rel32 */
+u32* JGE32( u32 to )
+{
+ return J32Rel( 0x8D, to );
+}
+
+/* jl rel32 */
+u32* JL32( u32 to )
+{
+ return J32Rel( 0x8C, to );
+}
+
+/* jle rel32 */
+u32* JLE32( u32 to )
+{
+ return J32Rel( 0x8E, to );
+}
+
+/* jae rel32 */
+u32* JAE32( u32 to )
+{
+ return J32Rel( 0x83, to );
+}
+
+/* jne rel32 */
+u32* JNE32( u32 to )
+{
+ return J32Rel( 0x85, to );
+}
+
+/* jnz rel32 */
+u32* JNZ32( u32 to )
+{
+ return J32Rel( 0x85, to );
+}
+
+/* jng rel32 */
+u32* JNG32( u32 to )
+{
+ return J32Rel( 0x8E, to );
+}
+
+/* jnge rel32 */
+u32* JNGE32( u32 to )
+{
+ return J32Rel( 0x8C, to );
+}
+
+/* jnl rel32 */
+u32* JNL32( u32 to )
+{
+ return J32Rel( 0x8D, to );
+}
+
+/* jnle rel32 */
+u32* JNLE32( u32 to )
+{
+ return J32Rel( 0x8F, to );
+}
+
+/* jo rel32 */
+u32* JO32( u32 to )
+{
+ return J32Rel( 0x80, to );
+}
+
+/* jno rel32 */
+u32* JNO32( u32 to )
+{
+ return J32Rel( 0x81, to );
+}
+
+// js rel32
+u32* JS32( u32 to )
+{
+ return J32Rel( 0x88, to );
+}
+
+
+/* call func */
+void CALLFunc( uptr func )
+{
+ sptr p = MEMADDR_(func, 5);
+ if (SPTR32(p))
+ {
+ CALL32(p);
+ }
+ else
+ {
+ MOV64ItoR(X86_TEMP, func);
+ CALL64R(X86_TEMP);
+ }
+}
+
+/* call rel32 */
+void CALL32( s32 to )
+{
+ write8( 0xE8 );
+ write32( to );
+}
+
+/* call r32 */
+void CALL32R( x86IntRegType to )
+{
+ RexB(0, to);
+ write8( 0xFF );
+ ModRM( 3, 2, to );
+}
+
+/* call r64 */
+void CALL64R( x86IntRegType to )
+{
+ RexB(0, to);
+ write8( 0xFF );
+ ModRM( 3, 2, to );
+}
+
+////////////////////////////////////
+// misc instructions /
+////////////////////////////////////
+
+/* cmp imm32 to r64 */
+void CMP64I32toR( x86IntRegType to, u32 from )
+{
+ RexB(1, to);
+ if ( to == EAX ) {
+ write8( 0x3D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 7, to );
+ }
+ write32( from );
+}
+
+/* cmp m64 to r64 */
+void CMP64MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(1, VAROP1(0x3B), true, 2, from, 0);
+}
+
+// cmp r64 to r64
+void CMP64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1,from,to);
+ write8( 0x39 );
+ ModRM( 3, from, to );
+}
+
+/* cmp imm32 to r32 */
+void CMP32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX ) {
+ write8( 0x3D );
+ }
+ else {
+ write8( 0x81 );
+ ModRM( 3, 7, to );
+ }
+ write32( from );
+}
+
+/* cmp imm32 to m32 */
+void CMP32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0x81), false, 7, to, 4);
+ write32(from);
+}
+
+/* cmp r32 to r32 */
+void CMP32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x39 );
+ ModRM( 3, from, to );
+}
+
+/* cmp m32 to r32 */
+void CMP32MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x3B), true, to, from, 0);
+}
+
+// cmp imm8 to [r32]
+void CMP32I8toRm( x86IntRegType to, u8 from)
+{
+ RexB(0,to);
+ write8( 0x83 );
+ ModRM( 0, 7, to );
+ write8(from);
+}
+
+// cmp imm32 to [r32+off]
+void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off)
+{
+ RexB(0,to);
+ write8( 0x83 );
+ ModRM( 1, 7, to );
+ write8(off);
+ write8(from);
+}
+
+// cmp imm8 to [r32]
+void CMP32I8toM( uptr to, u8 from)
+{
+ MEMADDR_OP(0, VAROP1(0x83), false, 7, to, 1);
+ write8( from );
+}
+
+/* cmp imm16 to r16 */
+void CMP16ItoR( x86IntRegType to, u16 from )
+{
+ write8( 0x66 );
+ RexB(0,to);
+ if ( to == EAX )
+ {
+ write8( 0x3D );
+ }
+ else
+ {
+ write8( 0x81 );
+ ModRM( 3, 7, to );
+ }
+ write16( from );
+}
+
+/* cmp imm16 to m16 */
+void CMP16ItoM( uptr to, u16 from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x81), false, 7, to, 2);
+ write16( from );
+}
+
+/* cmp r16 to r16 */
+void CMP16RtoR( x86IntRegType to, x86IntRegType from )
+{
+ write8( 0x66 );
+ RexRB(0,from,to);
+ write8( 0x39 );
+ ModRM( 3, from, to );
+}
+
+/* cmp m16 to r16 */
+void CMP16MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP2(0x66, 0x3B), true, to, from, 0);
+}
+
+// cmp imm8 to r8
+void CMP8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( to == EAX )
+ {
+ write8( 0x3C );
+ }
+ else
+ {
+ write8( 0x80 );
+ ModRM( 3, 7, to );
+ }
+ write8( from );
+}
+
+// cmp m8 to r8
+void CMP8MtoR( x86IntRegType to, uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0x3A), true, to, from, 0);
+}
+
+/* test r64 to r64 */
+void TEST64RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(1, from, to);
+ write8( 0x85 );
+ ModRM( 3, from, to );
+}
+
+/* test imm32 to r32 */
+void TEST32ItoR( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ if ( to == EAX )
+ {
+ write8( 0xA9 );
+ }
+ else
+ {
+ write8( 0xF7 );
+ ModRM( 3, 0, to );
+ }
+ write32( from );
+}
+
+void TEST32ItoM( uptr to, u32 from )
+{
+ MEMADDR_OP(0, VAROP1(0xF7), false, 0, to, 4);
+ write32( from );
+}
+
+/* test r32 to r32 */
+void TEST32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ RexRB(0,from,to);
+ write8( 0x85 );
+ ModRM( 3, from, to );
+}
+
+// test imm32 to [r32]
+void TEST32ItoRm( x86IntRegType to, u32 from )
+{
+ RexB(0,to);
+ write8( 0xF7 );
+ ModRM( 0, 0, to );
+ write32(from);
+}
+
+// test imm16 to r16
+void TEST16ItoR( x86IntRegType to, u16 from )
+{
+ write8(0x66);
+ RexB(0,to);
+ if ( to == EAX )
+ {
+ write8( 0xA9 );
+ }
+ else
+ {
+ write8( 0xF7 );
+ ModRM( 3, 0, to );
+ }
+ write16( from );
+}
+
+// test r16 to r16
+void TEST16RtoR( x86IntRegType to, x86IntRegType from )
+{
+ write8(0x66);
+ RexRB(0,from,to);
+ write16( 0x85 );
+ ModRM( 3, from, to );
+}
+
+// test imm8 to r8
+void TEST8ItoR( x86IntRegType to, u8 from )
+{
+ RexB(0,to);
+ if ( to == EAX )
+ {
+ write8( 0xA8 );
+ }
+ else
+ {
+ write8( 0xF6 );
+ ModRM( 3, 0, to );
+ }
+ write8( from );
+}
+
+// test imm8 to r8
+void TEST8ItoM( uptr to, u8 from )
+{
+ MEMADDR_OP(0, VAROP1(0xF6), false, 0, to, 1);
+ write8( from );
+}
+
+/* sets r8 */
+void SETS8R( x86IntRegType to )
+{
+ SET8R( 0x98, to );
+}
+
+/* setl r8 */
+void SETL8R( x86IntRegType to )
+{
+ SET8R( 0x9C, to );
+}
+
+// setge r8
+void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); }
+// setg r8
+void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); }
+// seta r8
+void SETA8R( x86IntRegType to ) { SET8R(0x97, to); }
+// setae r8
+void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); }
+/* setb r8 */
+void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); }
+/* setb r8 */
+void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); }
+// setz r8
+void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); }
+// sete r8
+void SETE8R( x86IntRegType to ) { SET8R(0x94, to); }
+
+/* push imm32 */
+void PUSH32I( u32 from )
+{
+ //X86_64ASSERT(); //becomes sign extended in x86_64
+ write8( 0x68 );
+ write32( from );
+}
+
+#ifdef __x86_64__
+
+/* push r64 */
+void PUSH64R( x86IntRegType from )
+{
+ RexB(0,from);
+ //write8( 0x51 | from );
+ write8( 0x50 | from );
+}
+
+/* push m64 */
+void PUSH64M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
+}
+
+/* pop r64 */
+void POP64R( x86IntRegType from ) {
+ RexB(0,from);
+ //write8( 0x59 | from );
+ write8( 0x58 | from );
+}
+
+void PUSHR(x86IntRegType from) { PUSH64R(from); }
+void POPR(x86IntRegType from) { POP64R(from); }
+
+#else
+
+/* push r32 */
+void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); }
+
+/* push m32 */
+void PUSH32M( uptr from )
+{
+ MEMADDR_OP(0, VAROP1(0xFF), false, 6, from, 0);
+}
+
+/* pop r32 */
+void POP32R( x86IntRegType from ) { write8( 0x58 | from ); }
+
+/* pushad */
+void PUSHA32( void ) { write8( 0x60 ); }
+
+/* popad */
+void POPA32( void ) { write8( 0x61 ); }
+
+void PUSHR(x86IntRegType from) { PUSH32R(from); }
+void POPR(x86IntRegType from) { POP32R(from); }
+
+#endif
+
+
+/* pushfd */
+void PUSHFD( void ) { write8( 0x9C ); }
+/* popfd */
+void POPFD( void ) { write8( 0x9D ); }
+
+void RET( void ) { write8( 0xC3 ); }
+void RET2( void ) { write16( 0xc3f3 ); }
+
+void CBW( void ) { write16( 0x9866 ); }
+void CWD( void ) { write8( 0x98 ); }
+void CDQ( void ) { write8( 0x99 ); }
+void CWDE() { write8(0x98); }
+
+#ifdef __x86_64__
+void CDQE( void ) { RexR(1,0); write8( 0x98 ); }
+#endif
+
+void LAHF() { write8(0x9f); }
+void SAHF() { write8(0x9e); }
+
+void BT32ItoR( x86IntRegType to, x86IntRegType from )
+{
+ write16( 0xBA0F );
+ write8( 0xE0 | to );
+ write8( from );
+}
+
+void BSRRtoR(x86IntRegType to, x86IntRegType from)
+{
+ write16( 0xBD0F );
+ ModRM( 3, from, to );
+}
+
+void BSWAP32R( x86IntRegType to )
+{
+ write8( 0x0F );
+ write8( 0xC8 + to );
+}
+
+// to = from + offset
+void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset)
+{
+ write8(0x66);
+ LEA32RtoR(to, from, offset);
+}
+
+void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
+{
+ RexRB(0,to,from);
+ write8(0x8d);
+
+ if( (from&7) == ESP ) {
+ if( offset == 0 ) {
+ ModRM(1, to, from);
+ write8(0x24);
+ }
+ else if( offset < 128 ) {
+ ModRM(1, to, from);
+ write8(0x24);
+ write8(offset);
+ }
+ else {
+ ModRM(2, to, from);
+ write8(0x24);
+ write32(offset);
+ }
+ }
+ else {
+ if( offset == 0 && from != EBP && from!=ESP ) {
+ ModRM(0, to, from);
+ }
+ else if( offset < 128 ) {
+ ModRM(1, to, from);
+ write8(offset);
+ }
+ else {
+ ModRM(2, to, from);
+ write32(offset);
+ }
+ }
+}
+
+// to = from0 + from1
+void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
+{
+ write8(0x66);
+ LEA32RRtoR(to, from0, from1);
+}
+
+void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
+{
+ RexRXB(0, to, from0, from1);
+ write8(0x8d);
+
+ if( (from1&7) == EBP ) {
+ ModRM(1, to, 4);
+ ModRM(0, from0, from1);
+ write8(0);
+ }
+ else {
+ ModRM(0, to, 4);
+ ModRM(0, from0, from1);
+ }
+}
+
+// to = from << scale (max is 3)
+void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
+{
+ write8(0x66);
+ LEA32RStoR(to, from, scale);
+}
+
+void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
+{
+ if( to == from ) {
+ SHL32ItoR(to, scale);
+ return;
+ }
+
+ if( from != ESP ) {
+ RexRXB(0,to,from,0);
+ write8(0x8d);
+ ModRM(0, to, 4);
+ ModRM(scale, from, 5);
+ write32(0);
+ }
+ else {
+ assert( to != ESP );
+ MOV32RtoR(to, from);
+ LEA32RStoR(to, to, scale);
+ }
+}
+
+#endif