Add a few instructions and fix others. re-disable highCq for now.

Disabled the svc memory clear since i'm not sure about it.
This commit is contained in:
riperiperi 2020-01-10 14:07:20 +00:00 committed by Thog
parent 8068eb23e5
commit 50f3985b6f
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
17 changed files with 558 additions and 17 deletions

View file

@ -294,13 +294,15 @@ namespace ARMeilleure.Decoders
{
// TODO (CQ): ARM32 support.
return opCode.Instruction.Name == InstName.Bl ||
opCode.Instruction.Name == InstName.Blr;
opCode.Instruction.Name == InstName.Blr ||
opCode.Instruction.Name == InstName.Blx;
}
private static bool IsException(OpCode opCode)
{
return opCode.Instruction.Name == InstName.Brk ||
opCode.Instruction.Name == InstName.Svc ||
opCode.Instruction.Name == InstName.Trap ||
opCode.Instruction.Name == InstName.Und;
}

View file

@ -12,6 +12,7 @@ namespace ARMeilleure.Decoders
public int Size { get; protected set; }
public bool Q { get; private set; }
public bool F { get; private set; }
public bool U { get; private set; }
public int Elems => GetBytesCount() >> ((Size == 1) ? 1 : 2);
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
@ -19,6 +20,7 @@ namespace ARMeilleure.Decoders
Size = (opCode >> 20) & 0x1; //fvector size: 1 for 16 bit
Q = ((opCode >> 6) & 0x1) != 0;
F = ((opCode >> 10) & 0x1) != 0;
U = ((opCode >> 24) & 0x1) != 0;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{
/// <summary>
/// A special alias that always runs in 64 bit int, to speed up binary ops a little.
/// </summary>
class OpCode32SimdBinary : OpCode32SimdReg
{
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Size = 3;
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdCmpZ : OpCode32Simd
{
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Size = (opCode >> 18) & 0x1; //fvector size: 1 for 16 bit
}
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdVdupGP : OpCode32, IOpCode32Simd
{
public int Elems => GetBytesCount() >> ((Size == 1) ? 1 : 2);
public int Size { get; private set; }
public int Vd { get; private set; }
public int Rt { get; private set; }
public bool Q { get; private set; }
public OpCode32SimdVdupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); //B:E - 0 for 32, 16 then 8.
Q = ((opCode >> 21) & 0x1) != 0;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
Rt = ((opCode >> 12) & 0xf);
}
}
}

View file

@ -671,7 +671,13 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0011100xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluImm));
SetA32("<<<<0001100xxxxxxxxxxxxxxxx0xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsImm));
SetA32("<<<<0001100xxxxxxxxxxxxx0xx1xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsReg));
SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, typeof(OpCode32AluRsImm));
SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32)); //preload hint for cache - nop
SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32)); //rs imm
SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, typeof(OpCode32AluReg));
SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, typeof(OpCode32AluReg));
SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, typeof(OpCode32AluReg));
SetA32("<<<<011011111111xxxx11111011xxxx", InstName.Revsh, InstEmit32.Revsh, typeof(OpCode32AluReg));
SetA32("<<<<0010011xxxxxxxxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluImm));
SetA32("<<<<0000011xxxxxxxxxxxxxxxx0xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsImm));
SetA32("<<<<0000011xxxxxxxxxxxxx0xx1xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsReg));
@ -680,7 +686,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsReg));
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smlab, InstEmit32.Smlab, typeof(OpCode32AluMla));
SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal, InstEmit32.Smlal, typeof(OpCode32AluUmull));
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("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluImm));
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsImm));
@ -730,13 +737,37 @@ namespace ARMeilleure.Decoders
SetA32("<<<<11100x11xxxxxxxx10xxx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS));
SetA32("111100100x0xxxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg));
SetA32("111100100x0xxxxxxxxx1100xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary));
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100100x0xxxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
SetA32("111100110xxxxxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100110x0xxxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
SetA32("1111001x0xxxxxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100110x1xxxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
SetA32("1111001x0xxxxxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ));
//SetA32("111100110x0xxxxxxxxx1110xxx0xxxx", InstName.Vcle, InstEmit32.Vcle_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
//SetA32("1111001x0xxxxxxxxxxx0011xxx1xxxx", InstName.Vcle, InstEmit32.Vcle_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, typeof(OpCode32SimdCmpZ));
//SetA32("111100110x1xxxxxxxxx1110xxx0xxxx", InstName.Vclt, InstEmit32.Vclt_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
//SetA32("1111001x0xxxxxxxxxxx0011xxx0xxxx", InstName.Vclt, InstEmit32.Vclt_I, typeof(OpCode32SimdReg));
SetA32("<<<<11101x11010xxxxx10xx01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS));
SetA32("<<<<11101x11010xxxxx10xx11x0xxxx", InstName.Vcmpe,InstEmit32.Vcmpe, typeof(OpCode32SimdS));
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, typeof(OpCode32SimdS));
SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI));
SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI));
SetA32("<<<<11101x00xxxxxxxx10xxx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdVdupGP));
// VLD# missing single to all lanes
@ -807,6 +838,12 @@ namespace ARMeilleure.Decoders
SetA32("111100111x11xx01xxxx0x111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, typeof(OpCode32Simd));
SetA32("<<<<11101x110001xxxx10xx01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, typeof(OpCode32SimdS));
SetA32("<<<<11100x10xxxxxxxx10xxx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11100x01xxxxxxxx10xxx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11100x01xxxxxxxx10xxx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, typeof(OpCode32SimdRegS));
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, typeof(OpCode32SimdBinary));
SetA32("111111100xxxxxxxxxxx10xxx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, typeof(OpCode32SimdSel));
SetA32("111101001x00xxxxxxxx0000xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemSingle));

View file

@ -478,6 +478,29 @@ namespace ARMeilleure.Instructions
EmitAluStore(context, res);
}
public static void Pkh(ArmEmitterContext context)
{
OpCode32AluRsImm op = (OpCode32AluRsImm)context.CurrOp;
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand res = context.Call(new _U32_U32(SoftFallback.ReverseBits32), m);
bool tbform = op.ShiftType == ShiftType.Asr;
if (tbform)
{
res = context.BitwiseOr(context.BitwiseAnd(n, Const(0xFFFF0000)), context.BitwiseAnd(m, Const(0xFFFF)));
}
else
{
res = context.BitwiseOr(context.BitwiseAnd(m, Const(0xFFFF0000)), context.BitwiseAnd(n, Const(0xFFFF)));
}
EmitAluStore(context, res);
}
public static void Rbit(ArmEmitterContext context)
{
Operand m = GetAluM(context);
@ -486,6 +509,39 @@ namespace ARMeilleure.Instructions
EmitAluStore(context, res);
}
public static void Rev(ArmEmitterContext context)
{
OpCode32Alu op = (OpCode32Alu)context.CurrOp;
Operand m = GetAluM(context);
Operand res = context.Call(new _U32_U32(System.Buffers.Binary.BinaryPrimitives.ReverseEndianness), m);
EmitAluStore(context, res);
}
public static void Rev16(ArmEmitterContext context)
{
OpCode32Alu op = (OpCode32Alu)context.CurrOp;
Operand m = GetAluM(context);
Operand res = context.Call(new _U32_U32(SoftFallback.ReverseBytes16_32), m);
EmitAluStore(context, res);
}
public static void Revsh(ArmEmitterContext context)
{
OpCode32Alu op = (OpCode32Alu)context.CurrOp;
Operand m = GetAluM(context);
Operand res = context.Call(new _U32_U32(SoftFallback.ReverseBytes16_32), m);
EmitAluStore(context, context.SignExtend16(OperandType.I32, res));
}
public static void Bfc(ArmEmitterContext context)
{
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;

View file

@ -75,13 +75,13 @@ namespace ARMeilleure.Instructions
uint pc = op.GetPc();
Operand addr = GetIntA32(context, op.Rm);
Operand bitOne = context.BitwiseAnd(addr, Const(0));
Operand bitOne = context.BitwiseAnd(addr, Const(1));
bool isThumb = IsThumb(context.CurrOp);
uint currentPc = isThumb
? op.GetPc() | 1
: op.GetPc() - 4;
? pc | 1
: pc - 4;
SetIntOrSP(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
@ -90,5 +90,9 @@ namespace ARMeilleure.Instructions
addr = context.BitwiseOr(addr, Const(1)); // set call flag
context.Return(addr); // call
}
public static void Nop(ArmEmitterContext context)
{
}
}
}

View file

@ -73,20 +73,20 @@ namespace ARMeilleure.Instructions
if (op.NHigh)
{
n = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
n = context.SignExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
}
else
{
n = context.ZeroExtend16(OperandType.I32, n);
n = context.SignExtend16(OperandType.I32, n);
}
if (op.MHigh)
{
m = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(m, Const(16)));
m = context.SignExtend16(OperandType.I32, context.ShiftRightUI(m, Const(16)));
}
else
{
m = context.ZeroExtend16(OperandType.I32, m);
m = context.SignExtend16(OperandType.I32, m);
}
Operand res = context.Multiply(n, m);
@ -106,22 +106,50 @@ namespace ARMeilleure.Instructions
Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm);
n = context.SignExtend32(OperandType.I64, n);
m = context.SignExtend32(OperandType.I64, m);
Operand res = context.Multiply(n, m);
Operand toAdd = context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdHi)), Const(32));
toAdd = context.BitwiseOr(toAdd, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdLo)));
res = context.Add(res, toAdd);
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res);
if (op.SetFlags)
{
EmitNZFlagsCheck(context, res);
}
EmitGenericStore(context, op.RdHi, op.SetFlags, hi);
EmitGenericStore(context, op.RdLo, op.SetFlags, lo);
}
public static void Smlalh(ArmEmitterContext context)
{
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
Operand m = GetIntA32(context, op.Rm);
if (op.NHigh)
{
n = context.ZeroExtend16(OperandType.I64, context.ShiftRightUI(n, Const(16)));
n = context.SignExtend16(OperandType.I64, context.ShiftRightUI(n, Const(16)));
}
else
{
n = context.ZeroExtend16(OperandType.I64, n);
n = context.SignExtend16(OperandType.I64, n);
}
if (op.MHigh)
{
m = context.ZeroExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
}
else
{
m = context.ZeroExtend16(OperandType.I64, m);
m = context.SignExtend16(OperandType.I64, m);
}
Operand res = context.Multiply(n, m);

View file

@ -31,6 +31,45 @@ namespace ARMeilleure.Instructions
EmitVectorBinaryOpZx32(context, (op1, op2) => context.Add(op1, op2));
}
public static void Vand_I(ArmEmitterContext context)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseAnd(op1, op2));
}
public static void Vdup(ArmEmitterContext context)
{
OpCode32SimdVdupGP op = (OpCode32SimdVdupGP)context.CurrOp;
Operand insert = GetIntA32(context, op.Rt);
// zero extend into an I64, then replicate. Saves the most time over elementwise inserts
switch (op.Size)
{
case 2:
insert = context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u));
break;
case 1:
insert = context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u));
break;
case 0:
insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u));
break;
default:
throw new Exception("Unknown Vdup Size!");
}
InsertScalar(context, op.Vd, insert);
if (op.Q)
{
InsertScalar(context, op.Vd | 1, insert);
}
}
public static void Vorr_I(ArmEmitterContext context)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseOr(op1, op2));
}
public static void Vmov_S(ArmEmitterContext context)
{
EmitScalarUnaryOpF32(context, (op1) => op1);
@ -41,6 +80,47 @@ namespace ARMeilleure.Instructions
EmitScalarUnaryOpF32(context, (op1) => context.Negate(op1));
}
public static void Vnmul_S(ArmEmitterContext context)
{
EmitScalarBinaryOpF32(context, (op1, op2) => context.Negate(context.Multiply(op1, op2)));
}
public static void Vnmla_S(ArmEmitterContext context)
{
if (false) //Optimizations.FastFP)
{
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
{
return context.Negate(context.Add(op1, context.Multiply(op2, op3)));
});
}
else
{
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
{
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulAdd, SoftFloat64.FPNegMulAdd, op1, op2, op3);
});
}
}
public static void Vnmls_S(ArmEmitterContext context)
{
if (false)//Optimizations.FastFP)
{
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
{
return context.Subtract(op1, context.Multiply(op2, op3));
});
}
else
{
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
{
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulSub, SoftFloat64.FPNegMulSub, op1, op2, op3);
});
}
}
public static void Vneg_V(ArmEmitterContext context)
{
if ((context.CurrOp as OpCode32Simd).F)
@ -132,7 +212,7 @@ namespace ARMeilleure.Instructions
public static void Vmul_I(ArmEmitterContext context)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.Multiply(op1, op2));
EmitVectorBinaryOpSx32(context, (op1, op2) => context.Multiply(op1, op2));
}
public static void Vmla_S(ArmEmitterContext context)

