mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-08-08 14:27:07 +00:00
gdb: Improve stepping (ryubing/ryujinx!106)
See merge request ryubing/ryujinx!106
This commit is contained in:
parent
d22756f1bd
commit
54d4d184f4
@ -143,6 +143,12 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
public static void EmitCall(ArmEmitterContext context, ulong immediate)
|
||||
{
|
||||
if (context.IsSingleStep)
|
||||
{
|
||||
context.Return(Const(immediate));
|
||||
return;
|
||||
}
|
||||
|
||||
bool isRecursive = immediate == context.EntryAddress;
|
||||
|
||||
if (isRecursive)
|
||||
@ -156,13 +162,25 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
|
||||
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
|
||||
{
|
||||
if (context.IsSingleStep)
|
||||
{
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
target = context.ZeroExtend32(OperandType.I64, target);
|
||||
}
|
||||
|
||||
context.Return(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitTableBranch(context, target, isJump: false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
||||
{
|
||||
if (isReturn)
|
||||
if (isReturn || context.IsSingleStep)
|
||||
{
|
||||
if (target.Type == OperandType.I32)
|
||||
{
|
||||
|
@ -52,6 +52,7 @@ namespace ARMeilleure.Translation
|
||||
public bool HighCq { get; }
|
||||
public bool HasPtc { get; }
|
||||
public Aarch32Mode Mode { get; }
|
||||
public bool IsSingleStep { get; }
|
||||
|
||||
private int _ifThenBlockStateIndex = 0;
|
||||
private Condition[] _ifThenBlockState = [];
|
||||
@ -66,7 +67,8 @@ namespace ARMeilleure.Translation
|
||||
ulong entryAddress,
|
||||
bool highCq,
|
||||
bool hasPtc,
|
||||
Aarch32Mode mode)
|
||||
Aarch32Mode mode,
|
||||
bool isSingleStep)
|
||||
{
|
||||
Memory = memory;
|
||||
CountTable = countTable;
|
||||
@ -76,6 +78,7 @@ namespace ARMeilleure.Translation
|
||||
HighCq = highCq;
|
||||
HasPtc = hasPtc;
|
||||
Mode = mode;
|
||||
IsSingleStep = isSingleStep;
|
||||
|
||||
_labels = new Dictionary<ulong, Operand>();
|
||||
}
|
||||
|
@ -195,22 +195,6 @@ namespace ARMeilleure.Translation
|
||||
|
||||
private ulong Step(State.ExecutionContext context, ulong address)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpCode opCode = Decoder.DecodeOpCode(Memory, address, context.ExecutionMode);
|
||||
|
||||
// For branch instructions during single-stepping, we handle them manually
|
||||
// func.Execute() will sometimes execute the entire function call, which is not what we want
|
||||
if (opCode.Instruction.Name is InstName.Bl or InstName.Blr or InstName.Blx or InstName.Br)
|
||||
{
|
||||
return ExecuteBranchInstructionForStepping(context, address, opCode);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
|
||||
|
||||
address = func.Execute(Stubs.ContextWrapper, context);
|
||||
@ -220,93 +204,7 @@ namespace ARMeilleure.Translation
|
||||
return address;
|
||||
}
|
||||
|
||||
private static ulong ExecuteBranchInstructionForStepping(State.ExecutionContext context, ulong address, OpCode opCode)
|
||||
{
|
||||
switch (opCode.Instruction.Name)
|
||||
{
|
||||
case InstName.Bl:
|
||||
if (opCode is IOpCodeBImm opBImm)
|
||||
{
|
||||
// Set link register
|
||||
if (context.ExecutionMode == ExecutionMode.Aarch64)
|
||||
{
|
||||
context.SetX(30, address + (ulong)opCode.OpCodeSizeInBytes); // LR = X30
|
||||
}
|
||||
else
|
||||
{
|
||||
// For ARM32, need to set the appropriate return address
|
||||
uint returnAddr = opCode is OpCode32 op32 && op32.IsThumb
|
||||
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u // Thumb bit set
|
||||
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
|
||||
context.SetX(14, returnAddr); // LR = R14
|
||||
}
|
||||
return (ulong)opBImm.Immediate;
|
||||
}
|
||||
break;
|
||||
|
||||
case InstName.Blr:
|
||||
if (opCode is OpCodeBReg opBReg)
|
||||
{
|
||||
// Set link register
|
||||
if (context.ExecutionMode == ExecutionMode.Aarch64)
|
||||
{
|
||||
context.SetX(30, address + (ulong)opCode.OpCodeSizeInBytes); // LR = X30
|
||||
}
|
||||
else
|
||||
{
|
||||
uint returnAddr = opCode is OpCode32 op32 && op32.IsThumb
|
||||
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u // Thumb bit set
|
||||
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
|
||||
context.SetX(14, returnAddr); // LR = R14
|
||||
}
|
||||
return context.GetX(opBReg.Rn);
|
||||
}
|
||||
break;
|
||||
|
||||
case InstName.Blx:
|
||||
if (opCode is IOpCodeBImm opBlxImm)
|
||||
{
|
||||
// Handle mode switching for BLX
|
||||
if (opCode is OpCode32 op32)
|
||||
{
|
||||
uint returnAddr = op32.IsThumb
|
||||
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u
|
||||
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
|
||||
context.SetX(14, returnAddr);
|
||||
|
||||
// BLX switches between ARM and Thumb modes
|
||||
context.SetPstateFlag(PState.TFlag, !op32.IsThumb);
|
||||
}
|
||||
return (ulong)opBlxImm.Immediate;
|
||||
}
|
||||
else if (opCode is IOpCode32BReg opBlxReg)
|
||||
{
|
||||
if (opCode is OpCode32 op32)
|
||||
{
|
||||
uint returnAddr = op32.IsThumb
|
||||
? (uint)address + (uint)opCode.OpCodeSizeInBytes | 1u
|
||||
: (uint)address + (uint)opCode.OpCodeSizeInBytes;
|
||||
context.SetX(14, returnAddr);
|
||||
|
||||
// For BLX register, the target address determines the mode
|
||||
ulong targetAddr = context.GetX(opBlxReg.Rm);
|
||||
context.SetPstateFlag(PState.TFlag, (targetAddr & 1) != 0);
|
||||
return targetAddr & ~1UL; // Clear the Thumb bit for the actual address
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case InstName.Br:
|
||||
if (opCode is OpCodeBReg opBr)
|
||||
{
|
||||
// BR doesn't set link register, just branches to the target
|
||||
return context.GetX(opBr.Rn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Unhandled branch instruction: {opCode.Instruction.Name}");
|
||||
}
|
||||
|
||||
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||
{
|
||||
@ -351,7 +249,8 @@ namespace ARMeilleure.Translation
|
||||
address,
|
||||
highCq,
|
||||
_ptc.State != PtcState.Disabled,
|
||||
mode: Aarch32Mode.User);
|
||||
mode: Aarch32Mode.User,
|
||||
isSingleStep: singleStep);
|
||||
|
||||
Logger.StartPass(PassName.Decoding);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user