diff --git a/Ryujinx/Cpu/Decoder/ADecoder.cs b/Ryujinx/Cpu/Decoder/ADecoder.cs index 5eb0e0dd0..06a535c1b 100644 --- a/Ryujinx/Cpu/Decoder/ADecoder.cs +++ b/Ryujinx/Cpu/Decoder/ADecoder.cs @@ -161,7 +161,7 @@ namespace ChocolArm64.Decoder AInst Inst = AOpCodeTable.GetInst(OpCode); - AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position); + AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode); if (Inst.Type != null) { diff --git a/Ryujinx/Cpu/Decoder/AOpCode.cs b/Ryujinx/Cpu/Decoder/AOpCode.cs index 4e5a80700..5d1275930 100644 --- a/Ryujinx/Cpu/Decoder/AOpCode.cs +++ b/Ryujinx/Cpu/Decoder/AOpCode.cs @@ -6,14 +6,16 @@ namespace ChocolArm64.Decoder { 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 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAdr.cs b/Ryujinx/Cpu/Decoder/AOpCodeAdr.cs index 49f756e72..3396281f4 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeAdr.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeAdr.cs @@ -7,7 +7,7 @@ namespace ChocolArm64.Decoder public int Rd { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAlu.cs b/Ryujinx/Cpu/Decoder/AOpCodeAlu.cs index 981af800e..e1a44f04b 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeAlu.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeAlu.cs @@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder 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; Rn = (OpCode >> 5) & 0x1f; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImm.cs b/Ryujinx/Cpu/Decoder/AOpCodeBImm.cs index 2a56d4af4..6519d281d 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBImm.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBImm.cs @@ -6,6 +6,6 @@ namespace ChocolArm64.Decoder { 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) { } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs b/Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs index 1b6a98e7c..a4ff686d6 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs @@ -4,7 +4,7 @@ namespace ChocolArm64.Decoder { 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); } diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs b/Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs index e0ce57e38..1b6185da6 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs @@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs b/Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs index e4ae845fe..1310feb8d 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs @@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs b/Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs index 6b8b966db..73e57b7ab 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs @@ -7,7 +7,7 @@ namespace ChocolArm64.Decoder public int Rt { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBReg.cs b/Ryujinx/Cpu/Decoder/AOpCodeBReg.cs index a71fc338a..c9c600af5 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeBReg.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeBReg.cs @@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder { 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 Op2 = (OpCode >> 16) & 0x1f; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeException.cs b/Ryujinx/Cpu/Decoder/AOpCodeException.cs index c3591a920..4579c1a7b 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeException.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeException.cs @@ -6,7 +6,7 @@ namespace ChocolArm64.Decoder { 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; } diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMem.cs b/Ryujinx/Cpu/Decoder/AOpCodeMem.cs index 1950b2867..5ec72125a 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeMem.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeMem.cs @@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder public int Size { 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; Rn = (OpCode >> 5) & 0x1f; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs b/Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs index b94294353..ad719a194 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs @@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder public bool Signed { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMov.cs b/Ryujinx/Cpu/Decoder/AOpCodeMov.cs index 3d1431fb1..d5398646d 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeMov.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeMov.cs @@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder public long Imm { 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 SF = (OpCode >> 31) & 1; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimd.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimd.cs index 796199845..5f940b220 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimd.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimd.cs @@ -12,7 +12,7 @@ namespace ChocolArm64.Decoder 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; Rn = (OpCode >> 5) & 0x1f; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs index 1047beffc..3f8889598 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs @@ -8,7 +8,7 @@ namespace ChocolArm64.Decoder public long Imm { 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 Type = (OpCode >> 22) & 0x3; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs index 3a08ce63a..2959aee6d 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs @@ -9,7 +9,7 @@ namespace ChocolArm64.Decoder public long Imm { 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs index cf6915f56..ea6fe00be 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs @@ -10,7 +10,7 @@ namespace ChocolArm64.Decoder public bool Signed => 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; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs index 0e8480b03..635ec91e4 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs @@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder public int Elems { 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) { diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs index c2917dfc8..5bad95edd 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs @@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder public bool Replicate { 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 S = (OpCode >> 12) & 1; diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSystem.cs b/Ryujinx/Cpu/Decoder/AOpCodeSystem.cs index 95b291001..3d81a5d45 100644 --- a/Ryujinx/Cpu/Decoder/AOpCodeSystem.cs +++ b/Ryujinx/Cpu/Decoder/AOpCodeSystem.cs @@ -11,7 +11,7 @@ namespace ChocolArm64.Decoder public int Op1 { 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; Op2 = (OpCode >> 5) & 0x7; diff --git a/Ryujinx/Cpu/Instruction/AInstEmitException.cs b/Ryujinx/Cpu/Instruction/AInstEmitException.cs index c343291a3..f05d962f2 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitException.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitException.cs @@ -37,7 +37,21 @@ namespace ChocolArm64.Instruction 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); + } } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/State/AExceptionEventArgs.cs b/Ryujinx/Cpu/State/AInstExceptEventArgs.cs similarity index 61% rename from Ryujinx/Cpu/State/AExceptionEventArgs.cs rename to Ryujinx/Cpu/State/AInstExceptEventArgs.cs index 53d2ed482..f2ee039b6 100644 --- a/Ryujinx/Cpu/State/AExceptionEventArgs.cs +++ b/Ryujinx/Cpu/State/AInstExceptEventArgs.cs @@ -2,11 +2,11 @@ using System; namespace ChocolArm64.State { - public class AExceptionEventArgs : EventArgs + public class AInstExceptEventArgs : EventArgs { public int Id { get; private set; } - public AExceptionEventArgs(int Id) + public AInstExceptEventArgs(int Id) { this.Id = Id; } diff --git a/Ryujinx/Cpu/State/AInstUndEventArgs.cs b/Ryujinx/Cpu/State/AInstUndEventArgs.cs new file mode 100644 index 000000000..53de65a33 --- /dev/null +++ b/Ryujinx/Cpu/State/AInstUndEventArgs.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Ryujinx/Cpu/State/ARegisters.cs b/Ryujinx/Cpu/State/ARegisters.cs index 1a8f2f13a..076567246 100644 --- a/Ryujinx/Cpu/State/ARegisters.cs +++ b/Ryujinx/Cpu/State/ARegisters.cs @@ -42,23 +42,23 @@ namespace ChocolArm64.State public long CntpctEl0 => Environment.TickCount * TicksPerMS; - public event EventHandler Break; - public event EventHandler SvcCall; - public event EventHandler Undefined; + public event EventHandler Break; + public event EventHandler SvcCall; + public event EventHandler Undefined; public void OnBreak(int Imm) { - Break?.Invoke(this, new AExceptionEventArgs(Imm)); + Break?.Invoke(this, new AInstExceptEventArgs(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)); } } } \ No newline at end of file diff --git a/Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs b/Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs new file mode 100644 index 000000000..86033a82a --- /dev/null +++ b/Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs @@ -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)) { } + } +} \ No newline at end of file diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx/OsHle/Process.cs index 3c91605a8..668238468 100644 --- a/Ryujinx/OsHle/Process.cs +++ b/Ryujinx/OsHle/Process.cs @@ -137,25 +137,31 @@ namespace Ryujinx.OsHle return -1; } - Thread.Registers.Break += BreakHandler; - Thread.Registers.SvcCall += SvcHandler.SvcCall; - Thread.Registers.ProcessId = ProcessId; - Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId(); - Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize; - Thread.Registers.X0 = (ulong)ArgsPtr; - Thread.Registers.X1 = (ulong)Handle; - Thread.Registers.X31 = (ulong)StackTop; + Thread.Registers.Break += BreakHandler; + Thread.Registers.SvcCall += SvcHandler.SvcCall; + Thread.Registers.Undefined += UndefinedHandler; + Thread.Registers.ProcessId = ProcessId; + Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId(); + Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize; + Thread.Registers.X0 = (ulong)ArgsPtr; + Thread.Registers.X1 = (ulong)Handle; + Thread.Registers.X31 = (ulong)StackTop; Thread.WorkFinished += ThreadFinished; return Handle; } - private void BreakHandler(object sender, AExceptionEventArgs e) + private void BreakHandler(object sender, AInstExceptEventArgs e) { throw new GuestBrokeExecutionException(); } + private void UndefinedHandler(object sender, AInstUndEventArgs e) + { + throw new UndefinedInstructionException(e.Position, e.RawOpCode); + } + private int GetFreeTlsSlot(AThread Thread) { for (int Index = 1; Index < TotalTlsSlots; Index++) diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx/OsHle/Svc/SvcHandler.cs index ccff71e4c..44bd88ee6 100644 --- a/Ryujinx/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx/OsHle/Svc/SvcHandler.cs @@ -63,7 +63,7 @@ namespace Ryujinx.OsHle.Svc Rng = new Random(); } - public void SvcCall(object sender, AExceptionEventArgs e) + public void SvcCall(object sender, AInstExceptEventArgs e) { ARegisters Registers = (ARegisters)sender;