View file

@ -12,8 +12,204 @@ using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
using Func2I = Func<Operand, Operand, Operand>;
static partial class InstEmit32
{
public static void Vceq_V(ArmEmitterContext context)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, false);
}
public static void Vceq_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, false, false);
}
public static void Vceq_Z(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.F)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, true);
}
else
{
EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, true, false);
}
}
public static void Vcge_V(ArmEmitterContext context)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, false);
}
public static void Vcge_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, false, !op.U);
}
public static void Vcge_Z(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.F)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, true);
}
else
{
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, true, true);
}
}
public static void Vcgt_V(ArmEmitterContext context)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, false);
}
public static void Vcgt_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, false, !op.U);
}
public static void Vcgt_Z(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.F)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, true);
}
else
{
EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, true, true);
}
}
public static void Vcle_V(ArmEmitterContext context)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, false);
}
public static void Vcle_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareLessOrEqual, context.ICompareLessOrEqualUI, false, !op.U);
}
public static void Vcle_Z(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.F)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, true);
}
else
{
EmitCmpOpI32(context, context.ICompareLessOrEqual, context.ICompareLessOrEqualUI, true, true);
}
}
public static void Vclt_V(ArmEmitterContext context)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, false);
}
public static void Vclt_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareLess, context.ICompareLessUI, false, !op.U);
}
public static void Vclt_Z(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.F)
{
EmitCmpOpF32(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, true);
}
else
{
EmitCmpOpI32(context, context.ICompareLess, context.ICompareLessUI, true, true);
}
}
private static void EmitCmpOpF32(
ArmEmitterContext context,
_F32_F32_F32 f32,
_F64_F64_F64 f64,
bool zero)
{
if (zero)
{
EmitVectorUnaryOpF32(context, (m) =>
{
OperandType type = m.Type;
if (type == OperandType.FP64) return context.Call(f64, m, new Operand(0.0));
else return context.Call(f32, m, new Operand(0.0));
});
}
else
{
EmitVectorBinaryOpF32(context, (n, m) =>
{
OperandType type = n.Type;
if (type == OperandType.FP64) return context.Call(f64, n, m);
else return context.Call(f32, n, m);
});
}
}
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
{
return context.ConditionalSelect(fromBool, Const(baseType, -1L), Const(baseType, 0L));
}
private static void EmitCmpOpI32(
ArmEmitterContext context,
Func2I signedOp,
Func2I unsignedOp,
bool zero,
bool signed)
{
if (zero)
{
if (signed)
{
EmitVectorUnaryOpSx32(context, (m) =>
{
OperandType type = m.Type;
Operand zeroV = (type == OperandType.I64) ? Const(0L) : Const(0);
return ZerosOrOnes(context, signedOp(m, zeroV), type);
});
}
else
{
EmitVectorUnaryOpZx32(context, (m) =>
{
OperandType type = m.Type;
Operand zeroV = (type == OperandType.I64) ? Const(0L) : Const(0);
return ZerosOrOnes(context, unsignedOp(m, zeroV), type);
});
}
}
else
{
if (signed)
{
EmitVectorBinaryOpSx32(context, (n, m) => ZerosOrOnes(context, signedOp(n, m), n.Type));
}
else
{
EmitVectorBinaryOpZx32(context, (n, m) => ZerosOrOnes(context, unsignedOp(n, m), n.Type));
}
}
}
public static void Vcmp(ArmEmitterContext context)
{
EmitVcmpOrVcmpe(context, false);

View file

@ -479,11 +479,16 @@ namespace ARMeilleure.Instructions
Mrc,
Mrrc,
Mvn,
Pkh,
Pld,
Rev,
Revsh,
Rsb,
Rsc,
Sbfx,
Smlab,
Smlal,
Smlalh,
Smmul,
Stl,
Stlb,
@ -510,10 +515,17 @@ namespace ARMeilleure.Instructions
// FP & SIMD (AArch32)
Vadd,
Vand,
Vceq,
Vcge,
Vcgt,
Vcle,
Vclt,
Vcmp,
Vcmpe,
Vcvt,
Vdiv,
Vdup,
Vld1,
Vld2,
Vld3,
@ -527,6 +539,10 @@ namespace ARMeilleure.Instructions
Vmsr,
Vmul,
Vneg,
Vnmul,
Vnmla,
Vnmls,
Vorr,
Vsel,
Vst1,
Vst2,

View file

@ -24,7 +24,7 @@ namespace ARMeilleure.Translation
public bool ShouldRejit()
{
return _rejit && Interlocked.Increment(ref _callCount) == MinCallsForRejit;
return false && Interlocked.Increment(ref _callCount) == MinCallsForRejit;
}
}
}

