Only throw undefined instruction exception at execution, not at translation stage

This commit is contained in:
gdkchan 2018-02-10 14:20:46 -03:00
parent 9f612682e0
commit 55743c0cba
28 changed files with 94 additions and 43 deletions

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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) { }
} }
} }

View file

@ -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);
} }

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
} }
} }
} }

View file

@ -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;
} }

View 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;
}
}
}

View file

@ -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));
} }
} }
} }

View 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)) { }
}
}

View file

@ -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++)

View file

@ -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;