mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 17:26:48 +02:00
Add helper class for ARM/Thumb assembly functions (#127)
Replaces static helper functions in
Sdk5DsiSdCardRedirectPatch.cpp
LastWindowCrcPatch.h
CardiTryReadCardDmaPatch.cpp
This commit is contained in:
63
common/ArmHelper.h
Normal file
63
common/ArmHelper.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Class containing helper functions for manipulating ARM or Thumb assembly.
|
||||
class ArmHelper
|
||||
{
|
||||
public:
|
||||
ArmHelper() = delete;
|
||||
|
||||
/// @brief Check if an ARM instruction is an unconditional bl call.
|
||||
/// @param instruction The ARM instruction to check.
|
||||
/// @return True if the instruction is an unconditional bl call, false otherwise.
|
||||
static bool IsArmUnconditionalBl(u32 instruction)
|
||||
{
|
||||
return (instruction >> 24) == 0xEB;
|
||||
}
|
||||
|
||||
/// @brief Get the offset of an ARM call (bl or blx).
|
||||
/// @param callInstruction The ARM call instruction.
|
||||
/// @return The offset to the destination function. +1 if Thumb.
|
||||
static s32 GetArmCallOffset(u32 callInstruction)
|
||||
{
|
||||
return 8 + ((int)((callInstruction & 0xFFFFFF) << 8) >> 6)
|
||||
+ ((callInstruction >> 24) == 0xFA ? 1 : 0);
|
||||
}
|
||||
|
||||
/// @brief Get the address of the callee in an ARM call (bl or blx).
|
||||
/// @param instructionPointer Pointer to the ARM call instruction.
|
||||
/// @return The address of the function being called. +1 if Thumb.
|
||||
static u32 GetArmCallAddress(const void* instructionPointer)
|
||||
{
|
||||
auto pc = (const u32*)((u32)instructionPointer & ~3);
|
||||
return (u32)pc + GetArmCallOffset(*pc);
|
||||
}
|
||||
|
||||
/// @brief Create an ARM call instruction (bl or blx).
|
||||
/// @param instructionAddress The address where the instruction is to be placed.
|
||||
/// @param targetAddress The address of the function to call. +1 if Thumb.
|
||||
/// @return The ARM call instruction to call the target.
|
||||
static u32 MakeArmCall(u32 instructionAddress, u32 targetAddress)
|
||||
{
|
||||
u32 offset = targetAddress - instructionAddress - 8;
|
||||
return ((targetAddress & 1) ? 0xFA000000 : 0xEB000000) | ((offset >> 2) & 0xFFFFFF);
|
||||
}
|
||||
|
||||
/// @brief Get the offset of a Thumb call (bl or blx).
|
||||
/// @param callInstruction1 The first Thumb call instruction.
|
||||
/// @param callInstruction2 The second Thumb call instruction.
|
||||
/// @return The offset to the destination function. +1 if Thumb.
|
||||
static s32 GetThumbCallOffset(u16 callInstruction1, u16 callInstruction2)
|
||||
{
|
||||
return 4 + ((int)((((callInstruction1 & 0x7FF) << 11) | (callInstruction2 & 0x7FF)) << 10) >> 9)
|
||||
+ ((callInstruction2 >> 11) == 0x1F ? 1 : 0);
|
||||
}
|
||||
|
||||
/// @brief Get the address of the callee in an Thumb call (bl or blx).
|
||||
/// @param instructionPointer Pointer to the first Thumb call instruction.
|
||||
/// @return The offset to the destination function. +1 if Thumb.
|
||||
static u32 GetThumbCallAddress(const void* instructionPointer)
|
||||
{
|
||||
auto pc = (const u16*)((u32)instructionPointer & ~1);
|
||||
return (u32)pc + GetThumbCallOffset(pc[0], pc[1]);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user