From b4771030d3222571bfcf0bca8dd66718476af8e1 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 30 Jul 2014 18:18:10 -0500 Subject: [PATCH] Fix a couple issues in the x86emitter on x86_64. This won't fix the billions of errors that will happen at runtime of using the x86 emitter, but chooses to make some better coding practice choices that enables it to compile on x86_64. in the xIndirectVoid class, instead of using s32 for the offset, use sptr which will be 32bit or 64bit depending on architecture. This also fixes a few alignment issues in xAddressVoid's constructors. In EmitSibMagic we are casting a void* to s32, which won't work on x86_64, so first do a cast from sptr to s32. Won't work on x86_64, but gets us compiling. --- common/include/x86emitter/x86types.h | 8 +++--- common/src/x86emitter/x86emitter.cpp | 43 ++++++++++++++++------------ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/common/include/x86emitter/x86types.h b/common/include/x86emitter/x86types.h index 8d99e7005f..74f63b02a0 100644 --- a/common/include/x86emitter/x86types.h +++ b/common/include/x86emitter/x86types.h @@ -675,10 +675,10 @@ template< typename T > void xWrite( T val ); class xIndirectVoid : public OperandSizedObject { public: - xAddressReg Base; // base register (no scale) - xAddressReg Index; // index reg gets multiplied by the scale - uint Scale; // scale applied to the index register, in scale/shift form - s32 Displacement; // offset applied to the Base/Index registers. + xAddressReg Base; // base register (no scale) + xAddressReg Index; // index reg gets multiplied by the scale + uint Scale; // scale applied to the index register, in scale/shift form + sptr Displacement; // offset applied to the Base/Index registers. public: explicit xIndirectVoid( s32 disp ); diff --git a/common/src/x86emitter/x86emitter.cpp b/common/src/x86emitter/x86emitter.cpp index bda52c429e..850771e024 100644 --- a/common/src/x86emitter/x86emitter.cpp +++ b/common/src/x86emitter/x86emitter.cpp @@ -226,7 +226,14 @@ static __fi void SibSB( u32 ss, u32 index, u32 base ) void EmitSibMagic( uint regfield, const void* address ) { ModRM( 0, regfield, ModRm_UseDisp32 ); - xWrite( (s32)address ); + + // SIB encoding only supports 32bit offsets, even on x86_64 + // We must make sure that the displacement is within the 32bit range + // Else we will fail out in a spectacular fashion + sptr displacement = (sptr)address; + pxAssertDev(displacement >= -0x80000000LL && displacement < 0x80000000LL, "SIB target is too far away, needs an indirect register"); + + xWrite( (s32)displacement ); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -461,7 +468,7 @@ xAddressVoid xAddressReg::operator-( s32 right ) const xAddressVoid xAddressReg::operator-( const void* right ) const { pxAssertMsg( Id != -1, "Uninitialized x86 register." ); - return xAddressVoid( *this, -(s32)right ); + return xAddressVoid( *this, -(sptr)right ); } xAddressVoid xAddressReg::operator*( u32 factor ) const @@ -483,10 +490,10 @@ xAddressVoid xAddressReg::operator<<( u32 shift ) const xAddressVoid::xAddressVoid( const xAddressReg& base, const xAddressReg& index, int factor, s32 displacement ) { - Base = base; - Index = index; - Factor = factor; - Displacement= displacement; + Base = base; + Index = index; + Factor = factor; + Displacement = displacement; pxAssertMsg( base.Id != xRegId_Invalid, "Uninitialized x86 register." ); pxAssertMsg( index.Id != xRegId_Invalid, "Uninitialized x86 register." ); @@ -494,28 +501,28 @@ xAddressVoid::xAddressVoid( const xAddressReg& base, const xAddressReg& index, i xAddressVoid::xAddressVoid( const xAddressReg& index, int displacement ) { - Base = xEmptyReg; - Index = index; - Factor = 0; - Displacement= displacement; + Base = xEmptyReg; + Index = index; + Factor = 0; + Displacement = displacement; pxAssertMsg( index.Id != xRegId_Invalid, "Uninitialized x86 register." ); } xAddressVoid::xAddressVoid( s32 displacement ) { - Base = xEmptyReg; - Index = xEmptyReg; - Factor = 0; - Displacement= displacement; + Base = xEmptyReg; + Index = xEmptyReg; + Factor = 0; + Displacement = displacement; } xAddressVoid::xAddressVoid( const void* displacement ) { - Base = xEmptyReg; - Index = xEmptyReg; - Factor = 0; - Displacement= (s32)displacement; + Base = xEmptyReg; + Index = xEmptyReg; + Factor = 0; + Displacement = (sptr)displacement; } xAddressVoid& xAddressVoid::Add( const xAddressReg& src )