Implement some more instructions, fix others.

Uxtab16/Sxtab16 are untested.
This commit is contained in:
riperiperi 2020-01-11 23:48:47 +00:00
parent fc2d482616
commit 3d9d492b22
9 changed files with 169 additions and 10 deletions

View file

@ -13,6 +13,7 @@ namespace ARMeilleure.Decoders
public bool NHigh { get; private set; }
public bool MHigh { get; private set; }
public bool R { get; private set; }
public bool SetFlags { get; private set; }
public OpCode32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
@ -21,6 +22,7 @@ namespace ARMeilleure.Decoders
Rm = (opCode >> 8) & 0xf;
Ra = (opCode >> 12) & 0xf;
Rd = (opCode >> 16) & 0xf;
R = (opCode & (1 << 5)) != 0;
NHigh = ((opCode >> 5) * 0x1) == 1;
MHigh = ((opCode >> 6) * 0x1) == 1;

View file

@ -652,7 +652,9 @@ namespace ARMeilleure.Decoders
SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x1xxxxxxxx00001011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemReg));
SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x1xxxxxxxx00001101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemReg));
SetA32("<<<<000xx1x1xxxxxxxxxxxx1111xxxx", InstName.Ldrsh, InstEmit32.Ldrsh, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x1xxxxxxxx00001111xxxx", InstName.Ldrsh, InstEmit32.Ldrsh, typeof(OpCode32MemReg));
SetA32("<<<<1110xxx0xxxxxxxx111xxxx1xxxx", InstName.Mcr, InstEmit32.Mcr, typeof(OpCode32System));
SetA32("<<<<0000001xxxxxxxxxxxxx1001xxxx", InstName.Mla, InstEmit32.Mla, typeof(OpCode32AluMla));
SetA32("<<<<00000110xxxxxxxxxxxx1001xxxx", InstName.Mls, InstEmit32.Mls, typeof(OpCode32AluMla));
@ -688,7 +690,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smlab, InstEmit32.Smlab, typeof(OpCode32AluMla));
SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, typeof(OpCode32AluUmull));
SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlalh,InstEmit32.Smlalh,typeof(OpCode32AluUmull));
SetA32("<<<<01110101xxxx1111xxxx00x1xxxx", InstName.Smmul, InstEmit32.Smmul, typeof(OpCode32AluMla));
SetA32("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla));
SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla));
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluImm));
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsImm));
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsReg));
@ -719,6 +722,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000010xxxxxxxxxxxxx0xx1xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsReg));
SetA32("<<<<1111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Svc, InstEmit32.Svc, typeof(OpCode32Exception));
SetA32("<<<<01101010xxxxxxxxxx000111xxxx", InstName.Sxtb, InstEmit32.Sxtb, typeof(OpCode32AluUx));
SetA32("<<<<01101000xxxxxxxxxx000111xxxx", InstName.Sxtb16,InstEmit32.Sxtb16,typeof(OpCode32AluUx));
SetA32("<<<<01101011xxxxxxxxxx000111xxxx", InstName.Sxth, InstEmit32.Sxth, typeof(OpCode32AluUx));
SetA32("<<<<00110011xxxx0000xxxxxxxxxxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluImm));
SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsImm));
@ -731,6 +735,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16,InstEmit32.Uxtb16,typeof(OpCode32AluUx));
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
// FP & SIMD (AArch32)
@ -805,6 +810,12 @@ namespace ARMeilleure.Decoders
SetA32("<<<<1101xx01xxxxxxxx10xxxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, typeof(OpCode32SimdMemImm));
SetA32("111100100x0xxxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, typeof(OpCode32SimdReg));
SetA32("1111001x0xxxxxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, typeof(OpCode32SimdReg));
SetA32("111100100x1xxxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg));
SetA32("1111001x0xxxxxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, typeof(OpCode32SimdReg));
SetA32("111111101x00xxxxxxxx10xxxxx0xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_S, typeof(OpCode32SimdRegS));
SetA32("111100110xxxxxxxxxxx1111xxx1xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg));

View file

@ -322,11 +322,72 @@ namespace ARMeilleure.Instructions
EmitAluStore(context, res);
}
private static void EmitExtend16(ArmEmitterContext context, bool signed)
{
IOpCode32AluUx op = (IOpCode32AluUx)context.CurrOp;
Operand m = GetAluM(context);
Operand res;
if (op.RotateBits == 0)
{
res = m;
}
else
{
Operand rotate = Const(op.RotateBits);
res = context.RotateRight(m, rotate);
}
Operand low16, high16;
if (signed)
{
low16 = context.SignExtend8(OperandType.I32, res);
high16 = context.SignExtend8(OperandType.I32, context.ShiftRightUI(res, Const(16)));
}
else
{
low16 = context.ZeroExtend8(OperandType.I32, res);
high16 = context.ZeroExtend8(OperandType.I32, context.ShiftRightUI(res, Const(16)));
}
if (op.Add)
{
Operand n = GetAluN(context);
Operand lowAdd, highAdd;
if (signed)
{
lowAdd = context.SignExtend16(OperandType.I32, n);
highAdd = context.SignExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
}
else
{
lowAdd = context.ZeroExtend16(OperandType.I32, n);
highAdd = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
}
low16 = context.Add(low16, lowAdd);
high16 = context.Add(high16, highAdd);
}
res = context.BitwiseOr(
context.ZeroExtend16(OperandType.I32, low16),
context.ShiftLeft(context.ZeroExtend16(OperandType.I32, high16), Const(16))
);
EmitAluStore(context, res);
}
public static void Uxtb(ArmEmitterContext context)
{
EmitSignExtend(context, false, 8);
}
public static void Uxtb16(ArmEmitterContext context)
{
EmitExtend16(context, false);
}
public static void Uxth(ArmEmitterContext context)
{
EmitSignExtend(context, false, 16);
@ -337,6 +398,11 @@ namespace ARMeilleure.Instructions
EmitSignExtend(context, true, 8);
}
public static void Sxtb16(ArmEmitterContext context)
{
EmitExtend16(context, true);
}
public static void Sxth(ArmEmitterContext context)
{
EmitSignExtend(context, true, 16);

View file

@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
public static void Ldah(ArmEmitterContext context)
{
EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Ordered);
EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
}
// stores

View file

@ -15,9 +15,9 @@ namespace ARMeilleure.Instructions
[Flags]
private enum MullFlags
{
Subtract = 0,
Add = 1 << 0,
Signed = 1 << 1,
Subtract = 1,
Add = 1 << 1,
Signed = 1 << 2,
SignedAdd = Signed | Add,
SignedSubtract = Signed | Subtract
@ -44,7 +44,22 @@ namespace ARMeilleure.Instructions
EmitGenericStore(context, op.RdLo, op.SetFlags, lo);
}
public static void Smmla(ArmEmitterContext context)
{
EmitSmmul(context, MullFlags.SignedAdd);
}
public static void Smmls(ArmEmitterContext context)
{
EmitSmmul(context, MullFlags.SignedSubtract);
}
public static void Smmul(ArmEmitterContext context)
{
EmitSmmul(context, MullFlags.Signed);
}
private static void EmitSmmul(ArmEmitterContext context, MullFlags flags)
{
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
@ -53,7 +68,16 @@ namespace ARMeilleure.Instructions
Operand res = context.Multiply(n, m);
if ((op.RawOpCode & (1 << 5)) != 0)
if (flags.HasFlag(MullFlags.Add) && op.Ra != 0xf)
{
res = context.Add(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res);
}
else if (flags.HasFlag(MullFlags.Subtract))
{
res = context.Subtract(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res);
}
if (op.R)
{
res = context.Add(res, Const(0x80000000L));
}

View file

@ -163,21 +163,65 @@ namespace ARMeilleure.Instructions
}
}
public static void Vmax_V(ArmEmitterContext context)
{
EmitVectorBinaryOpF32(context, (op1, op2) =>
{
return EmitSoftFloatCall(context, SoftFloat32.FPMax, SoftFloat64.FPMax, op1, op2);
});
}
public static void Vmax_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.U)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareGreaterUI(op1, op2), op1, op2));
}
else
{
EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareGreater(op1, op2), op1, op2));
}
}
public static void Vmin_V(ArmEmitterContext context)
{
EmitVectorBinaryOpF32(context, (op1, op2) =>
{
return EmitSoftFloatCall(context, SoftFloat32.FPMin, SoftFloat64.FPMin, op1, op2);
});
}
public static void Vmin_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.U)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLessUI(op1, op2), op1, op2));
}
else
{
EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLess(op1, op2), op1, op2));
}
}
//TODO: probably important to have a fast path for these instead of calling fucking standard math min/max
public static void VmaxminNm_S(ArmEmitterContext context)
{
bool max = (context.CurrOp.RawOpCode & (1 << 6)) == 0;
Delegate dlg = max ? new _F32_F32_F32(Math.Max) : new _F32_F32_F32(Math.Min);
_F32_F32_F32 f32 = max ? new _F32_F32_F32(SoftFloat32.FPMaxNum) : new _F32_F32_F32(SoftFloat32.FPMinNum);
_F64_F64_F64 f64 = max ? new _F64_F64_F64(SoftFloat64.FPMaxNum) : new _F64_F64_F64(SoftFloat64.FPMinNum);
EmitScalarBinaryOpF32(context, (op1, op2) => context.Call(dlg, op1, op2));
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, f32, f64, op1, op2));
}
public static void VmaxminNm_V(ArmEmitterContext context)
{
bool max = (context.CurrOp.RawOpCode & (1 << 21)) == 0;
Delegate dlg = max ? new _F32_F32_F32(Math.Max) : new _F32_F32_F32(Math.Min);
_F32_F32_F32 f32 = max ? new _F32_F32_F32(SoftFloat32.FPMaxNum) : new _F32_F32_F32(SoftFloat32.FPMinNum);
_F64_F64_F64 f64 = max ? new _F64_F64_F64(SoftFloat64.FPMaxNum) : new _F64_F64_F64(SoftFloat64.FPMinNum);
EmitVectorBinaryOpSx32(context, (op1, op2) => context.Call(dlg, op1, op2));
EmitVectorBinaryOpSx32(context, (op1, op2) => EmitSoftFloatCall(context, f32, f64, op1, op2));
}
public static void Vmul_S(ArmEmitterContext context)

View file

@ -489,6 +489,8 @@ namespace ARMeilleure.Instructions
Smlab,
Smlal,
Smlalh,
Smmla,
Smmls,
Smmul,
Stl,
Stlb,
@ -505,12 +507,14 @@ namespace ARMeilleure.Instructions
Strexd,
Strexh,
Strh,
Sxtb16,
Teq,
Trap,
Tst,
Ubfx,
Umull,
Uxtb,
Uxtb16,
Uxth,
// FP & SIMD (AArch32)
@ -532,6 +536,8 @@ namespace ARMeilleure.Instructions
Vld4,
Vldm,
Vldr,
Vmax,
Vmin,
VMMmn,
Vmla,
Vmls,

View file

@ -149,6 +149,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ResetSignal(handle);
}
public KernelResult ResetSignal32([R(0)] int handle)
{
return ResetSignal(handle);
}
private KernelResult ResetSignal(int handle)
{
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

View file

@ -103,6 +103,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{ 0x14, nameof(SvcHandler.UnmapSharedMemory32) },
{ 0x15, nameof(SvcHandler.CreateTransferMemory32) },
{ 0x16, nameof(SvcHandler.CloseHandle32) },
{ 0x17, nameof(SvcHandler.ResetSignal32) },
{ 0x18, nameof(SvcHandler.WaitSynchronization32) },
{ 0x1a, nameof(SvcHandler.ArbitrateLock32) },
{ 0x1b, nameof(SvcHandler.ArbitrateUnlock32) },