void xImpl_Test::operator()( const xIndirect32orLess& dest, int imm ) const { dest.prefix16(); xWrite8( dest.Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( 0, dest ); dest.xWriteImm( imm ); }
void xImpl_Group2::operator()(const xRegisterInt& to, u8 imm ) const { if( imm == 0 ) return; to.prefix16(); if( imm == 1 ) { // special encoding of 1's xWrite8( to.Is8BitOp() ? 0xd0 : 0xd1 ); EmitSibMagic( InstType, to ); } else { xWrite8( to.Is8BitOp() ? 0xc0 : 0xc1 ); EmitSibMagic( InstType, to ); xWrite8( imm ); } }
void xImpl_Group2::operator()( const xIndirect32orLess& sibdest, u8 imm ) const { if( imm == 0 ) return; sibdest.prefix16(); if( imm == 1 ) { // special encoding of 1's xWrite8( sibdest.Is8BitOp() ? 0xd0 : 0xd1 ); EmitSibMagic( InstType, sibdest ); } else { xWrite8( sibdest.Is8BitOp() ? 0xc0 : 0xc1 ); EmitSibMagic( InstType, sibdest ); xWrite8( imm ); } }
static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, int imm ) { to.prefix16(); if( !to.Is8BitOp() && is_s8( imm ) ) { xWrite8( 0x83 ); EmitSibMagic( InstType, to ); xWrite<s8>( imm ); } else { if( to.IsAccumulator() ) xWrite8( (to.Is8BitOp() ? 4 : 5) | (InstType<<3) ); else { xWrite8( to.Is8BitOp() ? 0x80 : 0x81 ); EmitSibMagic( InstType, to ); } to.xWriteImm( imm ); } }
////////////////////////////////////////////////////////////////////////////////////////// // Conditionally generates Sib encoding information! // // 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. // void EmitSibMagic(uint regfield, const xIndirectVoid &info) { // 3 bits also on x86_64 (so max is 8) // We might need to mask it on x86_64 pxAssertDev(regfield < 8, "Invalid x86 register identifier."); int displacement_size = (info.Displacement == 0) ? 0 : ((info.IsByteSizeDisp()) ? 1 : 2); pxAssert(!info.Base.IsEmpty() || !info.Index.IsEmpty() || displacement_size == 2); if (!NeedsSibMagic(info)) { // Use ModRm-only encoding, with the rm field holding an index/base register, if // one has been specified. If neither register is specified then use Disp32 form, // which is encoded as "EBP w/o displacement" (which is why EBP must always be // encoded *with* a displacement of 0, if it would otherwise not have one). if (info.Index.IsEmpty()) { EmitSibMagic(regfield, (void *)info.Displacement); return; } else { if (info.Index == ebp && displacement_size == 0) displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! ModRM(displacement_size, regfield, info.Index.Id); } } else { // In order to encode "just" index*scale (and no base), we have to encode // it as a special [index*scale + displacement] form, which is done by // specifying EBP as the base register and setting the displacement field // to zero. (same as ModRm w/o SIB form above, basically, except the // ModRm_UseDisp flag is specified in the SIB instead of the ModRM field). if (info.Base.IsEmpty()) { ModRM(0, regfield, ModRm_UseSib); SibSB(info.Scale, info.Index.Id, ModRm_UseDisp32); xWrite<s32>(info.Displacement); return; } else { if (info.Base == ebp && displacement_size == 0) displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! ModRM(displacement_size, regfield, ModRm_UseSib); SibSB(info.Scale, info.Index.Id, info.Base.Id); } } if (displacement_size != 0) { if (displacement_size == 1) xWrite<s8>(info.Displacement); else xWrite<s32>(info.Displacement); } }
void xImpl_IncDec::operator()( const xRegisterInt& to ) const { if( to.Is8BitOp() ) { xWrite8( 0xfe ); EmitSibMagic( isDec ? 1 : 0, to ); } else { to.prefix16(); xWrite8( (isDec ? 0x48 : 0x40) | to.Id ); } }
void xImpl_Test::operator()( const xRegisterInt& to, int imm ) const { to.prefix16(); if( to.IsAccumulator() ) xWrite8( to.Is8BitOp() ? 0xa8 : 0xa9 ); else { xWrite8( to.Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( 0, to ); } to.xWriteImm( imm ); }
static void _g1_EmitOp( G1Type InstType, const xIndirectVoid& sibdest, const xRegisterInt& from ) { from.prefix16(); xWrite8( (from.Is8BitOp() ? 0 : 1) | (InstType<<3) ); EmitSibMagic( from, sibdest ); }
static void _g3_EmitOp( G3Type InstType, const xIndirect32orLess& from ) { from.prefix16(); xWrite8( from.Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( InstType, from ); }
static void _g3_EmitOp( G3Type InstType, const xRegisterInt& from ) { from.prefix16(); xWrite8(from.Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( InstType, from ); }
__emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data ) { SimdPrefix( prefix, opcode ); EmitSibMagic( instId, data ); }
void xImpl_Group2::operator()( const xIndirect32orLess& sibdest, const xRegisterCL& /* from */ ) const { sibdest.prefix16(); xWrite8( sibdest.Is8BitOp() ? 0xd2 : 0xd3 ); EmitSibMagic( InstType, sibdest ); }
void EmitSibMagic( const xRegisterBase& reg1, const void* src ) { EmitSibMagic( reg1.Id, src ); }
void xImpl_Test::operator()( const xRegister32& to, const xRegister32& from ) const { xWrite8( 0x85 ); EmitSibMagic( from, to ); }
__emitinline void xPUSH( const xIndirectVoid& from ) { xWrite8( 0xff ); EmitSibMagic( 6, from ); }
////////////////////////////////////////////////////////////////////////////////////////// // emitter helpers for xmm instruction with prefixes, most of which are using // the basic opcode format (items inside braces denote optional or conditional // emission): // // [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB] // // Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or // 0x3a [and other value will result in assertion failue]. // __emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const xIndirectVoid& sib ) { SimdPrefix( prefix, opcode ); EmitSibMagic( instId, sib ); }
void xImpl_IncDec::operator()( const xIndirect32orLess& to ) const { to.prefix16(); xWrite8( to.Is8BitOp() ? 0xfe : 0xff ); EmitSibMagic( isDec ? 1 : 0, to ); }
void EmitSibMagic( const xRegisterBase& reg1, const xIndirectVoid& sib ) { EmitSibMagic( reg1.Id, sib ); }
static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xIndirectVoid& sibsrc ) { to.prefix16(); xWrite8( (to.Is8BitOp() ? 2 : 3) | (InstType<<3) ); EmitSibMagic( to, sibsrc ); }
void xImpl_Group2::operator()( const xRegisterInt& to, const xRegisterCL& /* from */ ) const { to.prefix16(); xWrite8( to.Is8BitOp() ? 0xd2 : 0xd3 ); EmitSibMagic( InstType, to ); }
__emitinline void xPOP( const xIndirectVoid& from ) { xWrite8( 0x8f ); EmitSibMagic( 0, from ); }
void xImpl_Test::operator()( const xRegister16& to, const xRegister16& from ) const { to.prefix16(); xWrite8( 0x85 ); EmitSibMagic( from, to ); }