mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
79 lines
2.3 KiB
C++
79 lines
2.3 KiB
C++
/*
|
|
Copyright (C) 2006 StrmnNrmn
|
|
|
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
#include "Base/Types.h"
|
|
#include "DynaRec/AssemblyUtils.h"
|
|
|
|
namespace AssemblyUtils
|
|
{
|
|
|
|
//*****************************************************************************
|
|
// Patch a long jump to target the specified location.
|
|
// Return true if the patching succeeded (i.e. within range), false otherwise
|
|
//*****************************************************************************
|
|
bool PatchJumpLong( CJumpLocation jump, CCodeLabel target )
|
|
{
|
|
const u32 JUMP_DIRECT_LONG_LENGTH = 5;
|
|
const u32 JUMP_LONG_LENGTH = 6;
|
|
|
|
u8 * p_jump_addr( reinterpret_cast< u8 * >( jump.GetWritableU8P() ) );
|
|
u32 instruction_length;
|
|
u32 * p_jump_instr_offset;
|
|
|
|
if( *p_jump_addr == 0xe8 || *p_jump_addr == 0xe9 )
|
|
{
|
|
// call/jmp
|
|
instruction_length = JUMP_DIRECT_LONG_LENGTH;
|
|
p_jump_instr_offset = reinterpret_cast< u32 * >( p_jump_addr + 1 );
|
|
}
|
|
else if( *p_jump_addr == 0x0f )
|
|
{
|
|
// jne etc
|
|
instruction_length = JUMP_LONG_LENGTH;
|
|
p_jump_instr_offset = reinterpret_cast< u32 * >( p_jump_addr + 2 );
|
|
}
|
|
else
|
|
{
|
|
DAEDALUS_ERROR( "Unhandled jump type" );
|
|
return false;
|
|
}
|
|
|
|
if (jump.IsIn32BitRange(target))
|
|
{
|
|
// All jumps are 32 bit offsets, and so always succeed.
|
|
*p_jump_instr_offset = jump.GetOffset(target) - instruction_length;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
DAEDALUS_ERROR( "Jump out of range" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// As above no (need to flush on intel)
|
|
//*****************************************************************************
|
|
bool PatchJumpLongAndFlush( CJumpLocation jump, CCodeLabel target )
|
|
{
|
|
return PatchJumpLong( jump, target );
|
|
}
|
|
|
|
}
|