mirror of https://github.com/PCSX2/pcsx2.git
Ok, I lied -- more work on the emitter. I forgot to fix up the Jump/Call api yesterday and, along the way, did lots of major cleanups. :)
(and broke linux, probably!) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1054 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
286c405ce9
commit
7394e99ef6
|
@ -2989,13 +2989,13 @@
|
||||||
RelativePath="..\..\x86\ix86\ix86_types.h"
|
RelativePath="..\..\x86\ix86\ix86_types.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\x86\ix86\ix86_writers.inl"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Implement"
|
Name="Implement"
|
||||||
>
|
>
|
||||||
<File
|
|
||||||
RelativePath="..\..\x86\ix86\implement\bittest.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\x86\ix86\implement\dwshift.h"
|
RelativePath="..\..\x86\ix86\implement\dwshift.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1644,7 +1644,7 @@ StartRecomp:
|
||||||
}
|
}
|
||||||
if (startpc != 0x81fc0) {
|
if (startpc != 0x81fc0) {
|
||||||
xADD(ptr16[&manual_page[inpage_ptr >> 12]], 1);
|
xADD(ptr16[&manual_page[inpage_ptr >> 12]], 1);
|
||||||
iJccKnownTarget(Jcc_Carry, dyna_block_reset);
|
xJC( dyna_block_reset );
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgCon::WriteLn("Manual block @ %08X : %08X %d %d %d %d", params
|
DbgCon::WriteLn("Manual block @ %08X : %08X %d %d %d %d", params
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
/* Pcsx2 - Pc Ps2 Emulator
|
|
||||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Implementations found here: BTS/BT/BTC/BTR plus BSF/BSR!
|
|
||||||
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
|
||||||
|
|
||||||
// These instructions are in the 'Group8' as per Intel's manual, but since they all have
|
|
||||||
// a unified purpose, I've named them for that instead.
|
|
||||||
|
|
||||||
enum G8Type
|
|
||||||
{
|
|
||||||
G8Type_BT = 4,
|
|
||||||
G8Type_BTS,
|
|
||||||
G8Type_BTR,
|
|
||||||
G8Type_BTC,
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// BSF / BSR -- 16/32 operands supported only.
|
|
||||||
//
|
|
||||||
// 0xbc [fwd] / 0xbd [rev]
|
|
||||||
//
|
|
||||||
template< u16 Opcode >
|
|
||||||
class BitScanImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BitScanImpl() {}
|
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( Opcode, to, from ); }
|
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, Opcode, to, from ); }
|
|
||||||
__forceinline void operator()( const xRegister32& to, const void* src ) const { xOpWrite0F( Opcode, to, src ); }
|
|
||||||
__forceinline void operator()( const xRegister16& to, const void* src ) const { xOpWrite0F( 0x66, Opcode, to, src ); }
|
|
||||||
__forceinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { xOpWrite0F( Opcode, to, sibsrc ); }
|
|
||||||
__forceinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { xOpWrite0F( 0x66, Opcode, to, sibsrc ); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Bit Test Instructions - Valid on 16/32 bit instructions only.
|
|
||||||
//
|
|
||||||
template< G8Type InstType >
|
|
||||||
class Group8Impl : public BitScanImpl<0xa3 | (InstType << 2)>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using BitScanImpl<0xa3 | (InstType << 2)>::operator();
|
|
||||||
|
|
||||||
__forceinline void operator()( const ModSibStrict<u32>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase ); xWrite<u8>( bitoffset ); }
|
|
||||||
__forceinline void operator()( const ModSibStrict<u16>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase ); xWrite<u8>( bitoffset ); }
|
|
||||||
void operator()( const xRegister<u32>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase ); xWrite<u8>( bitoffset ); }
|
|
||||||
void operator()( const xRegister<u16>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase ); xWrite<u8>( bitoffset ); }
|
|
||||||
|
|
||||||
Group8Impl() {}
|
|
||||||
};
|
|
||||||
|
|
|
@ -21,109 +21,34 @@
|
||||||
// Implementations here cover SHLD and SHRD.
|
// Implementations here cover SHLD and SHRD.
|
||||||
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// -------------------------------------------------------------------
|
|
||||||
// Optimization Note: Imm shifts by 0 are ignore (no code generated). This is a safe optimization
|
|
||||||
// because shifts by 0 do *not* affect flags status.
|
|
||||||
|
|
||||||
template< typename ImmType, bool isShiftRight >
|
|
||||||
class DwordShiftImpl
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
|
||||||
|
|
||||||
static bool Is8BitOperand() { return OperandSize == 1; }
|
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
|
||||||
|
|
||||||
static void basesibform( bool isCL )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write8( 0x0f );
|
|
||||||
write8( (isCL ? 0xa5 : 0xa4) | (isShiftRight ? 0x8 : 0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
DwordShiftImpl() {} // because GCC doesn't like static classes
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const xRegister<ImmType>& from )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write16( 0xa50f | (isShiftRight ? 0x800 : 0) );
|
|
||||||
ModRM_Direct( from.Id, to.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const xRegister<ImmType>& from, u8 shiftcnt )
|
|
||||||
{
|
|
||||||
if( shiftcnt == 0 ) return;
|
|
||||||
prefix16();
|
|
||||||
write16( 0xa40f | (isShiftRight ? 0x800 : 0) );
|
|
||||||
ModRM_Direct( from.Id, to.Id );
|
|
||||||
write8( shiftcnt );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const ModSibBase& sibdest, const xRegister<ImmType>& from, __unused const xRegisterCL& clreg )
|
|
||||||
{
|
|
||||||
basesibform();
|
|
||||||
EmitSibMagic( from.Id, sibdest );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const ModSibBase& sibdest, const xRegister<ImmType>& from, u8 shiftcnt )
|
|
||||||
{
|
|
||||||
basesibform();
|
|
||||||
EmitSibMagic( from.Id, sibdest );
|
|
||||||
write8( shiftcnt );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// dest data type is inferred from the 'from' register, so we can do void* resolution :)
|
|
||||||
static __emitinline void Emit( void* dest, const xRegister<ImmType>& from, __unused const xRegisterCL& clreg )
|
|
||||||
{
|
|
||||||
basesibform();
|
|
||||||
xWriteDisp( from.Id, dest );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// dest data type is inferred from the 'from' register, so we can do void* resolution :)
|
|
||||||
static __emitinline void Emit( void* dest, const xRegister<ImmType>& from, u8 shiftcnt )
|
|
||||||
{
|
|
||||||
basesibform();
|
|
||||||
xWriteDisp( from.Id, dest );
|
|
||||||
write8( shiftcnt );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
// I use explicit method declarations here instead of templates, in order to provide
|
// I use explicit method declarations here instead of templates, in order to provide
|
||||||
// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in SHLD/SHRD).
|
// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in SHLD/SHRD).
|
||||||
//
|
//
|
||||||
|
// Optimization Note: Imm shifts by 0 are ignore (no code generated). This is a safe optimization
|
||||||
|
// because shifts by 0 do *not* affect flags status.
|
||||||
|
//
|
||||||
template< bool isShiftRight >
|
template< bool isShiftRight >
|
||||||
class DwordShiftImplAll
|
class DwordShiftImplAll
|
||||||
{
|
{
|
||||||
protected:
|
static const u8 m_shiftop = isShiftRight ? 0x8 : 0;
|
||||||
typedef DwordShiftImpl<u32, isShiftRight> m_32;
|
|
||||||
typedef DwordShiftImpl<u16, isShiftRight> m_16;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ---------- 32 Bit Interface -----------
|
// ---------- 32 Bit Interface -----------
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from, __unused const xRegisterCL& clreg ) const { m_32::Emit( to, from ); }
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, to, from ); }
|
||||||
__forceinline void operator()( void* dest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { m_32::Emit( dest, from ); }
|
__forceinline void operator()( void* dest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, from, dest ); }
|
||||||
__noinline void operator()( const ModSibBase& sibdest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { m_32::Emit( sibdest, from ); }
|
__forceinline void operator()( const ModSibBase& dest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, from, dest ); }
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from, u8 shiftcnt ) const { m_32::Emit( to, from, shiftcnt ); }
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, to, from ); }
|
||||||
__forceinline void operator()( void* dest, const xRegister32& from, u8 shiftcnt ) const { m_32::Emit( dest, from, shiftcnt ); }
|
__forceinline void operator()( void* dest, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, from, dest, shiftcnt ); }
|
||||||
__noinline void operator()( const ModSibBase& sibdest, const xRegister32& from, u8 shiftcnt ) const { m_32::Emit( sibdest, shiftcnt ); }
|
__forceinline void operator()( const ModSibBase& dest, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, from, dest, shiftcnt ); }
|
||||||
|
|
||||||
// ---------- 16 Bit Interface -----------
|
// ---------- 16 Bit Interface -----------
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from, __unused const xRegisterCL& clreg ) const { m_16::Emit( to, from ); }
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, to, from ); }
|
||||||
__forceinline void operator()( void* dest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { m_16::Emit( dest, from ); }
|
__forceinline void operator()( void* dest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, from, dest ); }
|
||||||
__noinline void operator()( const ModSibBase& sibdest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { m_16::Emit( sibdest, from ); }
|
__forceinline void operator()( const ModSibBase& dest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, from, dest ); }
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from, u8 shiftcnt ) const { m_16::Emit( to, from, shiftcnt ); }
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, to, from ); }
|
||||||
__forceinline void operator()( void* dest, const xRegister16& from, u8 shiftcnt ) const { m_16::Emit( dest, from, shiftcnt ); }
|
__forceinline void operator()( void* dest, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, from, dest, shiftcnt ); }
|
||||||
__noinline void operator()( const ModSibBase& sibdest, const xRegister16& from, u8 shiftcnt ) const { m_16::Emit( sibdest, shiftcnt ); }
|
__forceinline void operator()( const ModSibBase& dest, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, from, dest, shiftcnt ); }
|
||||||
|
|
||||||
DwordShiftImplAll() {} // Why does GCC need these?
|
DwordShiftImplAll() {} // Why does GCC need these?
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,40 +43,40 @@ public:
|
||||||
template< typename T > __forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const
|
template< typename T > __forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
||||||
ModRM_Direct( from.Id, to.Id );
|
EmitSibMagic( from, to );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename T > __forceinline void operator()( const xRegister<T>& to, const void* src ) const
|
template< typename T > __forceinline void operator()( const xRegister<T>& to, const void* src ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
|
||||||
xWriteDisp( to.Id, src );
|
EmitSibMagic( to, src );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename T > __forceinline void operator()( void* dest, const xRegister<T>& from ) const
|
template< typename T > __forceinline void operator()( void* dest, const xRegister<T>& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
||||||
xWriteDisp( from.Id, dest );
|
EmitSibMagic( from, dest );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename T > __noinline void operator()( const ModSibBase& sibdest, const xRegister<T>& from ) const
|
template< typename T > __noinline void operator()( const ModSibBase& sibdest, const xRegister<T>& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
||||||
EmitSibMagic( from.Id, sibdest );
|
EmitSibMagic( from, sibdest );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename T > __noinline void operator()( const xRegister<T>& to, const ModSibBase& sibsrc ) const
|
template< typename T > __noinline void operator()( const xRegister<T>& to, const ModSibBase& sibsrc ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
|
||||||
EmitSibMagic( to.Id, sibsrc );
|
EmitSibMagic( to, sibsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -88,14 +88,14 @@ public:
|
||||||
{
|
{
|
||||||
if( Is8BitOp<T>() )
|
if( Is8BitOp<T>() )
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x80 );
|
xWrite8( 0x80 );
|
||||||
EmitSibMagic( InstType, sibdest );
|
EmitSibMagic( InstType, sibdest );
|
||||||
xWrite<s8>( imm );
|
xWrite<s8>( imm );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( is_s8( imm ) ? 0x83 : 0x81 );
|
xWrite8( is_s8( imm ) ? 0x83 : 0x81 );
|
||||||
EmitSibMagic( InstType, sibdest );
|
EmitSibMagic( InstType, sibdest );
|
||||||
if( is_s8( imm ) )
|
if( is_s8( imm ) )
|
||||||
xWrite<s8>( imm );
|
xWrite<s8>( imm );
|
||||||
|
@ -110,18 +110,18 @@ public:
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
if( !Is8BitOp<T>() && is_s8( imm ) )
|
if( !Is8BitOp<T>() && is_s8( imm ) )
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x83 );
|
xWrite8( 0x83 );
|
||||||
ModRM_Direct( InstType, to.Id );
|
EmitSibMagic( InstType, to );
|
||||||
xWrite<s8>( imm );
|
xWrite<s8>( imm );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( to.IsAccumulator() )
|
if( to.IsAccumulator() )
|
||||||
xWrite<u8>( (Is8BitOp<T>() ? 4 : 5) | (InstType<<3) );
|
xWrite8( (Is8BitOp<T>() ? 4 : 5) | (InstType<<3) );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0x80 : 0x81 );
|
xWrite8( Is8BitOp<T>() ? 0x80 : 0x81 );
|
||||||
ModRM_Direct( InstType, to.Id );
|
EmitSibMagic( InstType, to );
|
||||||
}
|
}
|
||||||
xWrite<T>( imm );
|
xWrite<T>( imm );
|
||||||
}
|
}
|
||||||
|
@ -167,9 +167,9 @@ class xImpl_G1Compare : xImpl_Group1< G1Type_CMP >
|
||||||
protected:
|
protected:
|
||||||
template< u8 Prefix > struct Woot
|
template< u8 Prefix > struct Woot
|
||||||
{
|
{
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, SSE2_ComparisonType cmptype ) const{ xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, SSE2_ComparisonType cmptype ) const{ xOpWrite0F( Prefix, 0xc2, to, from, (u8)cmptype ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const void* from, SSE2_ComparisonType cmptype ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const void* from, SSE2_ComparisonType cmptype ) const { xOpWrite0F( Prefix, 0xc2, to, from, (u8)cmptype ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, SSE2_ComparisonType cmptype ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, SSE2_ComparisonType cmptype ) const { xOpWrite0F( Prefix, 0xc2, to, from, (u8)cmptype ); }
|
||||||
Woot() {}
|
Woot() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,14 @@ public:
|
||||||
template< typename T > __forceinline void operator()( const xRegister<T>& to, __unused const xRegisterCL& from ) const
|
template< typename T > __forceinline void operator()( const xRegister<T>& to, __unused const xRegisterCL& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xd2 : 0xd3 );
|
xWrite8( Is8BitOp<T>() ? 0xd2 : 0xd3 );
|
||||||
ModRM_Direct( InstType, to.Id );
|
EmitSibMagic( InstType, to );
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T > __noinline void operator()( const ModSibStrict<T>& sibdest, __unused const xRegisterCL& from ) const
|
template< typename T > __noinline void operator()( const ModSibStrict<T>& sibdest, __unused const xRegisterCL& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xd2 : 0xd3 );
|
xWrite8( Is8BitOp<T>() ? 0xd2 : 0xd3 );
|
||||||
EmitSibMagic( InstType, sibdest );
|
EmitSibMagic( InstType, sibdest );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +64,14 @@ public:
|
||||||
if( imm == 1 )
|
if( imm == 1 )
|
||||||
{
|
{
|
||||||
// special encoding of 1's
|
// special encoding of 1's
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xd0 : 0xd1 );
|
xWrite8( Is8BitOp<T>() ? 0xd0 : 0xd1 );
|
||||||
EmitSibMagic( InstType, sibdest );
|
EmitSibMagic( InstType, sibdest );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xc0 : 0xc1 );
|
xWrite8( Is8BitOp<T>() ? 0xc0 : 0xc1 );
|
||||||
EmitSibMagic( InstType, sibdest );
|
EmitSibMagic( InstType, sibdest );
|
||||||
xWrite<u8>( imm );
|
xWrite8( imm );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +83,14 @@ public:
|
||||||
if( imm == 1 )
|
if( imm == 1 )
|
||||||
{
|
{
|
||||||
// special encoding of 1's
|
// special encoding of 1's
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xd0 : 0xd1 );
|
xWrite8( Is8BitOp<T>() ? 0xd0 : 0xd1 );
|
||||||
ModRM_Direct( InstType, to.Id );
|
EmitSibMagic( InstType, to );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xc0 : 0xc1 );
|
xWrite8( Is8BitOp<T>() ? 0xc0 : 0xc1 );
|
||||||
ModRM_Direct( InstType, to.Id );
|
EmitSibMagic( InstType, to );
|
||||||
xWrite<u8>( imm );
|
xWrite8( imm );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,136 +34,79 @@ enum G3Type
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
template< G3Type InstType >
|
template< G3Type InstType >
|
||||||
class Group3ImplAll
|
class xImpl_Group3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename T > __forceinline void operator()( const xRegister<T>& from ) const
|
template< typename T > __emitinline void operator()( const xRegister<T>& from ) const
|
||||||
{
|
{
|
||||||
prefix16<T>();
|
prefix16<T>();
|
||||||
xWrite<u8>(Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
xWrite8(Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
||||||
ModRM_Direct( InstType, from.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
template< typename T > __noinline void operator()( const ModSibStrict<T>& from ) const
|
|
||||||
{
|
|
||||||
prefix16<T>();
|
|
||||||
xWrite<u8>( Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
|
||||||
EmitSibMagic( InstType, from );
|
EmitSibMagic( InstType, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
Group3ImplAll() {}
|
// ------------------------------------------------------------------------
|
||||||
|
template< typename T > __emitinline void operator()( const ModSibStrict<T>& from ) const
|
||||||
|
{
|
||||||
|
prefix16<T>();
|
||||||
|
xWrite8( Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
||||||
|
EmitSibMagic( InstType, from );
|
||||||
|
}
|
||||||
|
|
||||||
|
xImpl_Group3() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// This class combines x86 and SSE/SSE2 instructions for iMUL and iDIV.
|
// This class combines x86 and SSE/SSE2 instructions for iMUL and iDIV.
|
||||||
//
|
//
|
||||||
template< G3Type InstType, u16 OpcodeSSE >
|
template< G3Type InstType, u16 OpcodeSSE >
|
||||||
class xImpl_Group3 : public Group3ImplAll<InstType>
|
class ImplMulDivBase : public xImpl_Group3<InstType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ImplMulDivBase() {}
|
||||||
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS;
|
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS;
|
||||||
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD;
|
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD;
|
||||||
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS;
|
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS;
|
||||||
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD;
|
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD;
|
||||||
|
};
|
||||||
|
|
||||||
xImpl_Group3() {}
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
class xImpl_iDiv : public ImplMulDivBase<G3Type_iDIV,0x5e>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ImplMulDivBase<G3Type_iDIV,0x5e>::operator();
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// The following iMul-specific forms are valid for 16 and 32 bit register operands only!
|
// The following iMul-specific forms are valid for 16 and 32 bit register operands only!
|
||||||
|
//
|
||||||
template< typename ImmType >
|
class xImpl_iMul : public ImplMulDivBase<G3Type_iMUL,0x59>
|
||||||
class iMulImpl
|
|
||||||
{
|
{
|
||||||
protected:
|
template< typename T1, typename T2, typename ImmType >
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
static __forceinline void ImmStyle( const T1& param1, const T2& param2, ImmType imm8 )
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
{
|
||||||
|
xOpWrite0F( (sizeof(ImmType) == 2) ? 0x66 : 0, is_s8( imm8 ) ? 0x6b : 0x69, param1, param2 );
|
||||||
|
if( is_s8( imm8 ) )
|
||||||
|
xWrite8( imm8 );
|
||||||
|
else
|
||||||
|
xWrite<ImmType>( imm8 );
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
using ImplMulDivBase<G3Type_iMUL,0x59>::operator();
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const xRegister<ImmType>& from )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write16( 0xaf0f );
|
|
||||||
ModRM_Direct( to.Id, from.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( 0xaf, to, from ); }
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const void* src )
|
__forceinline void operator()( const xRegister32& to, const void* src ) const { xOpWrite0F( 0xaf, to, src ); }
|
||||||
{
|
__forceinline void operator()( const xRegister32& to, const ModSibBase& src ) const { xOpWrite0F( 0xaf, to, src ); }
|
||||||
prefix16();
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from, s32 imm ) const{ ImmStyle( to, from, imm ); }
|
||||||
write16( 0xaf0f );
|
__forceinline void operator()( const xRegister32& to, const ModSibBase& from, s32 imm ) const { ImmStyle( to, from, imm ); }
|
||||||
xWriteDisp( to.Id, src );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, 0xaf, to, from ); }
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const ModSibBase& src )
|
__forceinline void operator()( const xRegister16& to, const void* src ) const { xOpWrite0F( 0x66, 0xaf, to, src ); }
|
||||||
{
|
__forceinline void operator()( const xRegister16& to, const ModSibBase& src ) const { xOpWrite0F( 0x66, 0xaf, to, src ); }
|
||||||
prefix16();
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from, s16 imm ) const{ ImmStyle( to, from, imm ); }
|
||||||
write16( 0xaf0f );
|
__forceinline void operator()( const xRegister16& to, const ModSibBase& from, s16 imm ) const { ImmStyle( to, from, imm ); }
|
||||||
EmitSibMagic( to.Id, src );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const xRegister<ImmType>& from, ImmType imm )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
|
||||||
ModRM_Direct( to.Id, from.Id );
|
|
||||||
if( is_s8( imm ) )
|
|
||||||
write8( imm );
|
|
||||||
else
|
|
||||||
xWrite<ImmType>( imm );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const void* src, ImmType imm )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
|
||||||
xWriteDisp( to.Id, src );
|
|
||||||
if( is_s8( imm ) )
|
|
||||||
write8( imm );
|
|
||||||
else
|
|
||||||
xWrite<ImmType>( imm );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const ModSibBase& src, ImmType imm )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
|
||||||
EmitSibMagic( to.Id, src );
|
|
||||||
if( is_s8( imm ) )
|
|
||||||
write8( imm );
|
|
||||||
else
|
|
||||||
xWrite<ImmType>( imm );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
class xImpl_iMul : public xImpl_Group3<G3Type_iMUL,0x59>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
typedef iMulImpl<u32> iMUL32;
|
|
||||||
typedef iMulImpl<u16> iMUL16;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using xImpl_Group3<G3Type_iMUL,0x59>::operator();
|
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { iMUL32::Emit( to, from ); }
|
|
||||||
__forceinline void operator()( const xRegister32& to, const void* src ) const { iMUL32::Emit( to, src ); }
|
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from, s32 imm ) const{ iMUL32::Emit( to, from, imm ); }
|
|
||||||
__noinline void operator()( const xRegister32& to, const ModSibBase& src ) const { iMUL32::Emit( to, src ); }
|
|
||||||
__noinline void operator()( const xRegister32& to, const ModSibBase& from, s32 imm ) const { iMUL32::Emit( to, from, imm ); }
|
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { iMUL16::Emit( to, from ); }
|
|
||||||
__forceinline void operator()( const xRegister16& to, const void* src ) const { iMUL16::Emit( to, src ); }
|
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from, s16 imm ) const{ iMUL16::Emit( to, from, imm ); }
|
|
||||||
__noinline void operator()( const xRegister16& to, const ModSibBase& src ) const { iMUL16::Emit( to, src ); }
|
|
||||||
__noinline void operator()( const xRegister16& to, const ModSibBase& from, s16 imm ) const { iMUL16::Emit( to, from, imm ); }
|
|
||||||
|
|
||||||
xImpl_iMul() {}
|
xImpl_iMul() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,62 +21,33 @@
|
||||||
// Implementations found here: Increment and Decrement Instructions!
|
// Implementations found here: Increment and Decrement Instructions!
|
||||||
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
//
|
template< bool isDec >
|
||||||
template< typename ImmType >
|
class xImpl_IncDec
|
||||||
class IncDecImpl
|
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
|
||||||
|
|
||||||
static bool Is8BitOperand() { return OperandSize == 1; }
|
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IncDecImpl() {} // For the love of GCC.
|
template< typename T >
|
||||||
|
__forceinline void operator()( const xRegister<T>& to ) const
|
||||||
static __emitinline void Emit( bool isDec, const xRegister<ImmType>& to )
|
|
||||||
{
|
{
|
||||||
// There is no valid 8-bit form of direct register inc/dec, so fall
|
if( Is8BitOp<T>() )
|
||||||
// back on Mod/RM format instead:
|
|
||||||
if (Is8BitOperand() )
|
|
||||||
{
|
{
|
||||||
write8( 0xfe );
|
xWrite8( 0xfe );
|
||||||
ModRM_Direct( isDec ? 1 : 0, to.Id );
|
EmitSibMagic( isDec ? 1 : 0, to );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16<T>();
|
||||||
write8( (isDec ? 0x48 : 0x40) | to.Id );
|
xWrite8( (isDec ? 0x48 : 0x40) | to.Id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static __emitinline void Emit( bool isDec, const ModSibStrict<ImmType>& dest )
|
template< typename T >
|
||||||
|
__forceinline void operator()( const ModSibStrict<T>& sibdest ) const
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16<T>();
|
||||||
write8( Is8BitOperand() ? 0xfe : 0xff );
|
xWrite8( Is8BitOp<T>() ? 0xfe : 0xff );
|
||||||
EmitSibMagic( isDec ? 1 : 0, dest );
|
EmitSibMagic( isDec ? 1 : 0, sibdest );
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
xImpl_IncDec() {} // don't ask.
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
template< bool isDec >
|
|
||||||
class IncDecImplAll
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
typedef IncDecImpl<u32> m_32;
|
|
||||||
typedef IncDecImpl<u16> m_16;
|
|
||||||
typedef IncDecImpl<u8> m_8;
|
|
||||||
|
|
||||||
public:
|
|
||||||
__forceinline void operator()( const xRegister32& to ) const { m_32::Emit( isDec, to ); }
|
|
||||||
__noinline void operator()( const ModSibStrict<u32>& sibdest ) const{ m_32::Emit( isDec, sibdest ); }
|
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister16& to ) const { m_16::Emit( isDec, to ); }
|
|
||||||
__noinline void operator()( const ModSibStrict<u16>& sibdest ) const{ m_16::Emit( isDec, sibdest ); }
|
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister8& to ) const { m_8::Emit( isDec, to ); }
|
|
||||||
__noinline void operator()( const ModSibStrict<u8>& sibdest ) const { m_8::Emit( isDec, sibdest ); }
|
|
||||||
|
|
||||||
IncDecImplAll() {} // don't ask.
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,48 +21,18 @@
|
||||||
// Implementations found here: CALL and JMP! (unconditional only)
|
// Implementations found here: CALL and JMP! (unconditional only)
|
||||||
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
||||||
|
|
||||||
template< typename ImmType >
|
|
||||||
class JmpCallImpl
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
|
||||||
|
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
JmpCallImpl() {} // For the love of GCC.
|
|
||||||
|
|
||||||
static __emitinline void Emit( bool isJmp, const xRegister<ImmType>& absreg )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
xWrite<u8>( 0xff );
|
|
||||||
ModRM_Direct( isJmp ? 4 : 2, absreg.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __emitinline void Emit( bool isJmp, const ModSibStrict<ImmType>& src )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
xWrite<u8>( 0xff );
|
|
||||||
EmitSibMagic( isJmp ? 4 : 2, src );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< bool isJmp >
|
template< bool isJmp >
|
||||||
class JmpCallImplAll
|
class xImpl_JmpCall
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
typedef JmpCallImpl<u32> m_32;
|
|
||||||
typedef JmpCallImpl<u16> m_16;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JmpCallImplAll() {}
|
xImpl_JmpCall() {}
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister32& absreg ) const { m_32::Emit( isJmp, absreg ); }
|
__forceinline void operator()( const xRegister32& absreg ) const { xOpWrite( 0x00, 0xff, isJmp ? 4 : 2, absreg ); }
|
||||||
__forceinline void operator()( const ModSibStrict<u32>& src ) const { m_32::Emit( isJmp, src ); }
|
__forceinline void operator()( const ModSibStrict<u32>& src ) const { xOpWrite( 0x00, 0xff, isJmp ? 4 : 2, src ); }
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister16& absreg ) const { m_16::Emit( isJmp, absreg ); }
|
__forceinline void operator()( const xRegister16& absreg ) const { xOpWrite( 0x66, 0xff, isJmp ? 4 : 2, absreg ); }
|
||||||
__forceinline void operator()( const ModSibStrict<u16>& src ) const { m_16::Emit( isJmp, src ); }
|
__forceinline void operator()( const ModSibStrict<u16>& src ) const { xOpWrite( 0x66, 0xff, isJmp ? 4 : 2, src ); }
|
||||||
|
|
||||||
// Special form for calling functions. This form automatically resolves the
|
// Special form for calling functions. This form automatically resolves the
|
||||||
// correct displacement based on the size of the instruction being generated.
|
// correct displacement based on the size of the instruction being generated.
|
||||||
|
@ -70,16 +40,16 @@ public:
|
||||||
__forceinline void operator()( const T* func ) const
|
__forceinline void operator()( const T* func ) const
|
||||||
{
|
{
|
||||||
if( isJmp )
|
if( isJmp )
|
||||||
iJccKnownTarget( Jcc_Unconditional, (void*)(uptr)func );
|
iJcc( Jcc_Unconditional, (void*)(uptr)func ); // double cast to/from (uptr) needed to appease GCC
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// calls are relative to the instruction after this one, and length is
|
// calls are relative to the instruction after this one, and length is
|
||||||
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
||||||
|
|
||||||
sptr dest = (sptr)func - ((sptr)iGetPtr() + 5);
|
sptr dest = (sptr)func - ((sptr)xGetPtr() + 5);
|
||||||
xWrite<u8>( 0xe8 );
|
xWrite8( 0xe8 );
|
||||||
xWrite<u32>( dest );
|
xWrite32( dest );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class MovImpl
|
||||||
protected:
|
protected:
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
static const uint OperandSize = sizeof(ImmType);
|
||||||
static bool Is8BitOperand() { return OperandSize == 1; }
|
static bool Is8BitOperand() { return OperandSize == 1; }
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
static void prefix16() { if( OperandSize == 2 ) xWrite8( 0x66 ); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MovImpl() {}
|
MovImpl() {}
|
||||||
|
@ -43,8 +43,8 @@ public:
|
||||||
if( to == from ) return; // ignore redundant MOVs.
|
if( to == from ) return; // ignore redundant MOVs.
|
||||||
|
|
||||||
prefix16();
|
prefix16();
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x88 : 0x89 );
|
xWrite8( Is8BitOperand() ? 0x88 : 0x89 );
|
||||||
ModRM_Direct( from.Id, to.Id );
|
EmitSibMagic( from, to );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -57,12 +57,12 @@ public:
|
||||||
|
|
||||||
if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() )
|
if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() )
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xa2 : 0xa3 );
|
xWrite8( Is8BitOperand() ? 0xa2 : 0xa3 );
|
||||||
xWrite<u32>( dest.Displacement );
|
xWrite32( dest.Displacement );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x88 : 0x89 );
|
xWrite8( Is8BitOperand() ? 0x88 : 0x89 );
|
||||||
EmitSibMagic( from.Id, dest );
|
EmitSibMagic( from.Id, dest );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,13 +77,13 @@ public:
|
||||||
|
|
||||||
if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() )
|
if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() )
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xa0 : 0xa1 );
|
xWrite8( Is8BitOperand() ? 0xa0 : 0xa1 );
|
||||||
xWrite<u32>( src.Displacement );
|
xWrite32( src.Displacement );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x8a : 0x8b );
|
xWrite8( Is8BitOperand() ? 0x8a : 0x8b );
|
||||||
EmitSibMagic( to.Id, src );
|
EmitSibMagic( to, src );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,13 +96,13 @@ public:
|
||||||
|
|
||||||
if( from.IsAccumulator() )
|
if( from.IsAccumulator() )
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xa2 : 0xa3 );
|
xWrite8( Is8BitOperand() ? 0xa2 : 0xa3 );
|
||||||
xWrite<s32>( (s32)dest );
|
xWrite<s32>( (s32)dest );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x88 : 0x89 );
|
xWrite8( Is8BitOperand() ? 0x88 : 0x89 );
|
||||||
xWriteDisp( from.Id, dest );
|
EmitSibMagic( from, dest );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,13 +115,13 @@ public:
|
||||||
|
|
||||||
if( to.IsAccumulator() )
|
if( to.IsAccumulator() )
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xa0 : 0xa1 );
|
xWrite8( Is8BitOperand() ? 0xa0 : 0xa1 );
|
||||||
xWrite<s32>( (s32)src );
|
xWrite<s32>( (s32)src );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x8a : 0x8b );
|
xWrite8( Is8BitOperand() ? 0x8a : 0x8b );
|
||||||
xWriteDisp( to.Id, src );
|
EmitSibMagic( to, src );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ public:
|
||||||
// Note: MOV does not have (reg16/32,imm8) forms.
|
// Note: MOV does not have (reg16/32,imm8) forms.
|
||||||
|
|
||||||
prefix16();
|
prefix16();
|
||||||
xWrite<u8>( (Is8BitOperand() ? 0xb0 : 0xb8) | to.Id );
|
xWrite8( (Is8BitOperand() ? 0xb0 : 0xb8) | to.Id );
|
||||||
xWrite<ImmType>( imm );
|
xWrite<ImmType>( imm );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ public:
|
||||||
static __emitinline void Emit( ModSibStrict<ImmType> dest, ImmType imm )
|
static __emitinline void Emit( ModSibStrict<ImmType> dest, ImmType imm )
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16();
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xc6 : 0xc7 );
|
xWrite8( Is8BitOperand() ? 0xc6 : 0xc7 );
|
||||||
EmitSibMagic( 0, dest );
|
EmitSibMagic( 0, dest );
|
||||||
xWrite<ImmType>( imm );
|
xWrite<ImmType>( imm );
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,7 @@ public:
|
||||||
MovImplAll() {} // Satisfy GCC's whims.
|
MovImplAll() {} // Satisfy GCC's whims.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ccSane() jASSUME( ccType >= 0 && ccType <= 0x0f )
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// CMOV !! [in all of it's disappointing lack-of glory] .. and ..
|
// CMOV !! [in all of it's disappointing lack-of glory] .. and ..
|
||||||
|
@ -186,85 +187,19 @@ public:
|
||||||
// CMOV Disclaimer: Caution! This instruction can look exciting and cool, until you
|
// CMOV Disclaimer: Caution! This instruction can look exciting and cool, until you
|
||||||
// realize that it cannot load immediate values into registers. -_-
|
// realize that it cannot load immediate values into registers. -_-
|
||||||
//
|
//
|
||||||
template< typename ImmType, int InstBaseVal >
|
|
||||||
class CMovSetImpl
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
|
||||||
|
|
||||||
static bool Is8BitOperand() { return OperandSize == 1; }
|
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
|
||||||
|
|
||||||
static __forceinline void emit_base( JccComparisonType cc )
|
|
||||||
{
|
|
||||||
jASSUME( cc >= 0 && cc <= 0x0f );
|
|
||||||
prefix16();
|
|
||||||
write8( 0x0f );
|
|
||||||
write8( InstBaseVal | cc );
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMovSetImpl() {}
|
|
||||||
|
|
||||||
static __emitinline void Emit( JccComparisonType cc, const xRegister<ImmType>& to, const xRegister<ImmType>& from )
|
|
||||||
{
|
|
||||||
if( to == from ) return;
|
|
||||||
emit_base( cc );
|
|
||||||
ModRM_Direct( to.Id, from.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __emitinline void Emit( JccComparisonType cc, const xRegister<ImmType>& to, const void* src )
|
|
||||||
{
|
|
||||||
emit_base( cc );
|
|
||||||
xWriteDisp( to.Id, src );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __emitinline void Emit( JccComparisonType cc, const xRegister<ImmType>& to, const ModSibBase& sibsrc )
|
|
||||||
{
|
|
||||||
emit_base( cc );
|
|
||||||
EmitSibMagic( to.Id, sibsrc );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This form is provided for SETcc only (not available in CMOV)
|
|
||||||
static __emitinline void EmitSet( JccComparisonType cc, const xRegister<ImmType>& to )
|
|
||||||
{
|
|
||||||
emit_base( cc );
|
|
||||||
ModRM_Direct( 0, to.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This form is provided for SETcc only (not available in CMOV)
|
|
||||||
static __emitinline void EmitSet( JccComparisonType cc, const void* src )
|
|
||||||
{
|
|
||||||
emit_base( cc );
|
|
||||||
xWriteDisp( 0, src );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This form is provided for SETcc only (not available in CMOV)
|
|
||||||
static __emitinline void EmitSet( JccComparisonType cc, const ModSibStrict<ImmType>& sibsrc )
|
|
||||||
{
|
|
||||||
emit_base( cc );
|
|
||||||
EmitSibMagic( 0, sibsrc );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// I use explicit method declarations here instead of templates, in order to provide
|
// I use explicit method declarations here instead of templates, in order to provide
|
||||||
// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in CMOV).
|
// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in CMOV).
|
||||||
//
|
//
|
||||||
class CMovImplGeneric
|
class CMovImplGeneric
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
typedef CMovSetImpl<u32, 0x40> m_32; // 0x40 is the cmov base instruction id
|
|
||||||
typedef CMovSetImpl<u16, 0x40> m_16; // 0x40 is the cmov base instruction id
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const xRegister32& from ) const { m_32::Emit( ccType, to, from ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const xRegister32& from ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, from ); }
|
||||||
__forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const void* src ) const { m_32::Emit( ccType, to, src ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const void* src ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, src ); }
|
||||||
__noinline void operator()( JccComparisonType ccType, const xRegister32& to, const ModSibBase& sibsrc ) const { m_32::Emit( ccType, to, sibsrc ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, sibsrc ); }
|
||||||
|
|
||||||
__forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const xRegister16& from ) const { m_16::Emit( ccType, to, from ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const xRegister16& from ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, from ); }
|
||||||
__forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const void* src ) const { m_16::Emit( ccType, to, src ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const void* src ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, src ); }
|
||||||
__noinline void operator()( JccComparisonType ccType, const xRegister16& to, const ModSibBase& sibsrc ) const { m_16::Emit( ccType, to, sibsrc ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, sibsrc ); }
|
||||||
|
|
||||||
CMovImplGeneric() {} // don't ask.
|
CMovImplGeneric() {} // don't ask.
|
||||||
};
|
};
|
||||||
|
@ -273,18 +208,16 @@ public:
|
||||||
template< JccComparisonType ccType >
|
template< JccComparisonType ccType >
|
||||||
class CMovImplAll
|
class CMovImplAll
|
||||||
{
|
{
|
||||||
protected:
|
static const u16 Opcode = 0x40 | ccType;
|
||||||
typedef CMovSetImpl<u32, 0x40> m_32;
|
|
||||||
typedef CMovSetImpl<u16, 0x40> m_16;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { m_32::Emit( ccType, to, from ); }
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { ccSane(); xOpWrite0F( Opcode, to, from ); }
|
||||||
__forceinline void operator()( const xRegister32& to, const void* src ) const { m_32::Emit( ccType, to, src ); }
|
__forceinline void operator()( const xRegister32& to, const void* src ) const { ccSane(); xOpWrite0F( Opcode, to, src ); }
|
||||||
__noinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { m_32::Emit( ccType, to, sibsrc ); }
|
__forceinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( Opcode, to, sibsrc ); }
|
||||||
|
|
||||||
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { m_16::Emit( ccType, to, from ); }
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, from ); }
|
||||||
__forceinline void operator()( const xRegister16& to, const void* src ) const { m_16::Emit( ccType, to, src ); }
|
__forceinline void operator()( const xRegister16& to, const void* src ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, src ); }
|
||||||
__noinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { m_16::Emit( ccType, to, sibsrc ); }
|
__forceinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, sibsrc ); }
|
||||||
|
|
||||||
CMovImplAll() {} // don't ask.
|
CMovImplAll() {} // don't ask.
|
||||||
};
|
};
|
||||||
|
@ -292,13 +225,11 @@ public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
class SetImplGeneric
|
class SetImplGeneric
|
||||||
{
|
{
|
||||||
protected:
|
// note: SETcc are 0x90, with 0 in the Reg field of ModRM.
|
||||||
typedef CMovSetImpl<u8, 0x90> Impl; // 0x90 is the SETcc base instruction id
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__forceinline void operator()( JccComparisonType cc, const xRegister8& to ) const { Impl::EmitSet( cc, to ); }
|
__forceinline void operator()( JccComparisonType ccType, const xRegister8& to ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, to ); }
|
||||||
__forceinline void operator()( JccComparisonType cc, void* dest ) const { Impl::EmitSet( cc, dest ); }
|
__forceinline void operator()( JccComparisonType ccType, void* dest ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, dest ); }
|
||||||
__noinline void operator()( JccComparisonType cc, const ModSibStrict<u8>& dest ) const { Impl::EmitSet( cc, dest ); }
|
__noinline void operator()( JccComparisonType ccType, const ModSibStrict<u8>& dest ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, dest ); }
|
||||||
|
|
||||||
SetImplGeneric() {} // if you do, ask GCC.
|
SetImplGeneric() {} // if you do, ask GCC.
|
||||||
};
|
};
|
||||||
|
@ -307,13 +238,12 @@ public:
|
||||||
template< JccComparisonType ccType >
|
template< JccComparisonType ccType >
|
||||||
class SetImplAll
|
class SetImplAll
|
||||||
{
|
{
|
||||||
protected:
|
static const u16 Opcode = 0x90 | ccType; // SETcc are 0x90 base opcode, with 0 in the Reg field of ModRM.
|
||||||
typedef CMovSetImpl<u8, 0x90> Impl; // 0x90 is the SETcc base instruction id
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
__forceinline void operator()( const xRegister8& to ) const { Impl::EmitSet( ccType, to ); }
|
__forceinline void operator()( const xRegister8& to ) const { ccSane(); xOpWrite0F( Opcode, 0, to ); }
|
||||||
__forceinline void operator()( void* dest ) const { Impl::EmitSet( ccType, dest ); }
|
__forceinline void operator()( void* dest ) const { ccSane(); xOpWrite0F( Opcode, 0, dest ); }
|
||||||
__noinline void operator()( const ModSibStrict<u8>& dest ) const { Impl::EmitSet( ccType, dest ); }
|
__noinline void operator()( const ModSibStrict<u8>& dest ) const { ccSane(); xOpWrite0F( Opcode, 0, dest ); }
|
||||||
|
|
||||||
SetImplAll() {} // if you do, ask GCC.
|
SetImplAll() {} // if you do, ask GCC.
|
||||||
};
|
};
|
||||||
|
@ -330,12 +260,12 @@ protected:
|
||||||
static const uint SrcOperandSize = sizeof( SrcImmType );
|
static const uint SrcOperandSize = sizeof( SrcImmType );
|
||||||
|
|
||||||
static bool Is8BitOperand() { return SrcOperandSize == 1; }
|
static bool Is8BitOperand() { return SrcOperandSize == 1; }
|
||||||
static void prefix16() { if( DestOperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
static void prefix16() { if( DestOperandSize == 2 ) xWrite8( 0x66 ); }
|
||||||
static __forceinline void emit_base( bool SignExtend )
|
static __forceinline void emit_base( bool SignExtend )
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16();
|
||||||
xWrite<u8>( 0x0f );
|
xWrite8( 0x0f );
|
||||||
xWrite<u8>( 0xb6 | (Is8BitOperand() ? 0 : 1) | (SignExtend ? 8 : 0 ) );
|
xWrite8( 0xb6 | (Is8BitOperand() ? 0 : 1) | (SignExtend ? 8 : 0 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -344,13 +274,13 @@ public:
|
||||||
static __emitinline void Emit( const xRegister<DestImmType>& to, const xRegister<SrcImmType>& from, bool SignExtend )
|
static __emitinline void Emit( const xRegister<DestImmType>& to, const xRegister<SrcImmType>& from, bool SignExtend )
|
||||||
{
|
{
|
||||||
emit_base( SignExtend );
|
emit_base( SignExtend );
|
||||||
ModRM_Direct( to.Id, from.Id );
|
EmitSibMagic( to, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
static __emitinline void Emit( const xRegister<DestImmType>& to, const ModSibStrict<SrcImmType>& sibsrc, bool SignExtend )
|
static __emitinline void Emit( const xRegister<DestImmType>& to, const ModSibStrict<SrcImmType>& sibsrc, bool SignExtend )
|
||||||
{
|
{
|
||||||
emit_base( SignExtend );
|
emit_base( SignExtend );
|
||||||
EmitSibMagic( to.Id, sibsrc );
|
EmitSibMagic( to, sibsrc );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,66 +18,93 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// Implementations found here: TEST + BTS/BT/BTC/BTR + BSF/BSR! (for lack of better location)
|
||||||
|
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// TEST instruction Implementation
|
// TEST instruction Implementation
|
||||||
|
//
|
||||||
template< typename ImmType >
|
class xImpl_Test
|
||||||
class TestImpl
|
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
static const uint OperandSize = sizeof(ImmType);
|
|
||||||
static bool Is8BitOperand() { return OperandSize == 1; }
|
|
||||||
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TestImpl() {}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, const xRegister<ImmType>& from )
|
template< typename T > __forceinline
|
||||||
|
void operator()( const xRegister<T>& to, const xRegister<T>& from ) const
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16<T>();
|
||||||
xWrite<u8>( Is8BitOperand() ? 0x84 : 0x85 );
|
xWrite8( Is8BitOp<T>() ? 0x84 : 0x85 );
|
||||||
ModRM_Direct( from.Id, to.Id );
|
EmitSibMagic( from, to );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static __emitinline void Emit( const xRegister<ImmType>& to, ImmType imm )
|
template< typename T > __forceinline
|
||||||
|
void operator()( const ModSibStrict<T>& dest, int imm ) const
|
||||||
{
|
{
|
||||||
prefix16();
|
prefix16<T>();
|
||||||
|
xWrite8( Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
||||||
|
EmitSibMagic( 0, dest );
|
||||||
|
xWrite<T>( imm );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
template< typename T > __forceinline
|
||||||
|
void operator()( const xRegister<T>& to, int imm ) const
|
||||||
|
{
|
||||||
|
prefix16<T>();
|
||||||
|
|
||||||
if( to.IsAccumulator() )
|
if( to.IsAccumulator() )
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xa8 : 0xa9 );
|
xWrite8( Is8BitOp<T>() ? 0xa8 : 0xa9 );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xf6 : 0xf7 );
|
xWrite8( Is8BitOp<T>() ? 0xf6 : 0xf7 );
|
||||||
ModRM_Direct( 0, to.Id );
|
EmitSibMagic( 0, to );
|
||||||
}
|
}
|
||||||
xWrite<ImmType>( imm );
|
xWrite<T>( imm );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
xImpl_Test() {} // Why does GCC need these?
|
||||||
static __emitinline void Emit( ModSibStrict<ImmType> dest, ImmType imm )
|
|
||||||
{
|
|
||||||
prefix16();
|
|
||||||
xWrite<u8>( Is8BitOperand() ? 0xf6 : 0xf7 );
|
|
||||||
EmitSibMagic( 0, dest );
|
|
||||||
xWrite<ImmType>( imm );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
enum G8Type
|
||||||
|
{
|
||||||
|
G8Type_BT = 4,
|
||||||
|
G8Type_BTS,
|
||||||
|
G8Type_BTR,
|
||||||
|
G8Type_BTC,
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// BSF / BSR -- 16/32 operands supported only.
|
||||||
//
|
//
|
||||||
class TestImplAll
|
// 0xbc [fwd] / 0xbd [rev]
|
||||||
|
//
|
||||||
|
template< u16 Opcode >
|
||||||
|
class xImpl_BitScan
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template< typename T >
|
xImpl_BitScan() {}
|
||||||
__forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const { TestImpl<T>::Emit( to, from ); }
|
|
||||||
|
|
||||||
template< typename T >
|
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( Opcode, to, from ); }
|
||||||
__noinline void operator()( const ModSibStrict<T>& sibdest, T imm ) const { TestImpl<T>::Emit( sibdest, imm ); }
|
__forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, Opcode, to, from ); }
|
||||||
template< typename T >
|
__forceinline void operator()( const xRegister32& to, const void* src ) const { xOpWrite0F( Opcode, to, src ); }
|
||||||
void operator()( const xRegister<T>& to, T imm ) const { TestImpl<T>::Emit( to, imm ); }
|
__forceinline void operator()( const xRegister16& to, const void* src ) const { xOpWrite0F( 0x66, Opcode, to, src ); }
|
||||||
|
__forceinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { xOpWrite0F( Opcode, to, sibsrc ); }
|
||||||
TestImplAll() {} // Why does GCC need these?
|
__forceinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { xOpWrite0F( 0x66, Opcode, to, sibsrc ); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Bit Test Instructions - Valid on 16/32 bit instructions only.
|
||||||
|
//
|
||||||
|
template< G8Type InstType >
|
||||||
|
class xImpl_Group8 : public xImpl_BitScan<0xa3 | (InstType << 2)>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using xImpl_BitScan<0xa3 | (InstType << 2)>::operator();
|
||||||
|
|
||||||
|
__forceinline void operator()( const ModSibStrict<u32>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase, bitoffset ); }
|
||||||
|
__forceinline void operator()( const ModSibStrict<u16>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase, bitoffset ); }
|
||||||
|
void operator()( const xRegister<u32>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase, bitoffset ); }
|
||||||
|
void operator()( const xRegister<u16>& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase, bitoffset ); }
|
||||||
|
|
||||||
|
xImpl_Group8() {}
|
||||||
|
};
|
||||||
|
|
|
@ -40,15 +40,15 @@ public:
|
||||||
__emitinline void operator()( const xRegisterSSE& to, u8 imm8 ) const
|
__emitinline void operator()( const xRegisterSSE& to, u8 imm8 ) const
|
||||||
{
|
{
|
||||||
SimdPrefix( 0x66, OpcodeImm );
|
SimdPrefix( 0x66, OpcodeImm );
|
||||||
ModRM( 3, (int)Modcode, to.Id );
|
EmitSibMagic( (int)Modcode, to );
|
||||||
xWrite<u8>( imm8 );
|
xWrite8( imm8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
__emitinline void operator()( const xRegisterMMX& to, u8 imm8 ) const
|
__emitinline void operator()( const xRegisterMMX& to, u8 imm8 ) const
|
||||||
{
|
{
|
||||||
SimdPrefix( 0x00, OpcodeImm );
|
SimdPrefix( 0x00, OpcodeImm );
|
||||||
ModRM( 3, (int)Modcode, to.Id );
|
EmitSibMagic( (int)Modcode, to );
|
||||||
xWrite<u8>( imm8 );
|
xWrite8( imm8 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ public:
|
||||||
{
|
{
|
||||||
SimdPrefix( 0x66, 0x73 );
|
SimdPrefix( 0x66, 0x73 );
|
||||||
ModRM( 3, (int)Modcode+1, to.Id );
|
ModRM( 3, (int)Modcode+1, to.Id );
|
||||||
xWrite<u8>( imm8 );
|
xWrite8( imm8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdImpl_Shift() {}
|
SimdImpl_Shift() {}
|
||||||
|
|
|
@ -21,110 +21,6 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// MMX / SSE Helper Functions!
|
// MMX / SSE Helper Functions!
|
||||||
|
|
||||||
extern void SimdPrefix( u8 prefix, u16 opcode );
|
|
||||||
|
|
||||||
extern void xOpWrite0F( u8 prefix, u16 opcode, int instId, const ModSibBase& sib );
|
|
||||||
extern void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data );
|
|
||||||
extern void xOpWrite0F( u16 opcode, int instId, const ModSibBase& sib );
|
|
||||||
extern void xOpWrite0F( u16 opcode, int instId, const void* data );
|
|
||||||
|
|
||||||
template< typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, int instId, const xRegister<T2>& from )
|
|
||||||
{
|
|
||||||
SimdPrefix( prefix, opcode );
|
|
||||||
ModRM_Direct( instId, from.Id );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, int instId, const xRegister<T2>& from )
|
|
||||||
{
|
|
||||||
xOpWrite0F( 0, opcode, instId, from );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& to, const xRegister<T2>& from, bool forcePrefix=false )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, to.Id, from );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __noinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& reg, const ModSibBase& sib, bool forcePrefix=false )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, reg.Id, sib );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& reg, const void* data, bool forcePrefix=false )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, reg.Id, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
template< typename T, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& to, const xRegister<T2>& from, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, to, from );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __noinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& reg, const ModSibBase& sib, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, reg, sib );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const xRegister<T>& reg, const void* data, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, reg, data );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template< typename T, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& to, const xRegister<T2>& from )
|
|
||||||
{
|
|
||||||
xOpWrite0F( 0, opcode, to, from );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __noinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& reg, const ModSibBase& sib )
|
|
||||||
{
|
|
||||||
xOpWrite0F( 0, opcode, reg, sib );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& reg, const void* data )
|
|
||||||
{
|
|
||||||
xOpWrite0F( 0, opcode, reg, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template< typename T, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& to, const xRegister<T2>& from, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( opcode, to, from );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __noinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& reg, const ModSibBase& sib, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( opcode, reg, sib );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const xRegister<T>& reg, const void* data, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( opcode, reg, data );
|
|
||||||
xWrite<u8>( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// For implementing SSE-only logic operations that have xmmreg,xmmreg/rm forms only,
|
// For implementing SSE-only logic operations that have xmmreg,xmmreg/rm forms only,
|
||||||
// like ANDPS/ANDPD
|
// like ANDPS/ANDPD
|
||||||
|
|
|
@ -41,9 +41,9 @@ class SimdImpl_Compare
|
||||||
protected:
|
protected:
|
||||||
template< u8 Prefix > struct Woot
|
template< u8 Prefix > struct Woot
|
||||||
{
|
{
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( CType ); }
|
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( CType ); }
|
__forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite<u8>( CType ); }
|
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); }
|
||||||
Woot() {}
|
Woot() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -122,17 +122,17 @@ public:
|
||||||
{
|
{
|
||||||
if( to != from ) xOpWrite0F( PrefixA, Opcode, to, from );
|
if( to != from ) xOpWrite0F( PrefixA, Opcode, to, from );
|
||||||
}
|
}
|
||||||
#ifndef __LINUX__ // Ifdef till Jake fixes; you can't use & on a const void*!
|
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const void* from ) const
|
__forceinline void operator()( const xRegisterSSE& to, const void* from ) const
|
||||||
{
|
{
|
||||||
xOpWrite0F( (isAligned || (from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode, to, from );
|
xOpWrite0F( (isAligned || ((uptr)from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode, to, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void operator()( const void* to, const xRegisterSSE& from ) const
|
__forceinline void operator()( const void* to, const xRegisterSSE& from ) const
|
||||||
{
|
{
|
||||||
xOpWrite0F( (isAligned || (from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode_Alt, to, from );
|
xOpWrite0F( (isAligned || ((uptr)from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode_Alt, to, from );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const
|
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const
|
||||||
{
|
{
|
||||||
// ModSib form is aligned if it's displacement-only and the displacement is aligned:
|
// ModSib form is aligned if it's displacement-only and the displacement is aligned:
|
||||||
|
@ -140,14 +140,12 @@ public:
|
||||||
xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode, to, from );
|
xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode, to, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __LINUX__ // II'll ifdef this one, too. xOpWrite0F doesn't take ModSibBase & xRegisterSSE in that order.
|
|
||||||
__forceinline void operator()( const ModSibBase& to, const xRegisterSSE& from ) const
|
__forceinline void operator()( const ModSibBase& to, const xRegisterSSE& from ) const
|
||||||
{
|
{
|
||||||
// ModSib form is aligned if it's displacement-only and the displacement is aligned:
|
// ModSib form is aligned if it's displacement-only and the displacement is aligned:
|
||||||
bool isReallyAligned = isAligned || ( (to.Displacement & 0x0f) == 0 && to.Index.IsEmpty() && to.Base.IsEmpty() );
|
bool isReallyAligned = isAligned || ( (to.Displacement & 0x0f) == 0 && to.Index.IsEmpty() && to.Base.IsEmpty() );
|
||||||
xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode_Alt, to, from );
|
xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode_Alt, from, to );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ class SimdImpl_Shuffle
|
||||||
protected:
|
protected:
|
||||||
template< u8 Prefix > struct Woot
|
template< u8 Prefix > struct Woot
|
||||||
{
|
{
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const void* from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const void* from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite<u8>( cmptype ); }
|
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); }
|
||||||
Woot() {}
|
Woot() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,26 @@ __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM] = { XMMT_INT };
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter {
|
||||||
|
|
||||||
|
__forceinline void xWrite8( u8 val )
|
||||||
|
{
|
||||||
|
xWrite( val );
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline void xWrite16( u16 val )
|
||||||
|
{
|
||||||
|
xWrite( val );
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline void xWrite32( u32 val )
|
||||||
|
{
|
||||||
|
xWrite( val );
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline void xWrite64( u64 val )
|
||||||
|
{
|
||||||
|
xWrite( val );
|
||||||
|
}
|
||||||
|
|
||||||
const xAddressIndexerBase ptr;
|
const xAddressIndexerBase ptr;
|
||||||
const xAddressIndexer<u128> ptr128;
|
const xAddressIndexer<u128> ptr128;
|
||||||
const xAddressIndexer<u64> ptr64;
|
const xAddressIndexer<u64> ptr64;
|
||||||
|
@ -75,7 +95,7 @@ const xAddressIndexer<u8> ptr8;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename OperandType > const xRegister<OperandType> xRegister<OperandType>::Empty;
|
template< typename OperandType > const xRegisterBase<OperandType> xRegisterBase<OperandType>::Empty;
|
||||||
const xAddressReg xAddressReg::Empty;
|
const xAddressReg xAddressReg::Empty;
|
||||||
|
|
||||||
const xRegisterSSE
|
const xRegisterSSE
|
||||||
|
@ -110,8 +130,11 @@ const xRegister8
|
||||||
|
|
||||||
const xRegisterCL cl;
|
const xRegisterCL cl;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Performance note: VC++ wants to use byte/word register form for the following
|
// Performance note: VC++ wants to use byte/word register form for the following
|
||||||
// ModRM/SibSB constructors when we use xWrite<u8>, and furthermore unrolls the
|
// ModRM/SibSB constructors when we use xWrite<u8>, and furthermore unrolls the
|
||||||
// the shift using a series of ADDs for the following results:
|
// the shift using a series of ADDs for the following results:
|
||||||
|
@ -135,30 +158,20 @@ namespace Internal
|
||||||
// (btw, I know this isn't a critical performance item by any means, but it's
|
// (btw, I know this isn't a critical performance item by any means, but it's
|
||||||
// annoying simply because it *should* be an easy thing to optimize)
|
// annoying simply because it *should* be an easy thing to optimize)
|
||||||
|
|
||||||
__forceinline void ModRM( uint mod, uint reg, uint rm )
|
static __forceinline void ModRM( uint mod, uint reg, uint rm )
|
||||||
{
|
{
|
||||||
xWrite<u8>( (mod << 6) | (reg << 3) | rm );
|
xWrite8( (mod << 6) | (reg << 3) | rm );
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void ModRM_Direct( uint reg, uint rm )
|
static __forceinline void SibSB( u32 ss, u32 index, u32 base )
|
||||||
{
|
{
|
||||||
ModRM( Mod_Direct, reg, rm );
|
xWrite8( (ss << 6) | (index << 3) | base );
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void SibSB( u32 ss, u32 index, u32 base )
|
__forceinline void EmitSibMagic( uint regfield, const void* address )
|
||||||
{
|
|
||||||
xWrite<u8>( (ss << 6) | (index << 3) | base );
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void xWriteDisp( int regfield, s32 displacement )
|
|
||||||
{
|
{
|
||||||
ModRM( 0, regfield, ModRm_UseDisp32 );
|
ModRM( 0, regfield, ModRm_UseDisp32 );
|
||||||
xWrite<s32>( displacement );
|
xWrite<s32>( (s32)address );
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void xWriteDisp( int regfield, const void* address )
|
|
||||||
{
|
|
||||||
xWriteDisp( regfield, (s32)address );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -180,7 +193,7 @@ namespace Internal
|
||||||
__emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data )
|
__emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data )
|
||||||
{
|
{
|
||||||
SimdPrefix( prefix, opcode );
|
SimdPrefix( prefix, opcode );
|
||||||
xWriteDisp( instId, data );
|
EmitSibMagic( instId, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
__emitinline void xOpWrite0F( u16 opcode, int instId, const ModSibBase& sib )
|
__emitinline void xOpWrite0F( u16 opcode, int instId, const ModSibBase& sib )
|
||||||
|
@ -219,7 +232,7 @@ namespace Internal
|
||||||
// regfield - register field to be written to the ModRm. This is either a register specifier
|
// regfield - register field to be written to the ModRm. This is either a register specifier
|
||||||
// or an opcode extension. In either case, the instruction determines the value for us.
|
// or an opcode extension. In either case, the instruction determines the value for us.
|
||||||
//
|
//
|
||||||
void EmitSibMagic( uint regfield, const ModSibBase& info )
|
__noinline void EmitSibMagic( uint regfield, const ModSibBase& info )
|
||||||
{
|
{
|
||||||
jASSUME( regfield < 8 );
|
jASSUME( regfield < 8 );
|
||||||
|
|
||||||
|
@ -235,7 +248,7 @@ namespace Internal
|
||||||
|
|
||||||
if( info.Index.IsEmpty() )
|
if( info.Index.IsEmpty() )
|
||||||
{
|
{
|
||||||
xWriteDisp( regfield, info.Displacement );
|
EmitSibMagic( regfield, (void*)info.Displacement );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -284,7 +297,7 @@ namespace Internal
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
const MovImplAll xMOV;
|
const MovImplAll xMOV;
|
||||||
const TestImplAll xTEST;
|
const xImpl_Test xTEST;
|
||||||
|
|
||||||
const xImpl_G1Logic<G1Type_AND,0x54> xAND;
|
const xImpl_G1Logic<G1Type_AND,0x54> xAND;
|
||||||
const xImpl_G1Logic<G1Type_OR,0x56> xOR;
|
const xImpl_G1Logic<G1Type_OR,0x56> xOR;
|
||||||
|
@ -305,15 +318,15 @@ const Group2ImplAll<G2Type_SHL> xSHL;
|
||||||
const Group2ImplAll<G2Type_SHR> xSHR;
|
const Group2ImplAll<G2Type_SHR> xSHR;
|
||||||
const Group2ImplAll<G2Type_SAR> xSAR;
|
const Group2ImplAll<G2Type_SAR> xSAR;
|
||||||
|
|
||||||
const Group3ImplAll<G3Type_NOT> xNOT;
|
const xImpl_Group3<G3Type_NOT> xNOT;
|
||||||
const Group3ImplAll<G3Type_NEG> xNEG;
|
const xImpl_Group3<G3Type_NEG> xNEG;
|
||||||
const Group3ImplAll<G3Type_MUL> xUMUL;
|
const xImpl_Group3<G3Type_MUL> xUMUL;
|
||||||
const Group3ImplAll<G3Type_DIV> xUDIV;
|
const xImpl_Group3<G3Type_DIV> xUDIV;
|
||||||
const xImpl_Group3<G3Type_iDIV,0x5e> xDIV;
|
const xImpl_iDiv xDIV;
|
||||||
const xImpl_iMul xMUL;
|
const xImpl_iMul xMUL;
|
||||||
|
|
||||||
const IncDecImplAll<false> xINC;
|
const xImpl_IncDec<false> xINC;
|
||||||
const IncDecImplAll<true> xDEC;
|
const xImpl_IncDec<true> xDEC;
|
||||||
|
|
||||||
const MovExtendImplAll<false> xMOVZX;
|
const MovExtendImplAll<false> xMOVZX;
|
||||||
const MovExtendImplAll<true> xMOVSX;
|
const MovExtendImplAll<true> xMOVSX;
|
||||||
|
@ -321,13 +334,13 @@ const MovExtendImplAll<true> xMOVSX;
|
||||||
const DwordShiftImplAll<false> xSHLD;
|
const DwordShiftImplAll<false> xSHLD;
|
||||||
const DwordShiftImplAll<true> xSHRD;
|
const DwordShiftImplAll<true> xSHRD;
|
||||||
|
|
||||||
const Group8Impl<G8Type_BT> xBT;
|
const xImpl_Group8<G8Type_BT> xBT;
|
||||||
const Group8Impl<G8Type_BTR> xBTR;
|
const xImpl_Group8<G8Type_BTR> xBTR;
|
||||||
const Group8Impl<G8Type_BTS> xBTS;
|
const xImpl_Group8<G8Type_BTS> xBTS;
|
||||||
const Group8Impl<G8Type_BTC> xBTC;
|
const xImpl_Group8<G8Type_BTC> xBTC;
|
||||||
|
|
||||||
const BitScanImpl<0xbc> xBSF;
|
const xImpl_BitScan<0xbc> xBSF;
|
||||||
const BitScanImpl<0xbd> xBSR;
|
const xImpl_BitScan<0xbd> xBSR;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
const CMovImplGeneric xCMOV;
|
const CMovImplGeneric xCMOV;
|
||||||
|
@ -390,7 +403,7 @@ const SetImplAll<Jcc_ParityOdd> xSETPO;
|
||||||
// Assigns the current emitter buffer target address.
|
// Assigns the current emitter buffer target address.
|
||||||
// This is provided instead of using x86Ptr directly, since we may in the future find
|
// This is provided instead of using x86Ptr directly, since we may in the future find
|
||||||
// a need to change the storage class system for the x86Ptr 'under the hood.'
|
// a need to change the storage class system for the x86Ptr 'under the hood.'
|
||||||
__emitinline void iSetPtr( void* ptr )
|
__emitinline void xSetPtr( void* ptr )
|
||||||
{
|
{
|
||||||
x86Ptr = (u8*)ptr;
|
x86Ptr = (u8*)ptr;
|
||||||
}
|
}
|
||||||
|
@ -399,26 +412,26 @@ __emitinline void iSetPtr( void* ptr )
|
||||||
// Retrieves the current emitter buffer target address.
|
// Retrieves the current emitter buffer target address.
|
||||||
// This is provided instead of using x86Ptr directly, since we may in the future find
|
// This is provided instead of using x86Ptr directly, since we may in the future find
|
||||||
// a need to change the storage class system for the x86Ptr 'under the hood.'
|
// a need to change the storage class system for the x86Ptr 'under the hood.'
|
||||||
__emitinline u8* iGetPtr()
|
__emitinline u8* xGetPtr()
|
||||||
{
|
{
|
||||||
return x86Ptr;
|
return x86Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
__emitinline void iAlignPtr( uint bytes )
|
__emitinline void xAlignPtr( uint bytes )
|
||||||
{
|
{
|
||||||
// forward align
|
// forward align
|
||||||
x86Ptr = (u8*)( ( (uptr)x86Ptr + bytes - 1) & ~(bytes - 1) );
|
x86Ptr = (u8*)( ( (uptr)x86Ptr + bytes - 1) & ~(bytes - 1) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
__emitinline void iAdvancePtr( uint bytes )
|
__emitinline void xAdvancePtr( uint bytes )
|
||||||
{
|
{
|
||||||
if( IsDevBuild )
|
if( IsDevBuild )
|
||||||
{
|
{
|
||||||
// common debugger courtesy: advance with INT3 as filler.
|
// common debugger courtesy: advance with INT3 as filler.
|
||||||
for( uint i=0; i<bytes; i++ )
|
for( uint i=0; i<bytes; i++ )
|
||||||
xWrite<u8>( 0xcc );
|
xWrite8( 0xcc );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
x86Ptr += bytes;
|
x86Ptr += bytes;
|
||||||
|
@ -553,7 +566,7 @@ static void EmitLeaMagic( xRegister<OperandType> to, const ModSibBase& src, bool
|
||||||
// note: no need to do ebp+0 check since we encode all 0 displacements as
|
// note: no need to do ebp+0 check since we encode all 0 displacements as
|
||||||
// register assignments above (via MOV)
|
// register assignments above (via MOV)
|
||||||
|
|
||||||
xWrite<u8>( 0x8d );
|
xWrite8( 0x8d );
|
||||||
ModRM( displacement_size, to.Id, src.Index.Id );
|
ModRM( displacement_size, to.Id, src.Index.Id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,10 +588,10 @@ static void EmitLeaMagic( xRegister<OperandType> to, const ModSibBase& src, bool
|
||||||
xSHL( to, src.Scale );
|
xSHL( to, src.Scale );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xWrite<u8>( 0x8d );
|
xWrite8( 0x8d );
|
||||||
ModRM( 0, to.Id, ModRm_UseSib );
|
ModRM( 0, to.Id, ModRm_UseSib );
|
||||||
SibSB( src.Scale, src.Index.Id, ModRm_UseDisp32 );
|
SibSB( src.Scale, src.Index.Id, ModRm_UseDisp32 );
|
||||||
xWrite<u32>( src.Displacement );
|
xWrite32( src.Displacement );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -614,7 +627,7 @@ static void EmitLeaMagic( xRegister<OperandType> to, const ModSibBase& src, bool
|
||||||
if( src.Base == ebp && displacement_size == 0 )
|
if( src.Base == ebp && displacement_size == 0 )
|
||||||
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
|
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
|
||||||
|
|
||||||
xWrite<u8>( 0x8d );
|
xWrite8( 0x8d );
|
||||||
ModRM( displacement_size, to.Id, ModRm_UseSib );
|
ModRM( displacement_size, to.Id, ModRm_UseSib );
|
||||||
SibSB( src.Scale, src.Index.Id, src.Base.Id );
|
SibSB( src.Scale, src.Index.Id, src.Base.Id );
|
||||||
}
|
}
|
||||||
|
@ -637,7 +650,7 @@ __emitinline void xLEA( xRegister32 to, const ModSibBase& src, bool preserve_fla
|
||||||
|
|
||||||
__emitinline void xLEA( xRegister16 to, const ModSibBase& src, bool preserve_flags )
|
__emitinline void xLEA( xRegister16 to, const ModSibBase& src, bool preserve_flags )
|
||||||
{
|
{
|
||||||
write8( 0x66 );
|
xWrite8( 0x66 );
|
||||||
EmitLeaMagic( to, src, preserve_flags );
|
EmitLeaMagic( to, src, preserve_flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,22 +663,51 @@ __emitinline void xLEA( xRegister16 to, const ModSibBase& src, bool preserve_fla
|
||||||
|
|
||||||
__emitinline void xPOP( const ModSibBase& from )
|
__emitinline void xPOP( const ModSibBase& from )
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x8f );
|
xWrite8( 0x8f );
|
||||||
EmitSibMagic( 0, from );
|
EmitSibMagic( 0, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
__emitinline void xPUSH( const ModSibBase& from )
|
__emitinline void xPUSH( const ModSibBase& from )
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0xff );
|
xWrite8( 0xff );
|
||||||
EmitSibMagic( 6, from );
|
EmitSibMagic( 6, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__forceinline void xPOP( xRegister32 from ) { xWrite8( 0x58 | from.Id ); }
|
||||||
|
__forceinline void xPOP( void* from ) { xPOP( ptr[from] ); }
|
||||||
|
|
||||||
|
__forceinline void xPUSH( u32 imm ) { xWrite8( 0x68 ); xWrite32( imm ); }
|
||||||
|
__forceinline void xPUSH( xRegister32 from ) { xWrite8( 0x50 | from.Id ); }
|
||||||
|
__forceinline void xPUSH( void* from ) { xPUSH( ptr[from] ); }
|
||||||
|
|
||||||
|
// pushes the EFLAGS register onto the stack
|
||||||
|
__forceinline void xPUSHFD() { xWrite8( 0x9C ); }
|
||||||
|
// pops the EFLAGS register from the stack
|
||||||
|
__forceinline void xPOPFD() { xWrite8( 0x9D ); }
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
|
__forceinline void xRET() { xWrite8( 0xC3 ); }
|
||||||
|
__forceinline void xCBW() { xWrite16( 0x9866 ); }
|
||||||
|
__forceinline void xCWD() { xWrite8( 0x98 ); }
|
||||||
|
__forceinline void xCDQ() { xWrite8( 0x99 ); }
|
||||||
|
__forceinline void xCWDE() { xWrite8( 0x98 ); }
|
||||||
|
|
||||||
|
__forceinline void xLAHF() { xWrite8( 0x9f ); }
|
||||||
|
__forceinline void xSAHF() { xWrite8( 0x9e ); }
|
||||||
|
|
||||||
|
__forceinline void xSTC() { xWrite8( 0xF9 ); }
|
||||||
|
__forceinline void xCLC() { xWrite8( 0xF8 ); }
|
||||||
|
|
||||||
|
// NOP 1-byte
|
||||||
|
__forceinline void xNOP() { xWrite8(0x90); }
|
||||||
|
|
||||||
__emitinline void xBSWAP( const xRegister32& to )
|
__emitinline void xBSWAP( const xRegister32& to )
|
||||||
{
|
{
|
||||||
write8( 0x0F );
|
xWrite8( 0x0F );
|
||||||
write8( 0xC8 | to.Id );
|
xWrite8( 0xC8 | to.Id );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,183 +20,183 @@
|
||||||
#include "ix86_legacy_internal.h"
|
#include "ix86_legacy_internal.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// 3DNOW instructions
|
// 3DNOW instructions [Anyone caught dead using these will be re-killed]
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
/* femms */
|
/* femms */
|
||||||
emitterT void FEMMS( void )
|
emitterT void FEMMS( void )
|
||||||
{
|
{
|
||||||
write16( 0x0E0F );
|
xWrite16( 0x0E0F );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFCMPEQMtoR( x86IntRegType to, uptr from )
|
emitterT void PFCMPEQMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0xB0 );
|
xWrite8( 0xB0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFCMPGTMtoR( x86IntRegType to, uptr from )
|
emitterT void PFCMPGTMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0xA0 );
|
xWrite8( 0xA0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFCMPGEMtoR( x86IntRegType to, uptr from )
|
emitterT void PFCMPGEMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x90 );
|
xWrite8( 0x90 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFADDMtoR( x86IntRegType to, uptr from )
|
emitterT void PFADDMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x9E );
|
xWrite8( 0x9E );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFADDRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFADDRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x9E );
|
xWrite8( 0x9E );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFSUBMtoR( x86IntRegType to, uptr from )
|
emitterT void PFSUBMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x9A );
|
xWrite8( 0x9A );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFSUBRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFSUBRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x9A );
|
xWrite8( 0x9A );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMULMtoR( x86IntRegType to, uptr from )
|
emitterT void PFMULMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0xB4 );
|
xWrite8( 0xB4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMULRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFMULRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0xB4 );
|
xWrite8( 0xB4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRCPMtoR( x86IntRegType to, uptr from )
|
emitterT void PFRCPMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x96 );
|
xWrite8( 0x96 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRCPRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFRCPRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x96 );
|
xWrite8( 0x96 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0xA6 );
|
xWrite8( 0xA6 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0xB6 );
|
xWrite8( 0xB6 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x97 );
|
xWrite8( 0x97 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0xA7 );
|
xWrite8( 0xA7 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PF2IDMtoR( x86IntRegType to, uptr from )
|
emitterT void PF2IDMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x1D );
|
xWrite8( 0x1D );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PF2IDRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PF2IDRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x1D );
|
xWrite8( 0x1D );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PI2FDMtoR( x86IntRegType to, uptr from )
|
emitterT void PI2FDMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x0D );
|
xWrite8( 0x0D );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PI2FDRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PI2FDRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x0D );
|
xWrite8( 0x0D );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMAXMtoR( x86IntRegType to, uptr from )
|
emitterT void PFMAXMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0xA4 );
|
xWrite8( 0xA4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMAXRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFMAXRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0xA4 );
|
xWrite8( 0xA4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMINMtoR( x86IntRegType to, uptr from )
|
emitterT void PFMINMtoR( x86IntRegType to, uptr from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 0, to, DISP32 );
|
ModRM( 0, to, DISP32 );
|
||||||
write32( from );
|
xWrite32( from );
|
||||||
write8( 0x94 );
|
xWrite8( 0x94 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void PFMINRtoR( x86IntRegType to, x86IntRegType from )
|
emitterT void PFMINRtoR( x86IntRegType to, x86IntRegType from )
|
||||||
{
|
{
|
||||||
write16( 0x0F0F );
|
xWrite16( 0x0F0F );
|
||||||
ModRM( 3, to, from );
|
ModRM( 3, to, from );
|
||||||
write8( 0x94 );
|
xWrite8( 0x94 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,244 +26,244 @@
|
||||||
/* fild m32 to fpu reg stack */
|
/* fild m32 to fpu reg stack */
|
||||||
emitterT void FILD32( u32 from )
|
emitterT void FILD32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xDB );
|
xWrite8( 0xDB );
|
||||||
ModRM( 0, 0x0, DISP32 );
|
ModRM( 0, 0x0, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fistp m32 from fpu reg stack */
|
/* fistp m32 from fpu reg stack */
|
||||||
emitterT void FISTP32( u32 from )
|
emitterT void FISTP32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xDB );
|
xWrite8( 0xDB );
|
||||||
ModRM( 0, 0x3, DISP32 );
|
ModRM( 0, 0x3, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fld m32 to fpu reg stack */
|
/* fld m32 to fpu reg stack */
|
||||||
emitterT void FLD32( u32 from )
|
emitterT void FLD32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD9 );
|
xWrite8( 0xD9 );
|
||||||
ModRM( 0, 0x0, DISP32 );
|
ModRM( 0, 0x0, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// fld st(i)
|
// fld st(i)
|
||||||
emitterT void FLD(int st) { write16(0xc0d9+(st<<8)); }
|
emitterT void FLD(int st) { xWrite16(0xc0d9+(st<<8)); }
|
||||||
emitterT void FLD1() { write16(0xe8d9); }
|
emitterT void FLD1() { xWrite16(0xe8d9); }
|
||||||
emitterT void FLDL2E() { write16(0xead9); }
|
emitterT void FLDL2E() { xWrite16(0xead9); }
|
||||||
|
|
||||||
/* fst m32 from fpu reg stack */
|
/* fst m32 from fpu reg stack */
|
||||||
emitterT void FST32( u32 to )
|
emitterT void FST32( u32 to )
|
||||||
{
|
{
|
||||||
write8( 0xD9 );
|
xWrite8( 0xD9 );
|
||||||
ModRM( 0, 0x2, DISP32 );
|
ModRM( 0, 0x2, DISP32 );
|
||||||
write32( MEMADDR(to, 4) );
|
xWrite32( MEMADDR(to, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fstp m32 from fpu reg stack */
|
/* fstp m32 from fpu reg stack */
|
||||||
emitterT void FSTP32( u32 to )
|
emitterT void FSTP32( u32 to )
|
||||||
{
|
{
|
||||||
write8( 0xD9 );
|
xWrite8( 0xD9 );
|
||||||
ModRM( 0, 0x3, DISP32 );
|
ModRM( 0, 0x3, DISP32 );
|
||||||
write32( MEMADDR(to, 4) );
|
xWrite32( MEMADDR(to, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// fstp st(i)
|
// fstp st(i)
|
||||||
emitterT void FSTP(int st) { write16(0xd8dd+(st<<8)); }
|
emitterT void FSTP(int st) { xWrite16(0xd8dd+(st<<8)); }
|
||||||
|
|
||||||
/* fldcw fpu control word from m16 */
|
/* fldcw fpu control word from m16 */
|
||||||
emitterT void FLDCW( u32 from )
|
emitterT void FLDCW( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD9 );
|
xWrite8( 0xD9 );
|
||||||
ModRM( 0, 0x5, DISP32 );
|
ModRM( 0, 0x5, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fnstcw fpu control word to m16 */
|
/* fnstcw fpu control word to m16 */
|
||||||
emitterT void FNSTCW( u32 to )
|
emitterT void FNSTCW( u32 to )
|
||||||
{
|
{
|
||||||
write8( 0xD9 );
|
xWrite8( 0xD9 );
|
||||||
ModRM( 0, 0x7, DISP32 );
|
ModRM( 0, 0x7, DISP32 );
|
||||||
write32( MEMADDR(to, 4) );
|
xWrite32( MEMADDR(to, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void FNSTSWtoAX() { write16(0xE0DF); }
|
emitterT void FNSTSWtoAX() { xWrite16(0xE0DF); }
|
||||||
emitterT void FXAM() { write16(0xe5d9); }
|
emitterT void FXAM() { xWrite16(0xe5d9); }
|
||||||
emitterT void FDECSTP() { write16(0xf6d9); }
|
emitterT void FDECSTP() { xWrite16(0xf6d9); }
|
||||||
emitterT void FRNDINT() { write16(0xfcd9); }
|
emitterT void FRNDINT() { xWrite16(0xfcd9); }
|
||||||
emitterT void FXCH(int st) { write16(0xc8d9+(st<<8)); }
|
emitterT void FXCH(int st) { xWrite16(0xc8d9+(st<<8)); }
|
||||||
emitterT void F2XM1() { write16(0xf0d9); }
|
emitterT void F2XM1() { xWrite16(0xf0d9); }
|
||||||
emitterT void FSCALE() { write16(0xfdd9); }
|
emitterT void FSCALE() { xWrite16(0xfdd9); }
|
||||||
emitterT void FPATAN(void) { write16(0xf3d9); }
|
emitterT void FPATAN(void) { xWrite16(0xf3d9); }
|
||||||
emitterT void FSIN(void) { write16(0xfed9); }
|
emitterT void FSIN(void) { xWrite16(0xfed9); }
|
||||||
|
|
||||||
/* fadd ST(src) to fpu reg stack ST(0) */
|
/* fadd ST(src) to fpu reg stack ST(0) */
|
||||||
emitterT void FADD32Rto0( x86IntRegType src )
|
emitterT void FADD32Rto0( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
write8( 0xC0 + src );
|
xWrite8( 0xC0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fadd ST(0) to fpu reg stack ST(src) */
|
/* fadd ST(0) to fpu reg stack ST(src) */
|
||||||
emitterT void FADD320toR( x86IntRegType src )
|
emitterT void FADD320toR( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDC );
|
xWrite8( 0xDC );
|
||||||
write8( 0xC0 + src );
|
xWrite8( 0xC0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fsub ST(src) to fpu reg stack ST(0) */
|
/* fsub ST(src) to fpu reg stack ST(0) */
|
||||||
emitterT void FSUB32Rto0( x86IntRegType src )
|
emitterT void FSUB32Rto0( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
write8( 0xE0 + src );
|
xWrite8( 0xE0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fsub ST(0) to fpu reg stack ST(src) */
|
/* fsub ST(0) to fpu reg stack ST(src) */
|
||||||
emitterT void FSUB320toR( x86IntRegType src )
|
emitterT void FSUB320toR( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDC );
|
xWrite8( 0xDC );
|
||||||
write8( 0xE8 + src );
|
xWrite8( 0xE8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */
|
/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */
|
||||||
emitterT void FSUBP( void )
|
emitterT void FSUBP( void )
|
||||||
{
|
{
|
||||||
write8( 0xDE );
|
xWrite8( 0xDE );
|
||||||
write8( 0xE9 );
|
xWrite8( 0xE9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fmul ST(src) to fpu reg stack ST(0) */
|
/* fmul ST(src) to fpu reg stack ST(0) */
|
||||||
emitterT void FMUL32Rto0( x86IntRegType src )
|
emitterT void FMUL32Rto0( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
write8( 0xC8 + src );
|
xWrite8( 0xC8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fmul ST(0) to fpu reg stack ST(src) */
|
/* fmul ST(0) to fpu reg stack ST(src) */
|
||||||
emitterT void FMUL320toR( x86IntRegType src )
|
emitterT void FMUL320toR( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDC );
|
xWrite8( 0xDC );
|
||||||
write8( 0xC8 + src );
|
xWrite8( 0xC8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fdiv ST(src) to fpu reg stack ST(0) */
|
/* fdiv ST(src) to fpu reg stack ST(0) */
|
||||||
emitterT void FDIV32Rto0( x86IntRegType src )
|
emitterT void FDIV32Rto0( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
write8( 0xF0 + src );
|
xWrite8( 0xF0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fdiv ST(0) to fpu reg stack ST(src) */
|
/* fdiv ST(0) to fpu reg stack ST(src) */
|
||||||
emitterT void FDIV320toR( x86IntRegType src )
|
emitterT void FDIV320toR( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDC );
|
xWrite8( 0xDC );
|
||||||
write8( 0xF8 + src );
|
xWrite8( 0xF8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void FDIV320toRP( x86IntRegType src )
|
emitterT void FDIV320toRP( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDE );
|
xWrite8( 0xDE );
|
||||||
write8( 0xF8 + src );
|
xWrite8( 0xF8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fadd m32 to fpu reg stack */
|
/* fadd m32 to fpu reg stack */
|
||||||
emitterT void FADD32( u32 from )
|
emitterT void FADD32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x0, DISP32 );
|
ModRM( 0, 0x0, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fsub m32 to fpu reg stack */
|
/* fsub m32 to fpu reg stack */
|
||||||
emitterT void FSUB32( u32 from )
|
emitterT void FSUB32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x4, DISP32 );
|
ModRM( 0, 0x4, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fmul m32 to fpu reg stack */
|
/* fmul m32 to fpu reg stack */
|
||||||
emitterT void FMUL32( u32 from )
|
emitterT void FMUL32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x1, DISP32 );
|
ModRM( 0, 0x1, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fdiv m32 to fpu reg stack */
|
/* fdiv m32 to fpu reg stack */
|
||||||
emitterT void FDIV32( u32 from )
|
emitterT void FDIV32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x6, DISP32 );
|
ModRM( 0, 0x6, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fabs fpu reg stack */
|
/* fabs fpu reg stack */
|
||||||
emitterT void FABS( void )
|
emitterT void FABS( void )
|
||||||
{
|
{
|
||||||
write16( 0xE1D9 );
|
xWrite16( 0xE1D9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fsqrt fpu reg stack */
|
/* fsqrt fpu reg stack */
|
||||||
emitterT void FSQRT( void )
|
emitterT void FSQRT( void )
|
||||||
{
|
{
|
||||||
write16( 0xFAD9 );
|
xWrite16( 0xFAD9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fchs fpu reg stack */
|
/* fchs fpu reg stack */
|
||||||
emitterT void FCHS( void )
|
emitterT void FCHS( void )
|
||||||
{
|
{
|
||||||
write16( 0xE0D9 );
|
xWrite16( 0xE0D9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fcomi st, st(i) */
|
/* fcomi st, st(i) */
|
||||||
emitterT void FCOMI( x86IntRegType src )
|
emitterT void FCOMI( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDB );
|
xWrite8( 0xDB );
|
||||||
write8( 0xF0 + src );
|
xWrite8( 0xF0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fcomip st, st(i) */
|
/* fcomip st, st(i) */
|
||||||
emitterT void FCOMIP( x86IntRegType src )
|
emitterT void FCOMIP( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDF );
|
xWrite8( 0xDF );
|
||||||
write8( 0xF0 + src );
|
xWrite8( 0xF0 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fucomi st, st(i) */
|
/* fucomi st, st(i) */
|
||||||
emitterT void FUCOMI( x86IntRegType src )
|
emitterT void FUCOMI( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDB );
|
xWrite8( 0xDB );
|
||||||
write8( 0xE8 + src );
|
xWrite8( 0xE8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fucomip st, st(i) */
|
/* fucomip st, st(i) */
|
||||||
emitterT void FUCOMIP( x86IntRegType src )
|
emitterT void FUCOMIP( x86IntRegType src )
|
||||||
{
|
{
|
||||||
write8( 0xDF );
|
xWrite8( 0xDF );
|
||||||
write8( 0xE8 + src );
|
xWrite8( 0xE8 + src );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fcom m32 to fpu reg stack */
|
/* fcom m32 to fpu reg stack */
|
||||||
emitterT void FCOM32( u32 from )
|
emitterT void FCOM32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x2, DISP32 );
|
ModRM( 0, 0x2, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fcomp m32 to fpu reg stack */
|
/* fcomp m32 to fpu reg stack */
|
||||||
emitterT void FCOMP32( u32 from )
|
emitterT void FCOMP32( u32 from )
|
||||||
{
|
{
|
||||||
write8( 0xD8 );
|
xWrite8( 0xD8 );
|
||||||
ModRM( 0, 0x3, DISP32 );
|
ModRM( 0, 0x3, DISP32 );
|
||||||
write32( MEMADDR(from, 4) );
|
xWrite32( MEMADDR(from, 4) );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FCMOV32( low, high ) \
|
#define FCMOV32( low, high ) \
|
||||||
{ \
|
{ \
|
||||||
write8( low ); \
|
xWrite8( low ); \
|
||||||
write8( high + from ); \
|
xWrite8( high + from ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); }
|
emitterT void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); }
|
||||||
|
|
|
@ -175,7 +175,7 @@ namespace x86Emitter
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
template< typename OperandType >
|
template< typename OperandType >
|
||||||
xForwardJump<OperandType>::xForwardJump( JccComparisonType cctype ) :
|
xForwardJump<OperandType>::xForwardJump( JccComparisonType cctype ) :
|
||||||
BasePtr( (s8*)iGetPtr() +
|
BasePtr( (s8*)xGetPtr() +
|
||||||
((OperandSize == 1) ? 2 : // j8's are always 2 bytes.
|
((OperandSize == 1) ? 2 : // j8's are always 2 bytes.
|
||||||
((cctype==Jcc_Unconditional) ? 5 : 6 )) // j32's are either 5 or 6 bytes
|
((cctype==Jcc_Unconditional) ? 5 : 6 )) // j32's are either 5 or 6 bytes
|
||||||
)
|
)
|
||||||
|
@ -184,19 +184,19 @@ namespace x86Emitter
|
||||||
jASSUME( OperandSize == 1 || OperandSize == 4 );
|
jASSUME( OperandSize == 1 || OperandSize == 4 );
|
||||||
|
|
||||||
if( OperandSize == 1 )
|
if( OperandSize == 1 )
|
||||||
xWrite<u8>( (cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype) );
|
xWrite8( (cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype) );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( cctype == Jcc_Unconditional )
|
if( cctype == Jcc_Unconditional )
|
||||||
xWrite<u8>( 0xe9 );
|
xWrite8( 0xe9 );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x0f );
|
xWrite8( 0x0f );
|
||||||
xWrite<u8>( 0x80 | cctype );
|
xWrite8( 0x80 | cctype );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iAdvancePtr( OperandSize );
|
xAdvancePtr( OperandSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -205,7 +205,7 @@ namespace x86Emitter
|
||||||
{
|
{
|
||||||
jASSUME( BasePtr != NULL );
|
jASSUME( BasePtr != NULL );
|
||||||
|
|
||||||
sptr displacement = (sptr)iGetPtr() - (sptr)BasePtr;
|
sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr;
|
||||||
if( OperandSize == 1 )
|
if( OperandSize == 1 )
|
||||||
{
|
{
|
||||||
if( !is_s8( displacement ) )
|
if( !is_s8( displacement ) )
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace x86Emitter
|
||||||
// flags.
|
// flags.
|
||||||
|
|
||||||
extern const Internal::MovImplAll xMOV;
|
extern const Internal::MovImplAll xMOV;
|
||||||
extern const Internal::TestImplAll xTEST;
|
extern const Internal::xImpl_Test xTEST;
|
||||||
|
|
||||||
extern const Internal::Group2ImplAll<Internal::G2Type_ROL> xROL;
|
extern const Internal::Group2ImplAll<Internal::G2Type_ROL> xROL;
|
||||||
extern const Internal::Group2ImplAll<Internal::G2Type_ROR> xROR;
|
extern const Internal::Group2ImplAll<Internal::G2Type_ROR> xROR;
|
||||||
|
@ -70,15 +70,15 @@ namespace x86Emitter
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Group 3 Instruction Class
|
// Group 3 Instruction Class
|
||||||
|
|
||||||
extern const Internal::Group3ImplAll<Internal::G3Type_NOT> xNOT;
|
extern const Internal::xImpl_Group3<Internal::G3Type_NOT> xNOT;
|
||||||
extern const Internal::Group3ImplAll<Internal::G3Type_NEG> xNEG;
|
extern const Internal::xImpl_Group3<Internal::G3Type_NEG> xNEG;
|
||||||
extern const Internal::Group3ImplAll<Internal::G3Type_MUL> xUMUL;
|
extern const Internal::xImpl_Group3<Internal::G3Type_MUL> xUMUL;
|
||||||
extern const Internal::Group3ImplAll<Internal::G3Type_DIV> xUDIV;
|
extern const Internal::xImpl_Group3<Internal::G3Type_DIV> xUDIV;
|
||||||
extern const Internal::xImpl_Group3<Internal::G3Type_iDIV,0x5e> xDIV;
|
extern const Internal::xImpl_iDiv xDIV;
|
||||||
extern const Internal::xImpl_iMul xMUL;
|
extern const Internal::xImpl_iMul xMUL;
|
||||||
|
|
||||||
extern const Internal::IncDecImplAll<false> xINC;
|
extern const Internal::xImpl_IncDec<false> xINC;
|
||||||
extern const Internal::IncDecImplAll<true> xDEC;
|
extern const Internal::xImpl_IncDec<true> xDEC;
|
||||||
|
|
||||||
extern const Internal::MovExtendImplAll<false> xMOVZX;
|
extern const Internal::MovExtendImplAll<false> xMOVZX;
|
||||||
extern const Internal::MovExtendImplAll<true> xMOVSX;
|
extern const Internal::MovExtendImplAll<true> xMOVSX;
|
||||||
|
@ -86,16 +86,16 @@ namespace x86Emitter
|
||||||
extern const Internal::DwordShiftImplAll<false> xSHLD;
|
extern const Internal::DwordShiftImplAll<false> xSHLD;
|
||||||
extern const Internal::DwordShiftImplAll<true> xSHRD;
|
extern const Internal::DwordShiftImplAll<true> xSHRD;
|
||||||
|
|
||||||
extern const Internal::Group8Impl<Internal::G8Type_BT> xBT;
|
extern const Internal::xImpl_Group8<Internal::G8Type_BT> xBT;
|
||||||
extern const Internal::Group8Impl<Internal::G8Type_BTR> xBTR;
|
extern const Internal::xImpl_Group8<Internal::G8Type_BTR> xBTR;
|
||||||
extern const Internal::Group8Impl<Internal::G8Type_BTS> xBTS;
|
extern const Internal::xImpl_Group8<Internal::G8Type_BTS> xBTS;
|
||||||
extern const Internal::Group8Impl<Internal::G8Type_BTC> xBTC;
|
extern const Internal::xImpl_Group8<Internal::G8Type_BTC> xBTC;
|
||||||
|
|
||||||
extern const Internal::JmpCallImplAll<true> xJMP;
|
extern const Internal::xImpl_JmpCall<true> xJMP;
|
||||||
extern const Internal::JmpCallImplAll<false> xCALL;
|
extern const Internal::xImpl_JmpCall<false> xCALL;
|
||||||
|
|
||||||
extern const Internal::BitScanImpl<0xbc> xBSF;
|
extern const Internal::xImpl_BitScan<0xbc> xBSF;
|
||||||
extern const Internal::BitScanImpl<0xbd> xBSR;
|
extern const Internal::xImpl_BitScan<0xbd> xBSR;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
extern const Internal::CMovImplGeneric xCMOV;
|
extern const Internal::CMovImplGeneric xCMOV;
|
||||||
|
@ -175,40 +175,75 @@ namespace x86Emitter
|
||||||
extern void xPOP( const ModSibBase& from );
|
extern void xPOP( const ModSibBase& from );
|
||||||
extern void xPUSH( const ModSibBase& from );
|
extern void xPUSH( const ModSibBase& from );
|
||||||
|
|
||||||
static __forceinline void xPOP( xRegister32 from ) { write8( 0x58 | from.Id ); }
|
extern void xPOP( xRegister32 from );
|
||||||
static __forceinline void xPOP( void* from ) { xPOP( ptr[from] ); }
|
extern void xPOP( void* from );
|
||||||
|
|
||||||
static __forceinline void xPUSH( u32 imm ) { write8( 0x68 ); write32( imm ); }
|
extern void xPUSH( u32 imm );
|
||||||
static __forceinline void xPUSH( xRegister32 from ) { write8( 0x50 | from.Id ); }
|
extern void xPUSH( xRegister32 from );
|
||||||
static __forceinline void xPUSH( void* from ) { xPUSH( ptr[from] ); }
|
extern void xPUSH( void* from );
|
||||||
|
|
||||||
// pushes the EFLAGS register onto the stack
|
// pushes the EFLAGS register onto the stack
|
||||||
static __forceinline void xPUSHFD() { write8( 0x9C ); }
|
extern void xPUSHFD();
|
||||||
// pops the EFLAGS register from the stack
|
// pops the EFLAGS register from the stack
|
||||||
static __forceinline void xPOPFD() { write8( 0x9D ); }
|
extern void xPOPFD();
|
||||||
|
|
||||||
// ----- Miscellaneous Instructions -----
|
// ----- Miscellaneous Instructions -----
|
||||||
// Various Instructions with no parameter and no special encoding logic.
|
// Various Instructions with no parameter and no special encoding logic.
|
||||||
|
|
||||||
__forceinline void xRET() { write8( 0xC3 ); }
|
extern void xRET();
|
||||||
__forceinline void xCBW() { write16( 0x9866 ); }
|
extern void xCBW();
|
||||||
__forceinline void xCWD() { write8( 0x98 ); }
|
extern void xCWD();
|
||||||
__forceinline void xCDQ() { write8( 0x99 ); }
|
extern void xCDQ();
|
||||||
__forceinline void xCWDE() { write8( 0x98 ); }
|
extern void xCWDE();
|
||||||
|
|
||||||
__forceinline void xLAHF() { write8( 0x9f ); }
|
extern void xLAHF();
|
||||||
__forceinline void xSAHF() { write8( 0x9e ); }
|
extern void xSAHF();
|
||||||
|
|
||||||
__forceinline void xSTC() { write8( 0xF9 ); }
|
extern void xSTC();
|
||||||
__forceinline void xCLC() { write8( 0xF8 ); }
|
extern void xCLC();
|
||||||
|
|
||||||
// NOP 1-byte
|
// NOP 1-byte
|
||||||
__forceinline void xNOP() { write8(0x90); }
|
extern void xNOP();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// JMP / Jcc Instructions!
|
// JMP / Jcc Instructions!
|
||||||
|
|
||||||
extern void iJccKnownTarget( JccComparisonType comparison, void* target, bool slideForward=false );
|
extern void iJcc( JccComparisonType comparison, void* target );
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Conditional jumps to fixed targets.
|
||||||
|
// Jumps accept any pointer as a valid target (function or data), and will generate either
|
||||||
|
// 8 or 32 bit displacement versions of the jump, depending on relative displacement of
|
||||||
|
// the target (efficient!)
|
||||||
|
//
|
||||||
|
|
||||||
|
template< typename T > __forceinline void xJE( const T* func ) { iJcc( Jcc_Equal, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJZ( const T* func ) { iJcc( Jcc_Zero, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJNE( const T* func ) { iJcc( Jcc_NotEqual, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJNZ( const T* func ) { iJcc( Jcc_NotZero, (void*)(uptr)func ); }
|
||||||
|
|
||||||
|
template< typename T > __forceinline void xJO( const T* func ) { iJcc( Jcc_Overflow, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJNO( const T* func ) { iJcc( Jcc_NotOverflow, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJC( const T* func ) { iJcc( Jcc_Carry, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJNC( const T* func ) { iJcc( Jcc_NotCarry, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJS( const T* func ) { iJcc( Jcc_Signed, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJNS( const T* func ) { iJcc( Jcc_Unsigned, (void*)(uptr)func ); }
|
||||||
|
|
||||||
|
template< typename T > __forceinline void xJPE( const T* func ) { iJcc( Jcc_ParityEven, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJPO( const T* func ) { iJcc( Jcc_ParityOdd, (void*)(uptr)func ); }
|
||||||
|
|
||||||
|
template< typename T > __forceinline void xJL( const T* func ) { iJcc( Jcc_Less, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJLE( const T* func ) { iJcc( Jcc_LessOrEqual, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJG( const T* func ) { iJcc( Jcc_Greater, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJGE( const T* func ) { iJcc( Jcc_GreaterOrEqual, (void*)(uptr)func ); }
|
||||||
|
|
||||||
|
template< typename T > __forceinline void xJB( const T* func ) { iJcc( Jcc_Below, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJBE( const T* func ) { iJcc( Jcc_BelowOrEqual, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJA( const T* func ) { iJcc( Jcc_Above, (void*)(uptr)func ); }
|
||||||
|
template< typename T > __forceinline void xJAE( const T* func ) { iJcc( Jcc_AboveOrEqual, (void*)(uptr)func ); }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Forward Jump Helpers (act as labels!)
|
||||||
|
|
||||||
#define DEFINE_FORWARD_JUMP( label, cond ) \
|
#define DEFINE_FORWARD_JUMP( label, cond ) \
|
||||||
template< typename OperandType > \
|
template< typename OperandType > \
|
||||||
|
|
|
@ -40,30 +40,30 @@ namespace x86Emitter {
|
||||||
|
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
const JmpCallImplAll<true> xJMP;
|
const xImpl_JmpCall<true> xJMP;
|
||||||
const JmpCallImplAll<false> xCALL;
|
const xImpl_JmpCall<false> xCALL;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void xSmartJump::SetTarget()
|
void xSmartJump::SetTarget()
|
||||||
{
|
{
|
||||||
u8* target = iGetPtr();
|
u8* target = xGetPtr();
|
||||||
if( m_baseptr == NULL ) return;
|
if( m_baseptr == NULL ) return;
|
||||||
|
|
||||||
iSetPtr( m_baseptr );
|
xSetPtr( m_baseptr );
|
||||||
u8* const saveme = m_baseptr + GetMaxInstructionSize();
|
u8* const saveme = m_baseptr + GetMaxInstructionSize();
|
||||||
iJccKnownTarget( m_cc, target, true );
|
iJccKnownTarget( m_cc, target, true );
|
||||||
|
|
||||||
// Copy recompiled data inward if the jump instruction didn't fill the
|
// Copy recompiled data inward if the jump instruction didn't fill the
|
||||||
// alloted buffer (means that we optimized things to a j8!)
|
// alloted buffer (means that we optimized things to a j8!)
|
||||||
|
|
||||||
const int spacer = (sptr)saveme - (sptr)iGetPtr();
|
const int spacer = (sptr)saveme - (sptr)xGetPtr();
|
||||||
if( spacer != 0 )
|
if( spacer != 0 )
|
||||||
{
|
{
|
||||||
u8* destpos = iGetPtr();
|
u8* destpos = xGetPtr();
|
||||||
const int copylen = (sptr)target - (sptr)saveme;
|
const int copylen = (sptr)target - (sptr)saveme;
|
||||||
|
|
||||||
memcpy_fast( destpos, saveme, copylen );
|
memcpy_fast( destpos, saveme, copylen );
|
||||||
iSetPtr( target - spacer );
|
xSetPtr( target - spacer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +81,10 @@ xSmartJump::~xSmartJump()
|
||||||
// slideForward - used internally by xSmartJump to indicate that the jump target is going
|
// slideForward - used internally by xSmartJump to indicate that the jump target is going
|
||||||
// to slide forward in the event of an 8 bit displacement.
|
// to slide forward in the event of an 8 bit displacement.
|
||||||
//
|
//
|
||||||
// Using this
|
__emitinline void Internal::iJccKnownTarget( JccComparisonType comparison, void* target, bool slideForward )
|
||||||
__emitinline void iJccKnownTarget( JccComparisonType comparison, void* target, bool slideForward )
|
|
||||||
{
|
{
|
||||||
// Calculate the potential j8 displacement first, assuming an instruction length of 2:
|
// Calculate the potential j8 displacement first, assuming an instruction length of 2:
|
||||||
sptr displacement8 = (sptr)target - ((sptr)iGetPtr() + 2);
|
sptr displacement8 = (sptr)target - ((sptr)xGetPtr() + 2);
|
||||||
|
|
||||||
const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
|
const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
|
||||||
displacement8 -= slideVal;
|
displacement8 -= slideVal;
|
||||||
|
@ -96,7 +95,7 @@ __emitinline void iJccKnownTarget( JccComparisonType comparison, void* target, b
|
||||||
|
|
||||||
if( is_s8( displacement8 ) )
|
if( is_s8( displacement8 ) )
|
||||||
{
|
{
|
||||||
xWrite<u8>( (comparison == Jcc_Unconditional) ? 0xeb : (0x70 | comparison) );
|
xWrite8( (comparison == Jcc_Unconditional) ? 0xeb : (0x70 | comparison) );
|
||||||
xWrite<s8>( displacement8 );
|
xWrite<s8>( displacement8 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -104,14 +103,21 @@ __emitinline void iJccKnownTarget( JccComparisonType comparison, void* target, b
|
||||||
// Perform a 32 bit jump instead. :(
|
// Perform a 32 bit jump instead. :(
|
||||||
|
|
||||||
if( comparison == Jcc_Unconditional )
|
if( comparison == Jcc_Unconditional )
|
||||||
xWrite<u8>( 0xe9 );
|
xWrite8( 0xe9 );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x0f );
|
xWrite8( 0x0f );
|
||||||
xWrite<u8>( 0x80 | comparison );
|
xWrite8( 0x80 | comparison );
|
||||||
}
|
}
|
||||||
xWrite<s32>( (sptr)target - ((sptr)iGetPtr() + 4) );
|
xWrite<s32>( (sptr)target - ((sptr)xGetPtr() + 4) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Low-level jump instruction! Specify a comparison type and a target in void* form, and
|
||||||
|
// a jump (either 8 or 32 bit) is generated.
|
||||||
|
__emitinline void iJcc( JccComparisonType comparison, void* target )
|
||||||
|
{
|
||||||
|
iJccKnownTarget( comparison, target, false );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,6 +32,30 @@
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include "ix86_legacy_internal.h"
|
#include "ix86_legacy_internal.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
emitterT void ModRM( uint mod, uint reg, uint rm )
|
||||||
|
{
|
||||||
|
// Note: Following ASSUMEs are for legacy support only.
|
||||||
|
// The new emitter performs these sanity checks during operand construction, so these
|
||||||
|
// assertions can probably be removed once all legacy emitter code has been removed.
|
||||||
|
jASSUME( mod < 4 );
|
||||||
|
jASSUME( reg < 8 );
|
||||||
|
jASSUME( rm < 8 );
|
||||||
|
xWrite8( (mod << 6) | (reg << 3) | rm );
|
||||||
|
}
|
||||||
|
|
||||||
|
emitterT void SibSB( uint ss, uint index, uint base )
|
||||||
|
{
|
||||||
|
// Note: Following ASSUMEs are for legacy support only.
|
||||||
|
// The new emitter performs these sanity checks during operand construction, so these
|
||||||
|
// assertions can probably be removed once all legacy emitter code has been removed.
|
||||||
|
jASSUME( ss < 4 );
|
||||||
|
jASSUME( index < 8 );
|
||||||
|
jASSUME( base < 8 );
|
||||||
|
xWrite8( (ss << 6) | (index << 3) | base );
|
||||||
|
}
|
||||||
|
|
||||||
using namespace x86Emitter;
|
using namespace x86Emitter;
|
||||||
|
|
||||||
template< typename ImmType >
|
template< typename ImmType >
|
||||||
|
@ -310,63 +334,26 @@ emitterT void SAHF() { xSAHF(); }
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Note: the 'to' field can either be a register or a special opcode extension specifier
|
|
||||||
// depending on the opcode's encoding.
|
|
||||||
|
|
||||||
emitterT 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( is_s8( offset ) ) {
|
|
||||||
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( is_s8( offset ) ) {
|
|
||||||
ModRM( 1, to, from );
|
|
||||||
write8(offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ModRM( 2, to, from );
|
|
||||||
write32(offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emitterT u8* J8Rel( int cc, int to )
|
emitterT u8* J8Rel( int cc, int to )
|
||||||
{
|
{
|
||||||
write8( cc );
|
xWrite8( cc );
|
||||||
write8( to );
|
xWrite8( to );
|
||||||
return (u8*)(x86Ptr - 1);
|
return (u8*)(x86Ptr - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT u16* J16Rel( int cc, u32 to )
|
emitterT u16* J16Rel( int cc, u32 to )
|
||||||
{
|
{
|
||||||
write16( 0x0F66 );
|
xWrite16( 0x0F66 );
|
||||||
write8( cc );
|
xWrite8( cc );
|
||||||
write16( to );
|
xWrite16( to );
|
||||||
return (u16*)( x86Ptr - 2 );
|
return (u16*)( x86Ptr - 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
emitterT u32* J32Rel( int cc, u32 to )
|
emitterT u32* J32Rel( int cc, u32 to )
|
||||||
{
|
{
|
||||||
write8( 0x0F );
|
xWrite8( 0x0F );
|
||||||
write8( cc );
|
xWrite8( cc );
|
||||||
write32( to );
|
xWrite32( to );
|
||||||
return (u32*)( x86Ptr - 4 );
|
return (u32*)( x86Ptr - 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,8 +435,8 @@ emitterT void NOP( void ) { xNOP(); }
|
||||||
/* jmp rel8 */
|
/* jmp rel8 */
|
||||||
emitterT u8* JMP8( u8 to )
|
emitterT u8* JMP8( u8 to )
|
||||||
{
|
{
|
||||||
write8( 0xEB );
|
xWrite8( 0xEB );
|
||||||
write8( to );
|
xWrite8( to );
|
||||||
return x86Ptr - 1;
|
return x86Ptr - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,8 +444,8 @@ emitterT u8* JMP8( u8 to )
|
||||||
emitterT u32* JMP32( uptr to )
|
emitterT u32* JMP32( uptr to )
|
||||||
{
|
{
|
||||||
assert( (sptr)to <= 0x7fffffff && (sptr)to >= -0x7fffffff );
|
assert( (sptr)to <= 0x7fffffff && (sptr)to >= -0x7fffffff );
|
||||||
write8( 0xE9 );
|
xWrite8( 0xE9 );
|
||||||
write32( to );
|
xWrite32( to );
|
||||||
return (u32*)(x86Ptr - 4 );
|
return (u32*)(x86Ptr - 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// legacy write functions (depreciated, use x86Emitter::EmitPtrCache instead)
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
#define emitterT __forceinline
|
|
||||||
|
|
||||||
using x86Emitter::write8;
|
|
||||||
using x86Emitter::write16;
|
|
||||||
using x86Emitter::write24;
|
|
||||||
using x86Emitter::write32;
|
|
||||||
using x86Emitter::write64;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// legacy jump/align functions
|
// legacy jump/align functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
|
@ -24,6 +24,13 @@
|
||||||
// Legacy Helper Macros and Functions (depreciated)
|
// Legacy Helper Macros and Functions (depreciated)
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define emitterT __forceinline
|
||||||
|
|
||||||
|
using x86Emitter::xWrite8;
|
||||||
|
using x86Emitter::xWrite16;
|
||||||
|
using x86Emitter::xWrite32;
|
||||||
|
using x86Emitter::xWrite64;
|
||||||
|
|
||||||
#include "ix86_legacy_types.h"
|
#include "ix86_legacy_types.h"
|
||||||
#include "ix86_legacy_instructions.h"
|
#include "ix86_legacy_instructions.h"
|
||||||
|
|
||||||
|
@ -37,7 +44,6 @@
|
||||||
|
|
||||||
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask))
|
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask))
|
||||||
|
|
||||||
extern void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset);
|
|
||||||
extern void ModRM( uint mod, uint reg, uint rm );
|
extern void ModRM( uint mod, uint reg, uint rm );
|
||||||
extern void SibSB( uint ss, uint index, uint base );
|
extern void SibSB( uint ss, uint index, uint base );
|
||||||
extern void SET8R( int cc, int to );
|
extern void SET8R( int cc, int to );
|
||||||
|
@ -45,27 +51,3 @@ extern u8* J8Rel( int cc, int to );
|
||||||
extern u32* J32Rel( int cc, u32 to );
|
extern u32* J32Rel( int cc, u32 to );
|
||||||
extern u64 GetCPUTick( void );
|
extern u64 GetCPUTick( void );
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
emitterT void ModRM( uint mod, uint reg, uint rm )
|
|
||||||
{
|
|
||||||
// Note: Following ASSUMEs are for legacy support only.
|
|
||||||
// The new emitter performs these sanity checks during operand construction, so these
|
|
||||||
// assertions can probably be removed once all legacy emitter code has been removed.
|
|
||||||
jASSUME( mod < 4 );
|
|
||||||
jASSUME( reg < 8 );
|
|
||||||
jASSUME( rm < 8 );
|
|
||||||
write8( (mod << 6) | (reg << 3) | rm );
|
|
||||||
}
|
|
||||||
|
|
||||||
emitterT void SibSB( uint ss, uint index, uint base )
|
|
||||||
{
|
|
||||||
// Note: Following ASSUMEs are for legacy support only.
|
|
||||||
// The new emitter performs these sanity checks during operand construction, so these
|
|
||||||
// assertions can probably be removed once all legacy emitter code has been removed.
|
|
||||||
jASSUME( ss < 4 );
|
|
||||||
jASSUME( index < 8 );
|
|
||||||
jASSUME( base < 8 );
|
|
||||||
write8( (ss << 6) | (index << 3) | base );
|
|
||||||
}
|
|
||||||
|
|
|
@ -36,29 +36,29 @@ __emitinline void Internal::SimdPrefix( u8 prefix, u16 opcode )
|
||||||
{
|
{
|
||||||
const bool is16BitOpcode = ((opcode & 0xff) == 0x38) || ((opcode & 0xff) == 0x3a);
|
const bool is16BitOpcode = ((opcode & 0xff) == 0x38) || ((opcode & 0xff) == 0x3a);
|
||||||
|
|
||||||
// If the lower byte is not a valid previx and the upper byte is non-zero it
|
// If the lower byte is not a valid prefix and the upper byte is non-zero it
|
||||||
// means we made a mistake!
|
// means we made a mistake!
|
||||||
if( !is16BitOpcode ) jASSUME( (opcode >> 8) == 0 );
|
if( !is16BitOpcode ) jASSUME( (opcode >> 8) == 0 );
|
||||||
|
|
||||||
if( prefix != 0 )
|
if( prefix != 0 )
|
||||||
{
|
{
|
||||||
if( is16BitOpcode )
|
if( is16BitOpcode )
|
||||||
xWrite<u32>( (opcode<<16) | 0x0f00 | prefix );
|
xWrite32( (opcode<<16) | 0x0f00 | prefix );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xWrite<u16>( 0x0f00 | prefix );
|
xWrite16( 0x0f00 | prefix );
|
||||||
xWrite<u8>( opcode );
|
xWrite8( opcode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( is16BitOpcode )
|
if( is16BitOpcode )
|
||||||
{
|
{
|
||||||
xWrite<u8>( 0x0f );
|
xWrite8( 0x0f );
|
||||||
xWrite<u16>( opcode );
|
xWrite16( opcode );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
xWrite<u16>( (opcode<<8) | 0x0f );
|
xWrite16( (opcode<<8) | 0x0f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,23 +199,31 @@ const SimdImpl_PMove<false> xPMOVZX;
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
__emitinline void xEMMS()
|
// Converts from MMX register mode to FPU register mode. The cpu enters MMX register mode
|
||||||
{
|
// when ever MMX instructions are run, and if FPU instructions are run without using EMMS,
|
||||||
xWrite<u16>( 0x770F );
|
// the FPU results will be invalid.
|
||||||
}
|
__forceinline void xEMMS() { xWrite16( 0x770F ); }
|
||||||
|
|
||||||
|
// [3DNow] Same as EMMS, but an AMD special version which may (or may not) leave MMX regs
|
||||||
|
// in an undefined state (which is fine, since presumably you're done using them anyway).
|
||||||
|
// This instruction is thus faster than EMMS on K8s, but all newer AMD cpus use the same
|
||||||
|
// logic for either EMMS or FEMMS.
|
||||||
|
// Conclusion: Obsolete. Just use EMMS instead.
|
||||||
|
__forceinline void xFEMMS() { xWrite16( 0x0E0F ); }
|
||||||
|
|
||||||
|
|
||||||
// Store Streaming SIMD Extension Control/Status to Mem32.
|
// Store Streaming SIMD Extension Control/Status to Mem32.
|
||||||
__emitinline void xSTMXCSR( u32* dest )
|
__emitinline void xSTMXCSR( u32* dest )
|
||||||
{
|
{
|
||||||
SimdPrefix( 0, 0xae );
|
SimdPrefix( 0, 0xae );
|
||||||
xWriteDisp( 3, dest );
|
EmitSibMagic( 3, dest );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Streaming SIMD Extension Control/Status from Mem32.
|
// Load Streaming SIMD Extension Control/Status from Mem32.
|
||||||
__emitinline void xLDMXCSR( const u32* src )
|
__emitinline void xLDMXCSR( const u32* src )
|
||||||
{
|
{
|
||||||
SimdPrefix( 0, 0xae );
|
SimdPrefix( 0, 0xae );
|
||||||
xWriteDisp( 2, src );
|
EmitSibMagic( 2, src );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -279,7 +287,7 @@ __forceinline void xMOVQ( const xRegisterMMX& to, const xRegisterSSE& from )
|
||||||
// that breaks the template inference of writeXMMop();
|
// that breaks the template inference of writeXMMop();
|
||||||
|
|
||||||
SimdPrefix( 0xf2, 0xd6 );
|
SimdPrefix( 0xf2, 0xd6 );
|
||||||
ModRM_Direct( to.Id, from.Id );
|
EmitSibMagic( to, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -301,13 +309,13 @@ IMPLEMENT_xMOVS( SD, 0xf2 )
|
||||||
|
|
||||||
__forceinline void xMOVNTDQA( const xRegisterSSE& to, const void* from )
|
__forceinline void xMOVNTDQA( const xRegisterSSE& to, const void* from )
|
||||||
{
|
{
|
||||||
xWrite<u32>( 0x2A380f66 );
|
xWrite32( 0x2A380f66 );
|
||||||
xWriteDisp( to.Id, from );
|
EmitSibMagic( to.Id, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void xMOVNTDQA( const xRegisterSSE& to, const ModSibBase& from )
|
__forceinline void xMOVNTDQA( const xRegisterSSE& to, const ModSibBase& from )
|
||||||
{
|
{
|
||||||
xWrite<u32>( 0x2A380f66 );
|
xWrite32( 0x2A380f66 );
|
||||||
EmitSibMagic( to.Id, from );
|
EmitSibMagic( to.Id, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
extern void cpudetectInit();//this is all that needs to be called and will fill up the below structs
|
extern void cpudetectInit();//this is all that needs to be called and will fill up the below structs
|
||||||
|
|
||||||
//cpu capabilities structure
|
//cpu capabilities structure
|
||||||
struct CAPABILITIES {
|
struct CAPABILITIES
|
||||||
|
{
|
||||||
u32 hasFloatingPointUnit;
|
u32 hasFloatingPointUnit;
|
||||||
u32 hasVirtual8086ModeEnhancements;
|
u32 hasVirtual8086ModeEnhancements;
|
||||||
u32 hasDebuggingExtensions;
|
u32 hasDebuggingExtensions;
|
||||||
|
@ -63,8 +64,8 @@ struct CAPABILITIES {
|
||||||
|
|
||||||
extern CAPABILITIES cpucaps;
|
extern CAPABILITIES cpucaps;
|
||||||
|
|
||||||
struct CPUINFO{
|
struct CPUINFO
|
||||||
|
{
|
||||||
u32 x86Family; // Processor Family
|
u32 x86Family; // Processor Family
|
||||||
u32 x86Model; // Processor Model
|
u32 x86Model; // Processor Model
|
||||||
u32 x86PType; // Processor Type
|
u32 x86PType; // Processor Type
|
||||||
|
@ -109,20 +110,26 @@ extern __threadlocal u32 *j32Ptr[32]; // depreciated item. use local u32* vars
|
||||||
|
|
||||||
extern __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM];
|
extern __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM];
|
||||||
|
|
||||||
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
|
extern void xWrite8( u8 val );
|
||||||
|
extern void xWrite16( u16 val );
|
||||||
|
extern void xWrite32( u32 val );
|
||||||
|
extern void xWrite64( u64 val );
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// templated version of is_s8 is required, so that u16's get correct sign extension treatment.
|
// templated version of is_s8 is required, so that u16's get correct sign extension treatment.
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static __forceinline bool is_s8( T imm ) { return (s8)imm == (s32)imm; }
|
static __forceinline bool is_s8( T imm ) { return (s8)imm == (s32)imm; }
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
static __forceinline void xWrite( T val )
|
__forceinline void xWrite( T val )
|
||||||
{
|
{
|
||||||
*(T*)x86Ptr = val;
|
*(T*)x86Ptr = val;
|
||||||
x86Ptr += sizeof(T);
|
x86Ptr += sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace x86Emitter
|
|
||||||
{
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ALWAYS_USE_MOVAPS [define] / AlwaysUseMovaps [const]
|
// ALWAYS_USE_MOVAPS [define] / AlwaysUseMovaps [const]
|
||||||
|
@ -178,54 +185,27 @@ namespace x86Emitter
|
||||||
class xAddressInfo;
|
class xAddressInfo;
|
||||||
class ModSibBase;
|
class ModSibBase;
|
||||||
|
|
||||||
extern void iSetPtr( void* ptr );
|
extern void xSetPtr( void* ptr );
|
||||||
extern u8* iGetPtr();
|
extern u8* xGetPtr();
|
||||||
extern void iAlignPtr( uint bytes );
|
extern void xAlignPtr( uint bytes );
|
||||||
extern void iAdvancePtr( uint bytes );
|
extern void xAdvancePtr( uint bytes );
|
||||||
|
|
||||||
|
|
||||||
static __forceinline void write8( u8 val )
|
|
||||||
{
|
|
||||||
xWrite( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __forceinline void write16( u16 val )
|
|
||||||
{
|
|
||||||
xWrite( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __forceinline void write24( u32 val )
|
|
||||||
{
|
|
||||||
*(u32*)x86Ptr = val;
|
|
||||||
x86Ptr += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __forceinline void write32( u32 val )
|
|
||||||
{
|
|
||||||
xWrite( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
static __forceinline void write64( u64 val )
|
|
||||||
{
|
|
||||||
xWrite( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// xRegister
|
// xRegisterBase
|
||||||
// Unless templating some fancy stuff, use the friendly xRegister32/16/8 typedefs instead.
|
// Unless templating some fancy stuff, use the friendly xRegister32/16/8 typedefs instead.
|
||||||
//
|
//
|
||||||
template< typename OperandType >
|
template< typename OperandType >
|
||||||
class xRegister
|
class xRegisterBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const uint OperandSize = sizeof( OperandType );
|
static const uint OperandSize = sizeof( OperandType );
|
||||||
static const xRegister Empty; // defined as an empty/unused value (-1)
|
static const xRegisterBase Empty; // defined as an empty/unused value (-1)
|
||||||
|
|
||||||
int Id;
|
int Id;
|
||||||
|
|
||||||
xRegister( const xRegister<OperandType>& src ) : Id( src.Id ) {}
|
xRegisterBase( const xRegisterBase<OperandType>& src ) : Id( src.Id ) {}
|
||||||
xRegister(): Id( -1 ) {}
|
xRegisterBase(): Id( -1 ) {}
|
||||||
explicit xRegister( int regId ) : Id( regId ) { jASSUME( Id >= -1 && Id < 8 ); }
|
explicit xRegisterBase( int regId ) : Id( regId ) { jASSUME( Id >= -1 && Id < 8 ); }
|
||||||
|
|
||||||
bool IsEmpty() const { return Id < 0; }
|
bool IsEmpty() const { return Id < 0; }
|
||||||
|
|
||||||
|
@ -235,19 +215,60 @@ namespace x86Emitter
|
||||||
// returns true if the register is a valid MMX or XMM register.
|
// returns true if the register is a valid MMX or XMM register.
|
||||||
bool IsSIMD() const { return OperandSize == 8 || OperandSize == 16; }
|
bool IsSIMD() const { return OperandSize == 8 || OperandSize == 16; }
|
||||||
|
|
||||||
bool operator==( const xRegister<OperandType>& src ) const
|
bool operator==( const xRegisterBase<OperandType>& src ) const { return (Id == src.Id); }
|
||||||
{
|
bool operator!=( const xRegisterBase<OperandType>& src ) const { return (Id != src.Id); }
|
||||||
return (Id == src.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=( const xRegister<OperandType>& src ) const
|
xRegisterBase<OperandType>& operator=( const xRegisterBase<OperandType>& src )
|
||||||
{
|
{
|
||||||
return (Id != src.Id);
|
Id = src.Id;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
template< typename OperandType >
|
||||||
|
class xRegister : public xRegisterBase<OperandType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const xRegister Empty; // defined as an empty/unused value (-1)
|
||||||
|
|
||||||
|
public:
|
||||||
|
xRegister(): xRegisterBase<OperandType>() {}
|
||||||
|
xRegister( const xRegister& src ) : xRegisterBase<OperandType>( src.Id ) {}
|
||||||
|
explicit xRegister( const xRegisterBase<OperandType>& src ) : xRegisterBase<OperandType>( src ) {}
|
||||||
|
explicit xRegister( int regId ) : xRegisterBase<OperandType>( regId ) {}
|
||||||
|
|
||||||
|
bool operator==( const xRegister<OperandType>& src ) const { return Id == src.Id; }
|
||||||
|
bool operator!=( const xRegister<OperandType>& src ) const { return Id != src.Id; }
|
||||||
|
|
||||||
xRegister<OperandType>& operator=( const xRegister<OperandType>& src )
|
xRegister<OperandType>& operator=( const xRegister<OperandType>& src )
|
||||||
{
|
{
|
||||||
Id = src.Id;
|
xRegisterBase<OperandType>::Id = src.Id;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
template< typename OperandType >
|
||||||
|
class xRegisterSIMD : public xRegisterBase<OperandType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const xRegisterSIMD Empty; // defined as an empty/unused value (-1)
|
||||||
|
|
||||||
|
public:
|
||||||
|
xRegisterSIMD(): xRegisterBase<OperandType>() {}
|
||||||
|
xRegisterSIMD( const xRegisterSIMD& src ) : xRegisterBase<OperandType>( src.Id ) {}
|
||||||
|
explicit xRegisterSIMD( const xRegisterBase<OperandType>& src ) : xRegisterBase<OperandType>( src ) {}
|
||||||
|
explicit xRegisterSIMD( int regId ) : xRegisterBase<OperandType>( regId ) {}
|
||||||
|
|
||||||
|
bool operator==( const xRegisterSIMD<OperandType>& src ) const { return Id == src.Id; }
|
||||||
|
bool operator!=( const xRegisterSIMD<OperandType>& src ) const { return Id != src.Id; }
|
||||||
|
|
||||||
|
xRegisterSIMD<OperandType>& operator=( const xRegisterSIMD<OperandType>& src )
|
||||||
|
{
|
||||||
|
xRegisterBase<OperandType>::Id = src.Id;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -260,8 +281,8 @@ namespace x86Emitter
|
||||||
// all about the the templated code in haphazard fashion. Yay.. >_<
|
// all about the the templated code in haphazard fashion. Yay.. >_<
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef xRegister<u128> xRegisterSSE;
|
typedef xRegisterSIMD<u128> xRegisterSSE;
|
||||||
typedef xRegister<u64> xRegisterMMX;
|
typedef xRegisterSIMD<u64> xRegisterMMX;
|
||||||
typedef xRegister<u32> xRegister32;
|
typedef xRegister<u32> xRegister32;
|
||||||
typedef xRegister<u16> xRegister16;
|
typedef xRegister<u16> xRegister16;
|
||||||
typedef xRegister<u8> xRegister8;
|
typedef xRegister<u8> xRegister8;
|
||||||
|
@ -624,9 +645,9 @@ namespace x86Emitter
|
||||||
xSmartJump( JccComparisonType ccType )
|
xSmartJump( JccComparisonType ccType )
|
||||||
{
|
{
|
||||||
jASSUME( ccType != Jcc_Unknown );
|
jASSUME( ccType != Jcc_Unknown );
|
||||||
m_baseptr = iGetPtr();
|
m_baseptr = xGetPtr();
|
||||||
m_cc = ccType;
|
m_cc = ccType;
|
||||||
iAdvancePtr( GetMaxInstructionSize() );
|
xAdvancePtr( GetMaxInstructionSize() );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -662,18 +683,69 @@ namespace x86Emitter
|
||||||
//
|
//
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
extern void ModRM( uint mod, uint reg, uint rm );
|
extern void SimdPrefix( u8 prefix, u16 opcode );
|
||||||
extern void ModRM_Direct( uint reg, uint rm );
|
extern void EmitSibMagic( uint regfield, const void* address );
|
||||||
extern void SibSB( u32 ss, u32 index, u32 base );
|
|
||||||
extern void xWriteDisp( int regfield, s32 displacement );
|
|
||||||
extern void xWriteDisp( int regfield, const void* address );
|
|
||||||
|
|
||||||
extern void EmitSibMagic( uint regfield, const ModSibBase& info );
|
extern void EmitSibMagic( uint regfield, const ModSibBase& info );
|
||||||
|
extern void iJccKnownTarget( JccComparisonType comparison, void* target, bool slideForward );
|
||||||
|
|
||||||
|
|
||||||
|
// Writes a ModRM byte for "Direct" register access forms, which is used for all
|
||||||
|
// instructions taking a form of [reg,reg].
|
||||||
|
template< typename T > __emitinline
|
||||||
|
void EmitSibMagic( uint reg1, const xRegisterBase<T>& reg2 )
|
||||||
|
{
|
||||||
|
xWrite8( (Mod_Direct << 6) | (reg1 << 3) | reg2.Id );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void EmitSibMagic( const xRegisterBase<T1> reg1, const xRegisterBase<T2>& reg2 )
|
||||||
|
{
|
||||||
|
xWrite8( (Mod_Direct << 6) | (reg1.Id << 3) | reg2.Id );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T1 > __emitinline
|
||||||
|
void EmitSibMagic( const xRegisterBase<T1> reg1, const void* src ) { EmitSibMagic( reg1.Id, src ); }
|
||||||
|
|
||||||
|
template< typename T1 > __emitinline
|
||||||
|
void EmitSibMagic( const xRegisterBase<T1> reg1, const ModSibBase& sib ) { EmitSibMagic( reg1.Id, sib ); }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void xOpWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 )
|
||||||
|
{
|
||||||
|
if( prefix != 0 )
|
||||||
|
xWrite16( (opcode<<8) | prefix );
|
||||||
|
else
|
||||||
|
xWrite8( opcode );
|
||||||
|
|
||||||
|
EmitSibMagic( param1, param2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2 )
|
||||||
|
{
|
||||||
|
SimdPrefix( prefix, opcode );
|
||||||
|
EmitSibMagic( param1, param2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2, u8 imm8 )
|
||||||
|
{
|
||||||
|
xOpWrite0F( prefix, opcode, param1, param2 );
|
||||||
|
xWrite8( imm8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2 ) { xOpWrite0F( 0, opcode, param1, param2 ); }
|
||||||
|
|
||||||
|
template< typename T1, typename T2 > __emitinline
|
||||||
|
void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2, u8 imm8 ) { xOpWrite0F( 0, opcode, param1, param2, imm8 ); }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename T > bool Is8BitOp() { return sizeof(T) == 1; }
|
template< typename T > bool Is8BitOp() { return sizeof(T) == 1; }
|
||||||
template< typename T > void prefix16() { if( sizeof(T) == 2 ) xWrite<u8>( 0x66 ); }
|
template< typename T > void prefix16() { if( sizeof(T) == 2 ) xWrite8( 0x66 ); }
|
||||||
|
|
||||||
#include "implement/xmm/basehelpers.h"
|
#include "implement/xmm/basehelpers.h"
|
||||||
#include "implement/xmm/moremovs.h"
|
#include "implement/xmm/moremovs.h"
|
||||||
|
@ -686,7 +758,6 @@ namespace x86Emitter
|
||||||
#include "implement/movs.h" // cmov and movsx/zx
|
#include "implement/movs.h" // cmov and movsx/zx
|
||||||
#include "implement/dwshift.h" // doubleword shifts!
|
#include "implement/dwshift.h" // doubleword shifts!
|
||||||
#include "implement/incdec.h"
|
#include "implement/incdec.h"
|
||||||
#include "implement/bittest.h"
|
|
||||||
#include "implement/test.h"
|
#include "implement/test.h"
|
||||||
#include "implement/jmpcall.h"
|
#include "implement/jmpcall.h"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue