Implement some more instructions, fix others.
Uxtab16/Sxtab16 are untested.
This commit is contained in:
parent
fc2d482616
commit
3d9d492b22
9 changed files with 169 additions and 10 deletions
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) },
|
||||
|
|
Loading…
Add table
Reference in a new issue