mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-08-08 06:16:31 +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)
|
public static void EmitCall(ArmEmitterContext context, ulong immediate)
|
||||||
{
|
{
|
||||||
|
if (context.IsSingleStep)
|
||||||
|
{
|
||||||
|
context.Return(Const(immediate));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool isRecursive = immediate == context.EntryAddress;
|
bool isRecursive = immediate == context.EntryAddress;
|
||||||
|
|
||||||
if (isRecursive)
|
if (isRecursive)
|
||||||
@ -156,13 +162,25 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitVirtualCall(ArmEmitterContext context, Operand target)
|
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);
|
EmitTableBranch(context, target, isJump: false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
public static void EmitVirtualJump(ArmEmitterContext context, Operand target, bool isReturn)
|
||||||
{
|
{
|
||||||
if (isReturn)
|
if (isReturn || context.IsSingleStep)
|
||||||
{
|
{
|
||||||
if (target.Type == OperandType.I32)
|
if (target.Type == OperandType.I32)
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,7 @@ namespace ARMeilleure.Translation
|
|||||||
public bool HighCq { get; }
|
public bool HighCq { get; }
|
||||||
public bool HasPtc { get; }
|
public bool HasPtc { get; }
|
||||||
public Aarch32Mode Mode { get; }
|
public Aarch32Mode Mode { get; }
|
||||||
|
public bool IsSingleStep { get; }
|
||||||
|
|
||||||
private int _ifThenBlockStateIndex = 0;
|
private int _ifThenBlockStateIndex = 0;
|
||||||
private Condition[] _ifThenBlockState = [];
|
private Condition[] _ifThenBlockState = [];
|
||||||
@ -66,7 +67,8 @@ namespace ARMeilleure.Translation
|
|||||||
ulong entryAddress,
|
ulong entryAddress,
|
||||||
bool highCq,
|
bool highCq,
|
||||||
bool hasPtc,
|
bool hasPtc,
|
||||||
Aarch32Mode mode)
|
Aarch32Mode mode,
|
||||||
|
bool isSingleStep)
|
||||||
{
|
{
|
||||||
Memory = memory;
|
Memory = memory;
|
||||||
CountTable = countTable;
|
CountTable = countTable;
|
||||||
@ -76,6 +78,7 @@ namespace ARMeilleure.Translation
|
|||||||
HighCq = highCq;
|
HighCq = highCq;
|
||||||
HasPtc = hasPtc;
|
HasPtc = hasPtc;
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
|
IsSingleStep = isSingleStep;
|
||||||
|
|
||||||
_labels = new Dictionary<ulong, Operand>();
|
_labels = new Dictionary<ulong, Operand>();
|
||||||
}
|
}
|
||||||
|
@ -195,22 +195,6 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
private ulong Step(State.ExecutionContext context, ulong address)
|
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);
|
TranslatedFunction func = Translate(address, context.ExecutionMode, highCq: false, singleStep: true);
|
||||||
|
|
||||||
address = func.Execute(Stubs.ContextWrapper, context);
|
address = func.Execute(Stubs.ContextWrapper, context);
|
||||||
@ -220,93 +204,7 @@ namespace ARMeilleure.Translation
|
|||||||
return address;
|
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)
|
internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||||
{
|
{
|
||||||
@ -351,7 +249,8 @@ namespace ARMeilleure.Translation
|
|||||||
address,
|
address,
|
||||||
highCq,
|
highCq,
|
||||||
_ptc.State != PtcState.Disabled,
|
_ptc.State != PtcState.Disabled,
|
||||||
mode: Aarch32Mode.User);
|
mode: Aarch32Mode.User,
|
||||||
|
isSingleStep: singleStep);
|
||||||
|
|
||||||
Logger.StartPass(PassName.Decoding);
|
Logger.StartPass(PassName.Decoding);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user