Merge pull request #10 from gdkchan/master

Working...
This commit is contained in:
Dr.Hacknik 2018-02-13 18:48:38 -05:00 committed by GitHub
commit e2c3a1e1fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 341 additions and 289 deletions

View file

@ -27,14 +27,12 @@ namespace Ryujinx
{
Logging.Info("Loading as cart with RomFS.");
Console.Title += " - Cart (with RomFS) - " + args[0];
Ns.Os.LoadCart(args[0], RomFsFiles[0]);
}
else
{
Logging.Info("Loading as cart WITHOUT RomFS.");
Console.Title += " - Cart (without RomFS) - " + args[0];
Ns.Os.LoadCart(args[0]);
}
}
@ -42,7 +40,6 @@ namespace Ryujinx
{
Logging.Info("Loading as homebrew.");
Console.Title += " - Homebrew - " + args[0];
Ns.Os.LoadProgram(args[0]);
}
}

View file

@ -59,7 +59,7 @@ If you have some homebrews that currently doesn't work on it, you can contact us
**Contact**
For help, support, suggestion, or if you just want to get in touch with the team, join our Discord served!
For help, support, suggestion, or if you just want to get in touch with the team, join our Discord server!
https://discord.gg/VkQYXAZ
**Running**

View file

@ -11,11 +11,11 @@ namespace ChocolArm64
#region "OpCode Table"
//Integer
Set("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc, typeof(AOpCodeAluRs));
Set("x0010001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm));
Set("x0001011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
Set("x00100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm));
Set("x0001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
Set("x0001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
Set("x0110001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluImm));
Set("x0101011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
Set("x01100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluImm));
Set("x0101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
Set("x0101011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
Set("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adr, typeof(AOpCodeAdr));
Set("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adrp, typeof(AOpCodeAdr));
@ -102,11 +102,11 @@ namespace ChocolArm64
Set("xx111000001xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemReg));
Set("1x001000001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxp, typeof(AOpCodeMemEx));
Set("xx001000000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxr, typeof(AOpCodeMemEx));
Set("x1010001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluImm));
Set("x1001011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
Set("x10100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluImm));
Set("x1001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
Set("x1001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
Set("x1110001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluImm));
Set("x1101011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
Set("x11100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluImm));
Set("x1101011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
Set("x1101011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
Set("11010100000xxxxxxxxxxxxxxxx00001", AInstEmit.Svc, typeof(AOpCodeException));
Set("1101010100001xxxxxxxxxxxxxxxxxxx", AInstEmit.Sys, typeof(AOpCodeSystem));
@ -119,24 +119,25 @@ namespace ChocolArm64
Set("10011011110xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umulh, typeof(AOpCodeMul));
//Vector
Set("0x001110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Add_V, typeof(AOpCodeSimdReg));
Set("0>001110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Add_V, typeof(AOpCodeSimdReg));
Set("01011110xx110001101110xxxxxxxxxx", AInstEmit.Addp_S, typeof(AOpCodeSimd));
Set("0x001110xx1xxxxx101111xxxxxxxxxx", AInstEmit.Addp_V, typeof(AOpCodeSimdReg));
Set("0x001110<<110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
Set("0>001110<<1xxxxx101111xxxxxxxxxx", AInstEmit.Addp_V, typeof(AOpCodeSimdReg));
Set("000011100x110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
Set("01001110<<110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
Set("0x001110001xxxxx000111xxxxxxxxxx", AInstEmit.And_V, typeof(AOpCodeSimdReg));
Set("0x001110011xxxxx000111xxxxxxxxxx", AInstEmit.Bic_V, typeof(AOpCodeSimdReg));
Set("0x10111100000xxx<<x101xxxxxxxxxx", AInstEmit.Bic_Vi, typeof(AOpCodeSimdImm));
Set("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
Set("0x101110xx1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
Set("0x001110xx100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
Set("0x001110xx1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
Set("0x101110xx100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
Set("0x001110xx1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
Set("0x001110xx100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
Set("0x101110xx1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
Set("0x101110xx1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
Set("0x101110xx100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
Set("0x001110xx100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
Set("0>101110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
Set("0>001110<<100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
Set("0>001110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
Set("0>101110<<100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
Set("0>001110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
Set("0>001110<<100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
Set("0>101110<<1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
Set("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
Set("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
Set("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
Set("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns));
Set("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
@ -199,26 +200,28 @@ namespace ChocolArm64
Set("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
Set("xx111100x11xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemReg));
Set("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeSimdMemLit));
Set("0x001110xx1xxxxx100101xxxxxxxxxx", AInstEmit.Mla_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx100101xxxxxxxxxx", AInstEmit.Mla_V, typeof(AOpCodeSimdReg));
Set("0x00111100000xxx0xx001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
Set("0x00111100000xxx10x001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
Set("0x00111100000xxx110x01xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
Set("0xx0111100000xxx111001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
Set("0x001110xx1xxxxx100111xxxxxxxxxx", AInstEmit.Mul_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx100111xxxxxxxxxx", AInstEmit.Mul_V, typeof(AOpCodeSimdReg));
Set("0x10111100000xxx0xx001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
Set("0x10111100000xxx10x001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
Set("0x10111100000xxx110x01xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
Set("0x101110xx100000101110xxxxxxxxxx", AInstEmit.Neg_V, typeof(AOpCodeSimdReg));
Set("0>101110<<100000101110xxxxxxxxxx", AInstEmit.Neg_V, typeof(AOpCodeSimdReg));
Set("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd));
Set("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
Set("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
Set("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));
Set("x0011110xx100010000000xxxxxxxxxx", AInstEmit.Scvtf_Gp, typeof(AOpCodeSimdCvt));
Set("010111100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_S, typeof(AOpCodeSimd));
Set("0x0011100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_V, typeof(AOpCodeSimd));
Set("010111110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_S, typeof(AOpCodeSimdShImm));
Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
Set("0x001110xx1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
@ -231,9 +234,7 @@ namespace ChocolArm64
Set("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
Set("xx111100x01xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemReg));
Set("01111110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_S, typeof(AOpCodeSimdReg));
Set("0x101110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_V, typeof(AOpCodeSimdReg));
Set("x0011110xx100010000000xxxxxxxxxx", AInstEmit.Scvtf_Gp, typeof(AOpCodeSimdCvt));
Set("010111100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_S, typeof(AOpCodeSimd));
Set("0>101110<<1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_V, typeof(AOpCodeSimdReg));
Set("0x001110000xxxxx0xx000xxxxxxxxxx", AInstEmit.Tbl_V, typeof(AOpCodeSimdTbl));
Set("001011100x110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
Set("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
@ -241,7 +242,7 @@ namespace ChocolArm64
Set("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt));
Set("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimdReg));
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
Set("0x101110xx1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
@ -311,9 +312,13 @@ namespace ChocolArm64
{
InsertTop(XMask, Value, Inst);
}
else if ((ZCount & OCount) != 0)
else if (ZCount != 0 && OCount != 0)
{
for (int OCtr = 0; (uint)OCtr < (1 << OCount) - 1; OCtr++)
//When both the > and the <, then a value is blacklisted,
//with > indicating 0, and < indicating 1. So, for example, ><<
//blacklists the pattern 011, but 000, 001, 010, 100, 101,
//110 and 111 are valid.
for (int OCtr = 0; (uint)OCtr < (1 << OCount); OCtr++)
{
int OVal = Value;
@ -322,7 +327,9 @@ namespace ChocolArm64
OVal |= ((OCtr >> O) & 1) << OPos[O];
}
InsertWithCtr(1, 1 << ZCount, ZCount, ZPos, XMask, OVal, Inst);
int ZStart = OCtr == (1 << OCount) ? 1 : 0;
InsertWithCtr(ZStart, 1 << ZCount, ZCount, ZPos, XMask, OVal, Inst);
}
}
else if (ZCount != 0)

View file

@ -15,8 +15,6 @@ namespace ChocolArm64.Decoder
int Shift = (OpCode >> 22) & 3;
//Assert Shift < 2
Imm <<= Shift * 12;
}
else if (DataOp == ADataOp.Logical)

View file

@ -11,11 +11,19 @@ namespace ChocolArm64.Decoder
public AOpCodeAluRs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
{
Shift = (OpCode >> 10) & 0x3f;
int Shift = (OpCode >> 10) & 0x3f;
if (Shift >= GetBitsCount())
{
Emitter = AInstEmit.Und;
return;
}
this.Shift = Shift;
Rm = (OpCode >> 16) & 0x1f;
ShiftType = (AShiftType)((OpCode >> 22) & 0x3);
//Assert ShiftType != 3
}
}
}

View file

@ -1,12 +1,14 @@
using ChocolArm64.Decoder;
using ChocolArm64.State;
using ChocolArm64.Translation;
using System;
using System.Reflection;
namespace ChocolArm64.Instruction
{
static partial class AInstEmit
{
private const BindingFlags Binding = BindingFlags.NonPublic | BindingFlags.Instance;
public static void Brk(AILEmitterCtx Context)
{
EmitExceptionCall(Context, nameof(ARegisters.OnBreak));
@ -27,7 +29,9 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I4(Op.Id);
Context.EmitCall(typeof(ARegisters), MthdName);
MethodInfo MthdInfo = typeof(ARegisters).GetMethod(MthdName, Binding);
Context.EmitCall(MthdInfo);
if (Context.CurrBlock.Next != null)
{
@ -46,7 +50,11 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I8(Op.Position);
Context.EmitLdc_I4(Op.RawOpCode);
Context.EmitCall(typeof(ARegisters), nameof(ARegisters.OnUndefined));
string MthdName = nameof(ARegisters.OnUndefined);
MethodInfo MthdInfo = typeof(ARegisters).GetMethod(MthdName, Binding);
Context.EmitCall(MthdInfo);
if (Context.CurrBlock.Next != null)
{

View file

@ -104,8 +104,8 @@ namespace ChocolArm64.Instruction
public static void Fadd_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Add);
public static void Fcvtzs_V(AILEmitterCtx Context) => EmitVectorFcvtS(Context);
public static void Fcvtzu_V(AILEmitterCtx Context) => EmitVectorFcvtU(Context);
public static void Fcvtzs_V(AILEmitterCtx Context) => EmitVectorFcvts(Context);
public static void Fcvtzu_V(AILEmitterCtx Context) => EmitVectorFcvtu(Context);
public static void Fmla_V(AILEmitterCtx Context)
{
@ -264,19 +264,7 @@ namespace ChocolArm64.Instruction
Context.EmitStvec(Op.Rd);
}
public static void Scvtf_V(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
Context.EmitLdvec(Op.Rn);
Context.EmitLdc_I4(Op.SizeF);
ASoftFallback.EmitCall(Context,
nameof(ASoftFallback.Scvtf_V64),
nameof(ASoftFallback.Scvtf_V128));
Context.EmitStvec(Op.Rd);
}
public static void Scvtf_V(AILEmitterCtx Context) => EmitVectorScvtf(Context);
public static void Shl_V(AILEmitterCtx Context)
{
@ -346,7 +334,7 @@ namespace ChocolArm64.Instruction
nameof(ASoftFallback.Tbl4_V128)); break;
default: throw new InvalidOperationException();
}
}
Context.EmitStvec(Op.Rd);
}
@ -434,33 +422,12 @@ namespace ChocolArm64.Instruction
public static void Ushr_V(AILEmitterCtx Context)
{
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
Context.EmitLdvec(Op.Rn);
Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
Context.EmitLdc_I4(Op.Size);
ASoftFallback.EmitCall(Context,
nameof(ASoftFallback.Ushr64),
nameof(ASoftFallback.Ushr128));
Context.EmitStvec(Op.Rd);
EmitVectorShr(Context, ShrFlags.None);
}
public static void Usra_V(AILEmitterCtx Context)
{
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
Context.EmitLdvec(Op.Rd);
Context.EmitLdvec(Op.Rn);
Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
Context.EmitLdc_I4(Op.Size);
ASoftFallback.EmitCall(Context,
nameof(ASoftFallback.Usra64),
nameof(ASoftFallback.Usra128));
Context.EmitStvec(Op.Rd);
EmitVectorShr(Context, ShrFlags.Accumulate);
}
public static void Uzp1_V(AILEmitterCtx Context)
@ -651,11 +618,11 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I4(0);
Context.EmitLdc_I4(Op.Size);
EmitVectorExtractZx(Context, Op.Rn, 0);
EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
{
EmitVectorExtractZx(Context, Op.Rn, Index);
EmitVectorExtractZx(Context, Op.Rn, Op.Size, Index);
Context.Emit(OpCodes.Add);
}
@ -730,7 +697,7 @@ namespace ChocolArm64.Instruction
int MaxShift = 8 << Op.Size;
EmitVectorBinaryZx(Context, () =>
Action Emit = () =>
{
AILLabel LblShl = new AILLabel();
AILLabel LblZero = new AILLabel();
@ -771,48 +738,83 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I8(0);
Context.MarkLabel(LblEnd);
});
};
if (Signed)
{
EmitVectorBinarySx(Context, Emit);
}
else
{
EmitVectorBinaryZx(Context, Emit);
}
}
private static void EmitVectorFcvtS(AILEmitterCtx Context)
private enum ShrFlags
{
EmitVectorCvtOp(Context, CvtDir.Fcvt, true);
None = 0,
Signed = 1 << 0,
Rounding = 1 << 1,
Accumulate = 1 << 2
}
private static void EmitVectorFcvtU(AILEmitterCtx Context)
private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags)
{
EmitVectorCvtOp(Context, CvtDir.Fcvt, false);
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
if (Flags.HasFlag(ShrFlags.Accumulate))
{
Action Emit = () =>
{
Context.EmitLdc_I4(Shift);
Context.Emit(OpCodes.Shr_Un);
Context.Emit(OpCodes.Add);
};
EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
}
else
{
EmitVectorUnaryZx(Context, () =>
{
Context.EmitLdc_I4(Shift);
Context.Emit(OpCodes.Shr_Un);
});
}
}
private static void EmitVectorCvtfS(AILEmitterCtx Context)
private static void EmitVectorFcvts(AILEmitterCtx Context)
{
EmitVectorCvtOp(Context, CvtDir.Cvtf, true);
EmitVectorFcvtOp(Context, Signed: true);
}
private static void EmitVectorCvtfU(AILEmitterCtx Context)
private static void EmitVectorFcvtu(AILEmitterCtx Context)
{
EmitVectorCvtOp(Context, CvtDir.Cvtf, false);
EmitVectorFcvtOp(Context, Signed: false);
}
private enum CvtDir
private static void EmitVectorScvtf(AILEmitterCtx Context)
{
Fcvt,
Cvtf
EmitVectorCvtfOp(Context, Signed: true);
}
private static void EmitVectorCvtOp(AILEmitterCtx Context, CvtDir Dir, bool Signed)
private static void EmitVectorUcvtf(AILEmitterCtx Context)
{
EmitVectorCvtfOp(Context, Signed: false);
}
private static void EmitVectorFcvtOp(AILEmitterCtx Context, bool Signed)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int SizeF = Op.Size & 1;
int SizeI = SizeF + 2;
int FBits = 0;
if (Op is AOpCodeSimdShImm OpImm)
{
FBits = (8 << (Op.Size + 1)) - OpImm.Imm;
}
int FBits = GetFBits(Context);
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
@ -822,26 +824,17 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I4(FBits);
if (Dir == CvtDir.Fcvt)
if (SizeF == 0)
{
//Float to Integer.
if (SizeF == 0)
{
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.SatSingleToInt32)
: nameof(ASoftFallback.SatSingleToUInt32));
}
else if (SizeF == 1)
{
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.SatDoubleToInt64)
: nameof(ASoftFallback.SatDoubleToUInt64));
}
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.SatSingleToInt32)
: nameof(ASoftFallback.SatSingleToUInt32));
}
else if (Dir == CvtDir.Cvtf)
else if (SizeF == 1)
{
//Integer to Float.
//TODO.
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.SatDoubleToInt64)
: nameof(ASoftFallback.SatDoubleToUInt64));
}
EmitVectorInsert(Context, Op.Rd, Index, SizeI);
@ -853,6 +846,57 @@ namespace ChocolArm64.Instruction
}
}
private static void EmitVectorCvtfOp(AILEmitterCtx Context, bool Signed)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int SizeF = Op.Size & 1;
int SizeI = SizeF + 2;
int FBits = GetFBits(Context);
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
{
EmitVectorExtract(Context, Op.Rn, Index, SizeI, Signed);
Context.EmitLdc_I4(FBits);
if (SizeF == 0)
{
Context.Emit(OpCodes.Conv_I4);
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.Int32ToSingle)
: nameof(ASoftFallback.UInt32ToSingle));
}
else if (SizeF == 1)
{
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.Int64ToDouble)
: nameof(ASoftFallback.UInt64ToDouble));
}
EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
}
if (Op.RegisterSize == ARegisterSize.SIMD64)
{
EmitVectorZeroUpper(Context, Op.Rd);
}
}
private static int GetFBits(AILEmitterCtx Context)
{
if (Context.CurrOp is AOpCodeSimdShImm Op)
{
return (8 << (Op.Size + 1)) - Op.Imm;
}
return 0;
}
private static void EmitVectorBinaryFOp(AILEmitterCtx Context, OpCode ILOp)
{
EmitVectorBinaryFOp(Context, () => Context.Emit(ILOp));
@ -899,36 +943,43 @@ namespace ChocolArm64.Instruction
private static void EmitVectorUnarySx(AILEmitterCtx Context, Action Emit)
{
EmitVectorOp(Context, Emit, 1, true);
EmitVectorOp(Context, Emit, OperFlags.Rn, true);
}
private static void EmitVectorBinarySx(AILEmitterCtx Context, Action Emit)
{
EmitVectorOp(Context, Emit, 2, true);
EmitVectorOp(Context, Emit, OperFlags.RnRm, true);
}
private static void EmitVectorUnaryZx(AILEmitterCtx Context, Action Emit)
{
EmitVectorOp(Context, Emit, 1, false);
EmitVectorOp(Context, Emit, OperFlags.Rn, false);
}
private static void EmitVectorBinaryZx(AILEmitterCtx Context, Action Emit)
{
EmitVectorOp(Context, Emit, 2, false);
EmitVectorOp(Context, Emit, OperFlags.RnRm, false);
}
private static void EmitVectorTernaryZx(AILEmitterCtx Context, Action Emit)
{
EmitVectorOp(Context, Emit, 3, false);
EmitVectorOp(Context, Emit, OperFlags.RdRnRm, false);
}
private static void EmitVectorOp(AILEmitterCtx Context, Action Emit, int Opers, bool Signed)
[Flags]
private enum OperFlags
{
if (Opers < 1 || Opers > 3)
{
throw new ArgumentOutOfRangeException(nameof(Opers));
}
Rd = 1 << 0,
Rn = 1 << 1,
Rm = 1 << 2,
RnRm = Rn | Rm,
RdRn = Rd | Rn,
RdRnRm = Rd | Rn | Rm
}
private static void EmitVectorOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
@ -939,19 +990,19 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I4(Index);
Context.EmitLdc_I4(Op.Size);
if (Opers == 3)
if (Opers.HasFlag(OperFlags.Rd))
{
EmitVectorExtract(Context, Op.Rd, Index, Signed);
EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
}
if (Opers >= 1)
if (Opers.HasFlag(OperFlags.Rn))
{
EmitVectorExtract(Context, Op.Rn, Index, Signed);
EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
}
if (Opers >= 2)
if (Opers.HasFlag(OperFlags.Rm))
{
EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Signed);
EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
}
Emit();
@ -999,7 +1050,7 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I4(Index);
Context.EmitLdc_I4(Op.Size);
EmitVectorExtract(Context, Op.Rn, Index, Signed);
EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
Context.EmitLdc_I8(Imm);
@ -1026,11 +1077,11 @@ namespace ChocolArm64.Instruction
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
{
EmitVectorExtractSx(Context, Op.Rn, Index);
EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
if (Op is AOpCodeSimdReg BinOp)
{
EmitVectorExtractSx(Context, BinOp.Rm, Index);
EmitVectorExtractSx(Context, BinOp.Rm, Index, Op.Size);
}
else
{
@ -1078,29 +1129,39 @@ namespace ChocolArm64.Instruction
}
}
private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index)
private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index, int Size)
{
EmitVectorExtract(Context, Reg, Index, true);
EmitVectorExtract(Context, Reg, Index, Size, true);
}
private static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index)
private static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index, int Size)
{
EmitVectorExtract(Context, Reg, Index, false);
EmitVectorExtract(Context, Reg, Index, Size, false);
}
private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, bool Signed)
private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
{
IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
Context.EmitLdvec(Reg);
Context.EmitLdc_I4(Index);
Context.EmitLdc_I4(Op.Size);
Context.EmitLdc_I4(Size);
ASoftFallback.EmitCall(Context, Signed
? nameof(ASoftFallback.ExtractSVec)
: nameof(ASoftFallback.ExtractVec));
}
private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
{
EmitVectorInsert(Context, Rd, 0, 3, 0);
}
private static void EmitVectorZeroUpper(AILEmitterCtx Context, int Rd)
{
EmitVectorInsert(Context, Rd, 1, 3, 0);
}
private static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size)
{
Context.EmitLdvec(Reg);
@ -1122,16 +1183,6 @@ namespace ChocolArm64.Instruction
Context.EmitStvec(Reg);
}
private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
{
EmitVectorInsert(Context, Rd, 0, 3, 0);
}
private static void EmitVectorZeroUpper(AILEmitterCtx Context, int Rd)
{
EmitVectorInsert(Context, Rd, 1, 3, 0);
}
private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
{
Context.EmitLdvec(Reg);

View file

@ -97,39 +97,7 @@ namespace ChocolArm64.Instruction
throw new ArgumentException(nameof(Size));
}
public static int SatDoubleToInt32(double Value, int FBits = 0)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > int.MaxValue ? int.MaxValue :
Value < int.MinValue ? int.MinValue : (int)Value;
}
public static long SatDoubleToInt64(double Value, int FBits = 0)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > long.MaxValue ? long.MaxValue :
Value < long.MinValue ? long.MinValue : (long)Value;
}
public static uint SatDoubleToUInt32(double Value, int FBits = 0)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > uint.MaxValue ? uint.MaxValue :
Value < uint.MinValue ? uint.MinValue : (uint)Value;
}
public static ulong SatDoubleToUInt64(double Value, int FBits = 0)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > ulong.MaxValue ? ulong.MaxValue :
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
}
public static int SatSingleToInt32(float Value, int FBits = 0)
public static int SatSingleToInt32(float Value, int FBits)
{
if (FBits != 0) Value *= MathF.Pow(2, FBits);
@ -137,7 +105,7 @@ namespace ChocolArm64.Instruction
Value < int.MinValue ? int.MinValue : (int)Value;
}
public static long SatSingleToInt64(float Value, int FBits = 0)
public static long SatSingleToInt64(float Value, int FBits)
{
if (FBits != 0) Value *= MathF.Pow(2, FBits);
@ -145,7 +113,7 @@ namespace ChocolArm64.Instruction
Value < long.MinValue ? long.MinValue : (long)Value;
}
public static uint SatSingleToUInt32(float Value, int FBits = 0)
public static uint SatSingleToUInt32(float Value, int FBits)
{
if (FBits != 0) Value *= MathF.Pow(2, FBits);
@ -153,7 +121,7 @@ namespace ChocolArm64.Instruction
Value < uint.MinValue ? uint.MinValue : (uint)Value;
}
public static ulong SatSingleToUInt64(float Value, int FBits = 0)
public static ulong SatSingleToUInt64(float Value, int FBits)
{
if (FBits != 0) Value *= MathF.Pow(2, FBits);
@ -161,6 +129,110 @@ namespace ChocolArm64.Instruction
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
}
public static int SatDoubleToInt32(double Value, int FBits)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > int.MaxValue ? int.MaxValue :
Value < int.MinValue ? int.MinValue : (int)Value;
}
public static long SatDoubleToInt64(double Value, int FBits)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > long.MaxValue ? long.MaxValue :
Value < long.MinValue ? long.MinValue : (long)Value;
}
public static uint SatDoubleToUInt32(double Value, int FBits)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > uint.MaxValue ? uint.MaxValue :
Value < uint.MinValue ? uint.MinValue : (uint)Value;
}
public static ulong SatDoubleToUInt64(double Value, int FBits)
{
if (FBits != 0) Value *= Math.Pow(2, FBits);
return Value > ulong.MaxValue ? ulong.MaxValue :
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
}
public static float Int32ToSingle(int Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float Int64ToSingle(long Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float UInt32ToSingle(uint Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float UInt64ToSingle(ulong Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float Int32ToDouble(int Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float Int64ToDouble(long Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float UInt32ToDouble(uint Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static float UInt64ToDouble(ulong Value, int FBits)
{
float ValueF = Value;
if (FBits != 0) ValueF *= 1 / MathF.Pow(2, FBits);
return ValueF;
}
public static ulong SMulHi128(ulong LHS, ulong RHS)
{
long LLo = (uint)(LHS >> 0);
@ -556,44 +628,6 @@ namespace ChocolArm64.Instruction
return Res;
}
public static AVec Scvtf_V64(AVec Vector, int Size)
{
return Scvtf_V(Vector, Size, 2);
}
public static AVec Scvtf_V128(AVec Vector, int Size)
{
return Scvtf_V(Vector, Size, 4);
}
private static AVec Scvtf_V(AVec Vector, int Size, int Bytes)
{
AVec Res = new AVec();
int Elems = Bytes >> Size;
if (Size == 0)
{
for (int Index = 0; Index < Elems; Index++)
{
int Value = (int)ExtractSVec(Vector, Index, Size + 2);
Res = AVec.InsertSingle(Res, Index, Value);
}
}
else
{
for (int Index = 0; Index < Elems; Index++)
{
long Value = ExtractSVec(Vector, Index, Size + 2);
Res = AVec.InsertDouble(Res, Index, Value);
}
}
return Res;
}
public static AVec Sshll(AVec Vector, int Shift, int Size)
{
return Sshll_(Vector, Shift, Size, false);
@ -785,57 +819,6 @@ namespace ChocolArm64.Instruction
return Res;
}
public static AVec Ushr64(AVec Vector, int Shift, int Size)
{
return Ushr(Vector, Shift, Size, 8);
}
public static AVec Ushr128(AVec Vector, int Shift, int Size)
{
return Ushr(Vector, Shift, Size, 16);
}
private static AVec Ushr(AVec Vector, int Shift, int Size, int Bytes)
{
AVec Res = new AVec();
int Elems = Bytes >> Size;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Vector, Index, Size);
Res = InsertVec(Res, Index, Size, Value >> Shift);
}
return Res;
}
public static AVec Usra64(AVec Res, AVec Vector, int Shift, int Size)
{
return Usra(Res, Vector, Shift, Size, 8);
}
public static AVec Usra128(AVec Res, AVec Vector, int Shift, int Size)
{
return Usra(Res, Vector, Shift, Size, 16);
}
private static AVec Usra(AVec Res, AVec Vector, int Shift, int Size, int Bytes)
{
int Elems = Bytes >> Size;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Vector, Index, Size);
ulong Addend = ExtractVec(Res, Index, Size);
Res = InsertVec(Res, Index, Size, Addend + (Value >> Shift));
}
return Res;
}
public static AVec Uzp1_V64(AVec LHS, AVec RHS, int Size)
{
return Uzp(LHS, RHS, Size, 0, 8);

View file

@ -10,9 +10,6 @@ namespace ChocolArm64.State
internal const int ErgSizeLog2 = 4;
internal const int DczSizeLog2 = 4;
private const long TicksPerS = 19_200_000;
private const long TicksPerMS = TicksPerS / 1_000;
public ulong X0, X1, X2, X3, X4, X5, X6, X7,
X8, X9, X10, X11, X12, X13, X14, X15,
X16, X17, X18, X19, X20, X21, X22, X23,
@ -40,23 +37,26 @@ namespace ChocolArm64.State
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
private const long TicksPerS = 19_200_000;
private const long TicksPerMS = TicksPerS / 1_000;
public long CntpctEl0 => Environment.TickCount * TicksPerMS;
public event EventHandler<AInstExceptEventArgs> Break;
public event EventHandler<AInstExceptEventArgs> SvcCall;
public event EventHandler<AInstUndEventArgs> Undefined;
public event EventHandler<AInstUndEventArgs> Undefined;
public void OnBreak(int Imm)
internal void OnBreak(int Imm)
{
Break?.Invoke(this, new AInstExceptEventArgs(Imm));
}
public void OnSvcCall(int Imm)
internal void OnSvcCall(int Imm)
{
SvcCall?.Invoke(this, new AInstExceptEventArgs(Imm));
}
public void OnUndefined(long Position, int RawOpCode)
internal void OnUndefined(long Position, int RawOpCode)
{
Undefined?.Invoke(this, new AInstUndEventArgs(Position, RawOpCode));
}