Only throw undefined instruction exception at execution, not at translation stage
This commit is contained in:
parent
9f612682e0
commit
55743c0cba
28 changed files with 94 additions and 43 deletions
|
@ -161,7 +161,7 @@ namespace ChocolArm64.Decoder
|
||||||
|
|
||||||
AInst Inst = AOpCodeTable.GetInst(OpCode);
|
AInst Inst = AOpCodeTable.GetInst(OpCode);
|
||||||
|
|
||||||
AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position);
|
AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode);
|
||||||
|
|
||||||
if (Inst.Type != null)
|
if (Inst.Type != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,14 +6,16 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
class AOpCode : IAOpCode
|
class AOpCode : IAOpCode
|
||||||
{
|
{
|
||||||
public long Position { get; private set; }
|
public long Position { get; private set; }
|
||||||
|
public int RawOpCode { get; private set; }
|
||||||
|
|
||||||
public AInstEmitter Emitter { get; protected set; }
|
public AInstEmitter Emitter { get; protected set; }
|
||||||
public ARegisterSize RegisterSize { get; protected set; }
|
public ARegisterSize RegisterSize { get; protected set; }
|
||||||
|
|
||||||
public AOpCode(AInst Inst, long Position)
|
public AOpCode(AInst Inst, long Position, int OpCode)
|
||||||
{
|
{
|
||||||
this.Position = Position;
|
this.Position = Position;
|
||||||
|
this.RawOpCode = OpCode;
|
||||||
|
|
||||||
RegisterSize = ARegisterSize.Int64;
|
RegisterSize = ARegisterSize.Int64;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Rd { get; private set; }
|
public int Rd { get; private set; }
|
||||||
public long Imm { get; private set; }
|
public long Imm { get; private set; }
|
||||||
|
|
||||||
public AOpCodeAdr(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeAdr(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = OpCode & 0x1f;
|
Rd = OpCode & 0x1f;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder
|
||||||
|
|
||||||
public ADataOp DataOp { get; private set; }
|
public ADataOp DataOp { get; private set; }
|
||||||
|
|
||||||
public AOpCodeAlu(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeAlu(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
Rd = (OpCode >> 0) & 0x1f;
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
Rn = (OpCode >> 5) & 0x1f;
|
||||||
|
|
|
@ -6,6 +6,6 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
public long Imm { get; protected set; }
|
public long Imm { get; protected set; }
|
||||||
|
|
||||||
public AOpCodeBImm(AInst Inst, long Position) : base(Inst, Position) { }
|
public AOpCodeBImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
class AOpCodeBImmAl : AOpCodeBImm
|
class AOpCodeBImmAl : AOpCodeBImm
|
||||||
{
|
{
|
||||||
public AOpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Imm = Position + ADecoderHelper.DecodeImm26_2(OpCode);
|
Imm = Position + ADecoderHelper.DecodeImm26_2(OpCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
public int Rt { get; private set; }
|
public int Rt { get; private set; }
|
||||||
|
|
||||||
public AOpCodeBImmCmp(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeBImmCmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rt = OpCode & 0x1f;
|
Rt = OpCode & 0x1f;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
public ACond Cond { get; private set; }
|
public ACond Cond { get; private set; }
|
||||||
|
|
||||||
public AOpCodeBImmCond(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeBImmCond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int O0 = (OpCode >> 4) & 1;
|
int O0 = (OpCode >> 4) & 1;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Rt { get; private set; }
|
public int Rt { get; private set; }
|
||||||
public int Pos { get; private set; }
|
public int Pos { get; private set; }
|
||||||
|
|
||||||
public AOpCodeBImmTest(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeBImmTest(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rt = OpCode & 0x1f;
|
Rt = OpCode & 0x1f;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
public int Rn { get; private set; }
|
public int Rn { get; private set; }
|
||||||
|
|
||||||
public AOpCodeBReg(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeBReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int Op4 = (OpCode >> 0) & 0x1f;
|
int Op4 = (OpCode >> 0) & 0x1f;
|
||||||
int Op2 = (OpCode >> 16) & 0x1f;
|
int Op2 = (OpCode >> 16) & 0x1f;
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
public int Id { get; private set; }
|
public int Id { get; private set; }
|
||||||
|
|
||||||
public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Id = (OpCode >> 5) & 0xffff;
|
Id = (OpCode >> 5) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Size { get; protected set; }
|
public int Size { get; protected set; }
|
||||||
public bool Extend64 { get; protected set; }
|
public bool Extend64 { get; protected set; }
|
||||||
|
|
||||||
public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rt = (OpCode >> 0) & 0x1f;
|
Rt = (OpCode >> 0) & 0x1f;
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
Rn = (OpCode >> 5) & 0x1f;
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder
|
||||||
public bool Signed { get; private set; }
|
public bool Signed { get; private set; }
|
||||||
public bool Prefetch { get; private set; }
|
public bool Prefetch { get; private set; }
|
||||||
|
|
||||||
public AOpCodeMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rt = OpCode & 0x1f;
|
Rt = OpCode & 0x1f;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder
|
||||||
public long Imm { get; private set; }
|
public long Imm { get; private set; }
|
||||||
public int Pos { get; private set; }
|
public int Pos { get; private set; }
|
||||||
|
|
||||||
public AOpCodeMov(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeMov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int P1 = (OpCode >> 22) & 1;
|
int P1 = (OpCode >> 22) & 1;
|
||||||
int SF = (OpCode >> 31) & 1;
|
int SF = (OpCode >> 31) & 1;
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace ChocolArm64.Decoder
|
||||||
|
|
||||||
public int SizeF => Size & 1;
|
public int SizeF => Size & 1;
|
||||||
|
|
||||||
public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
Rd = (OpCode >> 0) & 0x1f;
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
Rn = (OpCode >> 5) & 0x1f;
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace ChocolArm64.Decoder
|
||||||
public long Imm { get; private set; }
|
public long Imm { get; private set; }
|
||||||
public int Size { get; private set; }
|
public int Size { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdFmov(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdFmov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int Imm5 = (OpCode >> 5) & 0x1f;
|
int Imm5 = (OpCode >> 5) & 0x1f;
|
||||||
int Type = (OpCode >> 22) & 0x3;
|
int Type = (OpCode >> 22) & 0x3;
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder
|
||||||
public long Imm { get; private set; }
|
public long Imm { get; private set; }
|
||||||
public int Size { get; private set; }
|
public int Size { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdImm(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = OpCode & 0x1f;
|
Rd = OpCode & 0x1f;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder
|
||||||
public bool Signed => false;
|
public bool Signed => false;
|
||||||
public bool Prefetch => false;
|
public bool Prefetch => false;
|
||||||
|
|
||||||
public AOpCodeSimdMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int Opc = (OpCode >> 30) & 3;
|
int Opc = (OpCode >> 30) & 3;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Elems { get; private set; }
|
public int Elems { get; private set; }
|
||||||
public bool WBack { get; private set; }
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
switch ((OpCode >> 12) & 0xf)
|
switch ((OpCode >> 12) & 0xf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder
|
||||||
public bool Replicate { get; private set; }
|
public bool Replicate { get; private set; }
|
||||||
public bool WBack { get; private set; }
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
int Size = (OpCode >> 10) & 3;
|
int Size = (OpCode >> 10) & 3;
|
||||||
int S = (OpCode >> 12) & 1;
|
int S = (OpCode >> 12) & 1;
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Op1 { get; private set; }
|
public int Op1 { get; private set; }
|
||||||
public int Op0 { get; private set; }
|
public int Op0 { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSystem(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSystem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rt = (OpCode >> 0) & 0x1f;
|
Rt = (OpCode >> 0) & 0x1f;
|
||||||
Op2 = (OpCode >> 5) & 0x7;
|
Op2 = (OpCode >> 5) & 0x7;
|
||||||
|
|
|
@ -37,7 +37,21 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Und(AILEmitterCtx Context)
|
public static void Und(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException($"Undefined instruction at {Context.CurrOp.Position:x16}");
|
AOpCode Op = Context.CurrOp;
|
||||||
|
|
||||||
|
Context.EmitStoreState();
|
||||||
|
|
||||||
|
Context.EmitLdarg(ATranslatedSub.RegistersArgIdx);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(Op.Position);
|
||||||
|
Context.EmitLdc_I4(Op.RawOpCode);
|
||||||
|
|
||||||
|
Context.EmitCall(typeof(ARegisters), nameof(ARegisters.OnUndefined));
|
||||||
|
|
||||||
|
if (Context.CurrBlock.Next != null)
|
||||||
|
{
|
||||||
|
Context.EmitLoadState(Context.CurrBlock.Next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,11 @@ using System;
|
||||||
|
|
||||||
namespace ChocolArm64.State
|
namespace ChocolArm64.State
|
||||||
{
|
{
|
||||||
public class AExceptionEventArgs : EventArgs
|
public class AInstExceptEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public int Id { get; private set; }
|
public int Id { get; private set; }
|
||||||
|
|
||||||
public AExceptionEventArgs(int Id)
|
public AInstExceptEventArgs(int Id)
|
||||||
{
|
{
|
||||||
this.Id = Id;
|
this.Id = Id;
|
||||||
}
|
}
|
16
Ryujinx/Cpu/State/AInstUndEventArgs.cs
Normal file
16
Ryujinx/Cpu/State/AInstUndEventArgs.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ChocolArm64.State
|
||||||
|
{
|
||||||
|
public class AInstUndEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public long Position { get; private set; }
|
||||||
|
public int RawOpCode { get; private set; }
|
||||||
|
|
||||||
|
public AInstUndEventArgs(long Position, int RawOpCode)
|
||||||
|
{
|
||||||
|
this.Position = Position;
|
||||||
|
this.RawOpCode = RawOpCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,23 +42,23 @@ namespace ChocolArm64.State
|
||||||
|
|
||||||
public long CntpctEl0 => Environment.TickCount * TicksPerMS;
|
public long CntpctEl0 => Environment.TickCount * TicksPerMS;
|
||||||
|
|
||||||
public event EventHandler<AExceptionEventArgs> Break;
|
public event EventHandler<AInstExceptEventArgs> Break;
|
||||||
public event EventHandler<AExceptionEventArgs> SvcCall;
|
public event EventHandler<AInstExceptEventArgs> SvcCall;
|
||||||
public event EventHandler<EventArgs> Undefined;
|
public event EventHandler<AInstUndEventArgs> Undefined;
|
||||||
|
|
||||||
public void OnBreak(int Imm)
|
public void OnBreak(int Imm)
|
||||||
{
|
{
|
||||||
Break?.Invoke(this, new AExceptionEventArgs(Imm));
|
Break?.Invoke(this, new AInstExceptEventArgs(Imm));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnSvcCall(int Imm)
|
public void OnSvcCall(int Imm)
|
||||||
{
|
{
|
||||||
SvcCall?.Invoke(this, new AExceptionEventArgs(Imm));
|
SvcCall?.Invoke(this, new AInstExceptEventArgs(Imm));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnUndefined()
|
public void OnUndefined(long Position, int RawOpCode)
|
||||||
{
|
{
|
||||||
Undefined?.Invoke(this, EventArgs.Empty);
|
Undefined?.Invoke(this, new AInstUndEventArgs(Position, RawOpCode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
13
Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs
Normal file
13
Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.OsHle.Exceptions
|
||||||
|
{
|
||||||
|
public class UndefinedInstructionException : Exception
|
||||||
|
{
|
||||||
|
private const string ExMsg = "The instruction at 0x{0:x16} (opcode 0x{1:x8}) is undefined!";
|
||||||
|
|
||||||
|
public UndefinedInstructionException() : base() { }
|
||||||
|
|
||||||
|
public UndefinedInstructionException(long Position, int OpCode) : base(string.Format(ExMsg, Position, OpCode)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,25 +137,31 @@ namespace Ryujinx.OsHle
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Registers.Break += BreakHandler;
|
Thread.Registers.Break += BreakHandler;
|
||||||
Thread.Registers.SvcCall += SvcHandler.SvcCall;
|
Thread.Registers.SvcCall += SvcHandler.SvcCall;
|
||||||
Thread.Registers.ProcessId = ProcessId;
|
Thread.Registers.Undefined += UndefinedHandler;
|
||||||
Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId();
|
Thread.Registers.ProcessId = ProcessId;
|
||||||
Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize;
|
Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId();
|
||||||
Thread.Registers.X0 = (ulong)ArgsPtr;
|
Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize;
|
||||||
Thread.Registers.X1 = (ulong)Handle;
|
Thread.Registers.X0 = (ulong)ArgsPtr;
|
||||||
Thread.Registers.X31 = (ulong)StackTop;
|
Thread.Registers.X1 = (ulong)Handle;
|
||||||
|
Thread.Registers.X31 = (ulong)StackTop;
|
||||||
|
|
||||||
Thread.WorkFinished += ThreadFinished;
|
Thread.WorkFinished += ThreadFinished;
|
||||||
|
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BreakHandler(object sender, AExceptionEventArgs e)
|
private void BreakHandler(object sender, AInstExceptEventArgs e)
|
||||||
{
|
{
|
||||||
throw new GuestBrokeExecutionException();
|
throw new GuestBrokeExecutionException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UndefinedHandler(object sender, AInstUndEventArgs e)
|
||||||
|
{
|
||||||
|
throw new UndefinedInstructionException(e.Position, e.RawOpCode);
|
||||||
|
}
|
||||||
|
|
||||||
private int GetFreeTlsSlot(AThread Thread)
|
private int GetFreeTlsSlot(AThread Thread)
|
||||||
{
|
{
|
||||||
for (int Index = 1; Index < TotalTlsSlots; Index++)
|
for (int Index = 1; Index < TotalTlsSlots; Index++)
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Ryujinx.OsHle.Svc
|
||||||
Rng = new Random();
|
Rng = new Random();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SvcCall(object sender, AExceptionEventArgs e)
|
public void SvcCall(object sender, AInstExceptEventArgs e)
|
||||||
{
|
{
|
||||||
ARegisters Registers = (ARegisters)sender;
|
ARegisters Registers = (ARegisters)sender;
|
||||||
|
|
||||||
|
|
Reference in a new issue