View file

@ -667,7 +667,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
[R(1)] uint sizeLow,
[R(4)] uint sizeHigh)
{
_process.CpuMemory.WriteBytes(addressLow, new byte[sizeLow]);
//_process.CpuMemory.WriteBytes(addressLow, new byte[sizeLow]);
return KernelResult.Success;
}
}

View file

@ -114,6 +114,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{ 0x26, nameof(SvcHandler.Break32) },
{ 0x27, nameof(SvcHandler.OutputDebugString32) },
{ 0x29, nameof(SvcHandler.GetInfo32) },
{ 0x34, nameof(SvcHandler.WaitForAddress32) },
{ 0x35, nameof(SvcHandler.SignalToAddress32) },
{ 0x5F, nameof(SvcHandler.FlushProcessDataCache32) }
};

View file

@ -194,6 +194,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return WaitForAddress(address, type, value, timeout);
}
public KernelResult WaitForAddress32([R(0)] uint address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] uint timeoutLow, [R(4)] uint timeoutHigh)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
return WaitForAddress(address, type, value, timeout);
}
private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout)
{
if (IsPointingInsideKernel(address))
@ -237,6 +243,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SignalToAddress(address, type, value, count);
}
public KernelResult SignalToAddress32([R(0)] uint address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count)
{
return SignalToAddress(address, type, value, count);
}
private KernelResult SignalToAddress(ulong address, SignalType type, int value, int count)
{
if (IsPointingInsideKernel(address))

View file

@ -52,5 +52,55 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("UBFX <Rd>, <Rn>, #<lsb>, #<width>")]
public void Ubfx([Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1)
{
if (lsb + widthm1 > 31)
{
widthm1 -= (lsb + widthm1) - 31;
}
uint opcode = 0xe7e00050; // UBFX r0, r0, #0, #1
opcode |= ((rd & 0xf) << 12);
opcode |= ((rn & 0xf) << 0);
opcode |= ((widthm1 & 31) << 16) | ((lsb & 31) << 7);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: wd, r1: wn, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("SBFX <Rd>, <Rn>, #<lsb>, #<width>")]
public void Sbfx([Values(0u, 0xdu)] uint rd,
[Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1)
{
if (lsb + widthm1 > 31)
{
widthm1 -= (lsb + widthm1) - 31;
}
uint opcode = 0xe7a00050; // SBFX r0, r0, #0, #1
opcode |= ((rd & 0xf) << 12);
opcode |= ((rn & 0xf) << 0);
opcode |= ((widthm1 & 31) << 16) | ((lsb & 31) << 7);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r0: wd, r1: wn, sp: sp);
CompareAgainstUnicorn();
}
}
}