Address Feedback from LDj3SNuD

Opcode table reordered to have alphabetical sorting within groups,
Vmaxnm and Vminnm have split names to be less ambiguous, SoftFloat nits,
Test nits and Test simplification with ValueSource.
This commit is contained in:
riperiperi 2020-02-13 22:26:09 +00:00
commit ea6fc47fac
11 changed files with 168 additions and 407 deletions

View file

@ -73,23 +73,6 @@
return (imm, size); return (imm, size);
} }
public static long VFPExpandImm(long imm, int n)
{
int e = (n == 16) ? 5 : ((n == 32) ? 8 : 11);
int f = (n) * 8 - e - 1;
long sign = (imm & 0x80) << (n - 8);
var bit6 = (imm >> 6) & 0x1;
long exp = ((imm >> 4) & 0x3);
if (bit6 == 1) exp |= ShlOnes(0, e - 3) << 2;
if (bit6 == 0) exp |= (long)1 << (e - 1);
long frac = (imm & 0xf) << (f - 4);
return sign | (exp << f) | frac;
}
private static long ShlOnes(long value, int shift) private static long ShlOnes(long value, int shift)
{ {
if (shift != 0) if (shift != 0)

View file

@ -741,32 +741,32 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx)); SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx));
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx)); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
// FP & SIMD (AArch32) // FP & SIMD
SetA32("<<<<11101x110000xxxx10xx11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11101x110000xxxx10xx11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, typeof(OpCode32SimdRegS));
SetA32("111100111x11xx01xxxx0x110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdReg)); SetA32("111100111x11xx01xxxx0x110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdReg));
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS));
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg)); SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg));
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary)); SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary));
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, typeof(OpCode32SimdBinary)); SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, typeof(OpCode32SimdBinary));
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, typeof(OpCode32SimdBinary));
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary)); SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary));
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, typeof(OpCode32SimdBinary));
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg));
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg)); SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg));
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg));
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg)); SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg));
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg));
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg)); SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg));
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ));
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ));
@ -774,11 +774,11 @@ namespace ARMeilleure.Decoders
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS)); SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS));
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS)); SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS));
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, typeof(OpCode32SimdCmpZ)); // FP and integer, vector.
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, typeof(OpCode32SimdS)); // FP 32 and 64, scalar. SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, typeof(OpCode32SimdS)); // FP 32 and 64, scalar.
SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // FP32 to int. SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // FP32 to int.
SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // Int to FP32. SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // Int to FP32.
SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // The many FP32 to int encodings (fp). SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // The many FP32 to int encodings (fp).
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, typeof(OpCode32SimdCmpZ)); // FP and integer, vector.
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP)); SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP));
@ -812,19 +812,20 @@ namespace ARMeilleure.Decoders
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, typeof(OpCode32SimdMemImm)); SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, typeof(OpCode32SimdMemImm));
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, typeof(OpCode32SimdReg));
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, typeof(OpCode32SimdReg)); SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, typeof(OpCode32SimdReg));
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, typeof(OpCode32SimdReg));
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg));
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, typeof(OpCode32SimdReg)); SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, typeof(OpCode32SimdReg));
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg));
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.VMMmn, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS)); SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS));
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.VMMmn, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS)); SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg));
SetA32("111100110xxxxxxxxxxx1111xxx1xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg)); SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS));
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg));
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, typeof(OpCode32SimdReg));
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS));
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, typeof(OpCode32SimdReg)); SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, typeof(OpCode32SimdReg));
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, typeof(OpCode32SimdRegElem)); SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, typeof(OpCode32SimdRegElem));
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, typeof(OpCode32SimdRegS));
@ -849,26 +850,26 @@ namespace ARMeilleure.Decoders
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, typeof(OpCode32SimdSpecial)); SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, typeof(OpCode32SimdSpecial));
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, typeof(OpCode32SimdSpecial)); SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, typeof(OpCode32SimdSpecial));
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, typeof(OpCode32SimdRegElem));
SetA32("1111001x0xxxxxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, typeof(OpCode32SimdReg));
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, typeof(OpCode32SimdRegS));
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, typeof(OpCode32SimdReg)); SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, typeof(OpCode32SimdReg));
SetA32("1111001x0xxxxxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, typeof(OpCode32SimdRegElem));
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); // D/Q vector I32. SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); // D/Q vector I32.
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
SetA32("111100111x11xx01xxxx0x111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, typeof(OpCode32Simd));
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, typeof(OpCode32SimdS)); SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, typeof(OpCode32SimdS));
SetA32("111100111x11xx01xxxx0x111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, typeof(OpCode32Simd));
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, typeof(OpCode32SimdRegS));
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, typeof(OpCode32SimdBinary)); SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, typeof(OpCode32SimdBinary));
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, typeof(OpCode32SimdReg));
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, typeof(OpCode32SimdReg)); SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, typeof(OpCode32SimdReg));
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, typeof(OpCode32SimdReg));
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, typeof(OpCode32SimdRev)); SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, typeof(OpCode32SimdRev));
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, typeof(OpCode32SimdCvtFI)); SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, typeof(OpCode32SimdCvtFI));
@ -876,8 +877,8 @@ namespace ARMeilleure.Decoders
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, typeof(OpCode32SimdSel)); SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, typeof(OpCode32SimdSel));
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, typeof(OpCode32SimdReg));
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShImm)); SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShImm));
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, typeof(OpCode32SimdShImm)); SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, typeof(OpCode32SimdShImm));
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, typeof(OpCode32SimdShImm)); SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, typeof(OpCode32SimdShImm));
@ -905,22 +906,22 @@ namespace ARMeilleure.Decoders
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult)); SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult)); SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, typeof(OpCode32SimdMemImm));
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS));
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, typeof(OpCode32SimdSqrte)); SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, typeof(OpCode32SimdSqrte));
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, typeof(OpCode32SimdReg)); SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, typeof(OpCode32SimdReg));
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, typeof(OpCode32SimdSqrte)); SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, typeof(OpCode32SimdSqrte));
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, typeof(OpCode32SimdReg)); SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, typeof(OpCode32SimdReg));
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS));
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, typeof(OpCode32SimdMemImm));
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, typeof(OpCode32SimdReg));
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, typeof(OpCode32SimdRegS));
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, typeof(OpCode32SimdReg)); SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, typeof(OpCode32SimdReg));
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, typeof(OpCode32SimdTbl)); SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, typeof(OpCode32SimdTbl));
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, typeof(OpCode32SimdCmpZ));
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, typeof(OpCode32SimdCmpZ));
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, typeof(OpCode32SimdCmpZ));
#endregion #endregion
FillFastLookupTable(_instA32FastLookup, _allInstA32); FillFastLookupTable(_instA32FastLookup, _allInstA32);
FillFastLookupTable(_instT32FastLookup, _allInstT32); FillFastLookupTable(_instT32FastLookup, _allInstT32);

View file

@ -544,10 +544,11 @@ namespace ARMeilleure.Instructions
Vldm, Vldm,
Vldr, Vldr,
Vmax, Vmax,
Vmaxnm,
Vmin, Vmin,
Vminnm,
Vmla, Vmla,
Vmls, Vmls,
VMMmn,
Vmov, Vmov,
Vmovn, Vmovn,
Vmrs, Vmrs,

View file

@ -119,10 +119,9 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
private static float _DefaultNaN = BitConverter.Int32BitsToSingle(0x7fc00000);
private static float FPDefaultNaN() private static float FPDefaultNaN()
{ {
return _DefaultNaN; return BitConverter.Int32BitsToSingle(0x7fc00000);
} }
private static float FPInfinity(bool sign) private static float FPInfinity(bool sign)
@ -1343,6 +1342,7 @@ namespace ARMeilleure.Instructions
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
float product; float product;
if ((inf1 && zero2) || (zero1 && inf2)) if ((inf1 && zero2) || (zero1 && inf2))
{ {
product = FPZero(false); product = FPZero(false);
@ -1506,6 +1506,7 @@ namespace ARMeilleure.Instructions
{ {
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero; bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
if (inf1 && inf2 && sign1 == sign2) if (inf1 && inf2 && sign1 == sign2)
{ {
result = FPDefaultNaN(); result = FPDefaultNaN();
@ -1527,6 +1528,7 @@ namespace ARMeilleure.Instructions
else else
{ {
result = (value1 - value2) / 2.0f; result = (value1 - value2) / 2.0f;
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result)) if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
{ {
context.Fpsr |= FPSR.Ufc; context.Fpsr |= FPSR.Ufc;
@ -1555,6 +1557,7 @@ namespace ARMeilleure.Instructions
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
float product; float product;
if ((inf1 && zero2) || (zero1 && inf2)) if ((inf1 && zero2) || (zero1 && inf2))
{ {
product = FPZero(false); product = FPZero(false);
@ -1563,9 +1566,8 @@ namespace ARMeilleure.Instructions
{ {
product = FPMulFpscr(value1, value2, true); product = FPMulFpscr(value1, value2, true);
} }
float three = FPThree(false); result = FPHalvedSub(FPThree(false), product, context, fpcr);
result = FPHalvedSub(three, product, context, fpcr);
} }
return result; return result;
@ -1708,11 +1710,9 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
private static float _DefaultNaN = BitConverter.Int32BitsToSingle(0x7fc00000);
private static float FPDefaultNaN() private static float FPDefaultNaN()
{ {
return _DefaultNaN; return BitConverter.Int32BitsToSingle(0x7fc00000);
} }
private static float FPInfinity(bool sign) private static float FPInfinity(bool sign)
@ -2635,6 +2635,7 @@ namespace ARMeilleure.Instructions
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
double product; double product;
if ((inf1 && zero2) || (zero1 && inf2)) if ((inf1 && zero2) || (zero1 && inf2))
{ {
product = FPZero(false); product = FPZero(false);
@ -2819,6 +2820,7 @@ namespace ARMeilleure.Instructions
else else
{ {
result = (value1 - value2) / 2.0; result = (value1 - value2) / 2.0;
if ((fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result)) if ((fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result))
{ {
context.Fpsr |= FPSR.Ufc; context.Fpsr |= FPSR.Ufc;
@ -2847,6 +2849,7 @@ namespace ARMeilleure.Instructions
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero; bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
double product; double product;
if ((inf1 && zero2) || (zero1 && inf2)) if ((inf1 && zero2) || (zero1 && inf2))
{ {
product = FPZero(false); product = FPZero(false);
@ -2856,8 +2859,7 @@ namespace ARMeilleure.Instructions
product = FPMulFpscr(value1, value2, true); product = FPMulFpscr(value1, value2, true);
} }
double three = FPThree(false); result = FPHalvedSub(FPThree(false), product, context, fpcr);
result = FPHalvedSub(three, product, context, fpcr);
} }
return result; return result;
@ -3000,10 +3002,9 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
private static double _DefaultNaN = BitConverter.Int64BitsToDouble(0x7ff8000000000000);
private static double FPDefaultNaN() private static double FPDefaultNaN()
{ {
return _DefaultNaN; return BitConverter.Int64BitsToDouble(0x7ff8000000000000);
} }
private static double FPInfinity(bool sign) private static double FPInfinity(bool sign)

View file

@ -1,13 +1,27 @@
#define Alu32 #define Alu32
using NUnit.Framework; using NUnit.Framework;
using System; using System;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
#if Alu32
[Category("Alu32")] [Category("Alu32")]
class CpuTestAlu32 : CpuTest32 public sealed class CpuTestAlu32 : CpuTest32
{ {
#if Alu32
#region "ValueSource (Opcodes)"
private static uint[] _Lsr_Lsl_Asr_Ror_()
{
return new uint[]
{
0xe1b00030u, // LSRS R0, R0, R0
0xe1b00010u, // LSLS R0, R0, R0
0xe1b00050u, // ASRS R0, R0, R0
0xe1b00070u // RORS R0, R0, R0
};
}
#endregion
private const int RndCnt = 2; private const int RndCnt = 2;
[Test, Pairwise, Description("RBIT <Rd>, <Rn>")] [Test, Pairwise, Description("RBIT <Rd>, <Rn>")]
@ -26,60 +40,12 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise, Description("LSRS {<Rd>,} <Rm>, <Rs>")] [Test, Pairwise]
public void Lsr([Values(0x00000000u, 0x7FFFFFFFu, public void Lsr_Lsl_Asr_Ror([ValueSource("_Lsr_Lsl_Asr_Ror_")] uint opcode,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue, [Values(0x00000000u, 0x7FFFFFFFu,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount)
{ {
uint opcode = 0xe1b00030u; // LSRS R0, R0, R0
uint rd = 0;
uint rm = 1;
uint rs = 2;
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8);
SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("LSLS {<Rd>,} <Rm>, <Rs>")]
public void Lsl([Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount)
{
uint opcode = 0xe1b00010u; // LSLS R0, R0, R0
uint rd = 0;
uint rm = 1;
uint rs = 2;
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8);
SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("ASRS {<Rd>,} <Rm>, <Rs>")]
public void Asr([Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount)
{
uint opcode = 0xe1b00050u; // ASRS R0, R0, R0
uint rd = 0;
uint rm = 1;
uint rs = 2;
opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8);
SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("RORS {<Rd>,} <Rm>, <Rs>")]
public void Ror([Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint shiftValue,
[Range(0, 31)] [Values(32, 256, 768, -1, -23)] int shiftAmount)
{
uint opcode = 0xe1b00070u; // RORS R0, R0, R0
uint rd = 0; uint rd = 0;
uint rm = 1; uint rm = 1;
uint rs = 2; uint rs = 2;
@ -89,6 +55,6 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif
} }
#endif
} }

View file

@ -4,25 +4,50 @@ using NUnit.Framework;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
[Category("AluRs")] [Category("AluRs32")]
public sealed class CpuTestAluRs32 : CpuTest32 public sealed class CpuTestAluRs32 : CpuTest32
{ {
#if AluRs32 #if AluRs32
private const int RndCnt = 5; #region "ValueSource (Opcodes)"
private const int RndCntAmount = 50; private static uint[] _Add_Adds_Rsb_Rsbs_()
private const int RndCntLsb = 2; {
return new uint[]
[Test, Pairwise, Description("ADC <Rd>, <Rn>, <Rm>")] {
public void Adc([Values(0u, 13u)] uint rd, 0xe0800000u, // ADD R0, R0, R0, LSL #0
[Values(1u, 13u)] uint rn, 0xe0900000u, // ADDS R0, R0, R0, LSL #0
[Values(2u, 13u)] uint rm, 0xe0600000u, // RSB R0, R0, R0, LSL #0
[Values(0x00000000u, 0x7FFFFFFFu, 0xe0700000u // RSBS R0, R0, R0, LSL #0
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, };
[Values(0x00000000u, 0x7FFFFFFFu, }
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn) private static uint[] _Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_()
{
return new uint[]
{
0xe0a00000u, // ADC R0, R0, R0
0xe0b00000u, // ADCS R0, R0, R0
0xe0e00000u, // RSC R0, R0, R0
0xe0f00000u, // RSCS R0, R0, R0
0xe0c00000u, // SBC R0, R0, R0
0xe0d00000u // SBCS R0, R0, R0
};
}
#endregion
private const int RndCnt = 2;
private const int RndCntAmount = 2;
[Test, Pairwise]
public void Adc_Adcs_Rsc_Rscs_Sbc_Sbcs([ValueSource("_Adc_Adcs_Rsc_Rscs_Sbc_Sbcs_")] uint opcode,
[Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn)
{ {
uint opcode = 0xe0a00000u; // ADC R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt(); uint sp = TestContext.CurrentContext.Random.NextUInt();
@ -32,38 +57,18 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise, Description("ADCS <Rd>, <Rn>, <Rm>")] [Test, Pairwise]
public void Adcs([Values(0u, 13u)] uint rd, public void Add_Adds_Rsb_Rsbs([ValueSource("_Add_Adds_Rsb_Rsbs_")] uint opcode,
[Values(1u, 13u)] uint rn, [Values(0u, 13u)] uint rd,
[Values(2u, 13u)] uint rm, [Values(1u, 13u)] uint rn,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(2u, 13u)] uint rm,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, [Values(0x00000000u, 0x7FFFFFFFu,
[Values(0x00000000u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm, [Values(0x00000000u, 0x7FFFFFFFu,
[Values] bool carryIn) 0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
{ {
uint opcode = 0xe0b00000u; // ADCS R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("ADD <Rd>, <Rn>, <Rm>{, <shift> #<amount>}")]
public void Add([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
{
uint opcode = 0xe0800000u; // ADD R0, R0, R0, LSL #0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12); opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
opcode |= ((shift & 3) << 5) | ((amount & 31) << 7); opcode |= ((shift & 3) << 5) | ((amount & 31) << 7);
@ -73,152 +78,6 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Pairwise, Description("ADDS <Rd>, <Rn>, <Rm>{, <shift> #<amount>}")]
public void Adds([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
{
uint opcode = 0xe0900000u; // ADDS R0, R0, R0, LSL #0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
opcode |= ((shift & 3) << 5) | ((amount & 31) << 7);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("RSB <Rd>, <Rn>, <Rm>{, <shift> #<amount>}")]
public void Rsb([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
{
uint opcode = 0xe0600000u; // RSB R0, R0, R0, LSL #0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
opcode |= ((shift & 3) << 5) | ((amount & 31) << 7);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("RSBS <Rd>, <Rn>, <Rm>{, <shift> #<amount>}")]
public void Rsbs([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values(0b00u, 0b01u, 0b10u, 0b11u)] uint shift, // <LSL, LSR, ASR, ROR>
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntAmount)] uint amount)
{
uint opcode = 0xe0700000u; // RSBS R0, R0, R0, LSL #0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
opcode |= ((shift & 3) << 5) | ((amount & 31) << 7);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("RSB <Rd>, <Rn>, <Rm>")]
public void Rsc([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0xe0e00000u; // RSC R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("RSCS <Rd>, <Rn>, <Rm>")]
public void Rscs([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0xe0f00000u; // RSCS R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("SBC <Rd>, <Rn>, <Rm>")]
public void Sbc([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0xe0c00000u; // SBC R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("SBCS <Rd>, <Rn>, <Rm>")]
public void Sbcs([Values(0u, 13u)] uint rd,
[Values(1u, 13u)] uint rn,
[Values(2u, 13u)] uint rm,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
[Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
[Values] bool carryIn)
{
uint opcode = 0xe0d00000u; // SBCS R0, R0, R0
opcode |= ((rm & 15) << 0) | ((rn & 15) << 16) | ((rd & 15) << 12);
uint sp = TestContext.CurrentContext.Random.NextUInt();
SingleOpcode(opcode, r1: wn, r2: wm, sp: sp, carry: carryIn);
CompareAgainstUnicorn();
}
#endif #endif
} }
} }

View file

@ -1,14 +1,17 @@
using NUnit.Framework; #define Bf32
using NUnit.Framework;
using System; using System;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
[Category("Bfm")] [Category("Bf32")]
public sealed class CpuTestBf32 : CpuTest32 public sealed class CpuTestBf32 : CpuTest32
{ {
private const int RndCnt = 10; #if Bf32
private const int RndCntImmr = 10; private const int RndCnt = 2;
private const int RndCntImms = 10; private const int RndCntImmr = 2;
private const int RndCntImms = 2;
[Test, Pairwise, Description("BFC <Rd>, #<lsb>, #<width>")] [Test, Pairwise, Description("BFC <Rd>, #<lsb>, #<width>")]
public void Bfc([Values(0u, 0xdu)] uint rd, public void Bfc([Values(0u, 0xdu)] uint rd,
@ -81,7 +84,7 @@ namespace Ryujinx.Tests.Cpu
[Values(1u, 0xdu)] uint rn, [Values(1u, 0xdu)] uint rn,
[Random(RndCnt)] uint wd, [Random(RndCnt)] uint wd,
[Values(0x00000000u, 0x7FFFFFFFu, [Values(0x00000000u, 0x7FFFFFFFu,
0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn, 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, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1) [Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint widthm1)
{ {
@ -100,5 +103,6 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
#endif
} }
} }

View file

@ -1,4 +1,5 @@
#define SimdLogical32 #define SimdLogical32
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
@ -6,13 +7,33 @@ using System;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
[Category("SimdLogical32")] [Category("SimdLogical32")]
class CpuTestSimdLogical32 : CpuTest32 public sealed class CpuTestSimdLogical32 : CpuTest32
{ {
#if SimdLogical32 #if SimdLogical32
#region "ValueSource (Opcodes)"
private static uint[] _Vbif_Vbit_Vbsl_Vand_()
{
return new uint[]
{
0xf3300110u, // VBIF D0, D0, D0
0xf3200110u, // VBIT D0, D0, D0
0xf3100110u, // VBSL D0, D0, D0
0xf2000110u // VAND D0, D0, D0
};
}
#endregion
private const int RndCnt = 5; private const int RndCnt = 2;
private uint GenerateVectorOpcode(uint opcode, uint rd, uint rn, uint rm, bool q) [Test, Pairwise]
public void Vbif_Vbit_Vbsl_Vand([ValueSource("_Vbif_Vbit_Vbsl_Vand_")] uint opcode,
[Range(0u, 4u)] uint rd,
[Range(0u, 4u)] uint rn,
[Range(0u, 4u)] uint rm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q)
{ {
if (q) if (q)
{ {
@ -26,80 +47,6 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3); opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
return opcode;
}
[Test, Pairwise, Description("VBIF {<Vd>}, <Vm>, <Vn>")]
public void Vbif([Range(0u, 4u)] uint rd,
[Range(0u, 4u)] uint rn,
[Range(0u, 4u)] uint rm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q)
{
uint opcode = GenerateVectorOpcode(0xf3300110u, rd, rn, rm, q); // VBIF D0, D0, D0
V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a, z);
V128 v2 = MakeVectorE0E1(b, z);
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("VBIT {<Vd>}, <Vm>, <Vn>")]
public void Vbit([Range(0u, 4u)] uint rd,
[Range(0u, 4u)] uint rn,
[Range(0u, 4u)] uint rm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q)
{
uint opcode = GenerateVectorOpcode(0xf3200110u, rd, rn, rm, q); // VBIT D0, D0, D0
V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a, z);
V128 v2 = MakeVectorE0E1(b, z);
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("VBSL {<Vd>}, <Vm>, <Vn>")]
public void Vbsl([Range(0u, 4u)] uint rd,
[Range(0u, 4u)] uint rn,
[Range(0u, 4u)] uint rm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q)
{
uint opcode = GenerateVectorOpcode(0xf3100110u, rd, rn, rm, q); // VBSL D0, D0, D0
V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a, z);
V128 v2 = MakeVectorE0E1(b, z);
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("VAND {<Vd>}, <Vm>, <Vn>")]
public void Vand([Range(0u, 4u)] uint rd,
[Range(0u, 4u)] uint rn,
[Range(0u, 4u)] uint rm,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q)
{
uint opcode = GenerateVectorOpcode(0xf2000110u, rd, rn, rm, q); // VAND D0, D0, D0
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a, z); V128 v1 = MakeVectorE0E1(a, z);
V128 v2 = MakeVectorE0E1(b, z); V128 v2 = MakeVectorE0E1(b, z);

View file

@ -1,4 +1,4 @@
#define SimdMem32 #define SimdMemory32
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
@ -9,7 +9,7 @@ namespace Ryujinx.Tests.Cpu
[Category("SimdMemory32")] [Category("SimdMemory32")]
public sealed class CpuTestSimdMemory32 : CpuTest32 public sealed class CpuTestSimdMemory32 : CpuTest32
{ {
#if SimdMem32 #if SimdMemory32
private const int RndCntImm = 2; private const int RndCntImm = 2;
private uint[] LDSTModes = private uint[] LDSTModes =

View file

@ -14,7 +14,7 @@ namespace Ryujinx.Tests.Cpu
#if SimdMov32 #if SimdMov32
private const int RndCntImm = 10; private const int RndCntImm = 10;
[Test, Combinatorial, Description("VMOV.I<size> <Dd/Qd>, #<imm>")] [Test, Pairwise, Description("VMOV.I<size> <Dd/Qd>, #<imm>")]
public void Movi_V([Range(0u, 10u)] uint variant, public void Movi_V([Range(0u, 10u)] uint variant,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm, [Values(0x0u)] [Random(1u, 0xffu, RndCntImm)] uint imm,
@ -62,7 +62,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VMOV.F<size> <Sd>, #<imm>")] [Test, Pairwise, Description("VMOV.F<size> <Sd>, #<imm>")]
public void Movi_S([Range(2u, 3u)] uint size, public void Movi_S([Range(2u, 3u)] uint size,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm) [Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm)
@ -107,7 +107,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VMOV.<size> <Rt>, <Dn[x]>")] [Test, Pairwise, Description("VMOV.<size> <Rt>, <Dn[x]>")]
public void Mov_GP_Elem([Range(0u, 7u)] uint vn, public void Mov_GP_Elem([Range(0u, 7u)] uint vn,
[Values(0u, 1u, 2u, 3u)] uint rt, [Values(0u, 1u, 2u, 3u)] uint rt,
[Range(0u, 2u)] uint size, [Range(0u, 2u)] uint size,
@ -206,7 +206,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VMOVN.<size> <Dt>, <Qm>")] [Test, Pairwise, Description("VMOVN.<size> <Dt>, <Qm>")]
public void Movn_V([Range(0u, 1u, 2u)] uint size, public void Movn_V([Range(0u, 1u, 2u)] uint size,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 2u, 4u, 8u)] uint vm) [Values(0u, 2u, 4u, 8u)] uint vm)
@ -230,7 +230,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VTRN.<size> <Vd>, <Vm>")] [Test, Pairwise, Description("VTRN.<size> <Vd>, <Vm>")]
public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm, public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size, [Values(0u, 1u, 2u)] uint size,
@ -263,7 +263,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VZIP.<size> <Vd>, <Vm>")] [Test, Pairwise, Description("VZIP.<size> <Vd>, <Vm>")]
public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm, public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size, [Values(0u, 1u, 2u)] uint size,
@ -296,7 +296,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VUZP.<size> <Vd>, <Vm>")] [Test, Pairwise, Description("VUZP.<size> <Vd>, <Vm>")]
public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm, public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size, [Values(0u, 1u, 2u)] uint size,
@ -329,7 +329,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VTBL.8 <Dd>, {list}, <Dm>")] [Test, Pairwise, Description("VTBL.8 <Dd>, {list}, <Dm>")]
public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid. public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid.
[Range(4u, 12u)] uint vn, // Selection. [Range(4u, 12u)] uint vn, // Selection.
[Values(0u, 1u)] uint vd, // Destinations. [Values(0u, 1u)] uint vd, // Destinations.
@ -378,7 +378,7 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VEXT.8 {<Vd>,} <Vn>, <Vm>, #<imm>")] [Test, Pairwise, Description("VEXT.8 {<Vd>,} <Vn>, <Vm>, #<imm>")]
public void Vext([Values(0u, 1u, 2u, 3u)] uint vm, public void Vext([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vn, [Values(0u, 1u, 2u, 3u)] uint vn,
[Values(0u, 1u, 2u, 3u)] uint vd, [Values(0u, 1u, 2u, 3u)] uint vd,

View file

@ -4,13 +4,12 @@ using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
[Category("SimdReg32")] [Category("SimdReg32")]
public sealed class CpuTestSimdReg32 : CpuTest32 { public sealed class CpuTestSimdReg32 : CpuTest32
{
#if SimdReg32 #if SimdReg32
#region "ValueSource (Types)" #region "ValueSource (Types)"
@ -224,11 +223,10 @@ namespace Ryujinx.Tests.Cpu
uint opcode = 0xf2000d00u; // VADD.F32 D0, D0, D0 uint opcode = 0xf2000d00u; // VADD.F32 D0, D0, D0
if (q) if (q)
{ {
rm <<= 2;
rn <<= 2;
rd <<= 2;
opcode |= 1 << 6; opcode |= 1 << 6;
rm <<= 1;
rn <<= 1;
rd <<= 1;
} }
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
@ -326,7 +324,8 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn(); CompareAgainstUnicorn();
} }
[Test, Combinatorial, Description("VPADD.f32 V0, V0, V0")] [Explicit]
[Test, Pairwise, Description("VPADD.f32 V0, V0, V0")]
public void Vpadd_f32([Values(0u)] uint rd, public void Vpadd_f32([Values(0u)] uint rd,
[Range(0u, 7u)] uint rn, [Range(0u, 7u)] uint rn,
[Range(0u, 7u)] uint rm) [Range(0u, 7u)] uint rm)