OpCode cleanup

This commit is contained in:
riperiperi 2020-01-18 23:36:28 +00:00
parent 969f197028
commit 4d13cb0446
26 changed files with 159 additions and 82 deletions

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.Decoders
Imm8ToFP64Table = BuildImm8ToFP64Table();
}
public static readonly uint[] Imm8ToFP32Table;
public static readonly uint[] Imm8ToFP32Table;
public static readonly ulong[] Imm8ToFP64Table;
private static uint[] BuildImm8ToFP32Table()
@ -46,11 +46,11 @@ namespace ARMeilleure.Decoders
}
return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) |
MoveBit(imm, 6, 29) | MoveBit( imm, 6, 28) |
MoveBit(imm, 6, 27) | MoveBit( imm, 6, 26) |
MoveBit(imm, 6, 25) | MoveBit( imm, 5, 24) |
MoveBit(imm, 4, 23) | MoveBit( imm, 3, 22) |
MoveBit(imm, 2, 21) | MoveBit( imm, 1, 20) |
MoveBit(imm, 6, 29) | MoveBit(imm, 6, 28) |
MoveBit(imm, 6, 27) | MoveBit(imm, 6, 26) |
MoveBit(imm, 6, 25) | MoveBit(imm, 5, 24) |
MoveBit(imm, 4, 23) | MoveBit(imm, 3, 22) |
MoveBit(imm, 2, 21) | MoveBit(imm, 1, 20) |
MoveBit(imm, 0, 19);
}
@ -63,21 +63,21 @@ namespace ARMeilleure.Decoders
}
return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) |
MoveBit(imm, 6, 61) | MoveBit( imm, 6, 60) |
MoveBit(imm, 6, 59) | MoveBit( imm, 6, 58) |
MoveBit(imm, 6, 57) | MoveBit( imm, 6, 56) |
MoveBit(imm, 6, 55) | MoveBit( imm, 6, 54) |
MoveBit(imm, 5, 53) | MoveBit( imm, 4, 52) |
MoveBit(imm, 3, 51) | MoveBit( imm, 2, 50) |
MoveBit(imm, 1, 49) | MoveBit( imm, 0, 48);
MoveBit(imm, 6, 61) | MoveBit(imm, 6, 60) |
MoveBit(imm, 6, 59) | MoveBit(imm, 6, 58) |
MoveBit(imm, 6, 57) | MoveBit(imm, 6, 56) |
MoveBit(imm, 6, 55) | MoveBit(imm, 6, 54) |
MoveBit(imm, 5, 53) | MoveBit(imm, 4, 52) |
MoveBit(imm, 3, 51) | MoveBit(imm, 2, 50) |
MoveBit(imm, 1, 49) | MoveBit(imm, 0, 48);
}
public struct BitMask
{
public long WMask;
public long TMask;
public int Pos;
public int Shift;
public int Pos;
public int Shift;
public bool IsUndefined;
public static BitMask Invalid => new BitMask { IsUndefined = true };
@ -88,7 +88,7 @@ namespace ARMeilleure.Decoders
int immS = (opCode >> 10) & 0x3f;
int immR = (opCode >> 16) & 0x3f;
int n = (opCode >> 22) & 1;
int n = (opCode >> 22) & 1;
int sf = (opCode >> 31) & 1;
int length = BitUtils.HighestBitSet((~immS & 0x3f) | (n << 6));
@ -115,7 +115,7 @@ namespace ARMeilleure.Decoders
if (r > 0)
{
wMask = BitUtils.RotateRight(wMask, r, size);
wMask = BitUtils.RotateRight(wMask, r, size);
wMask &= BitUtils.FillWithOnes(size);
}
@ -124,7 +124,7 @@ namespace ARMeilleure.Decoders
WMask = BitUtils.Replicate(wMask, size),
TMask = BitUtils.Replicate(tMask, size),
Pos = immS,
Pos = immS,
Shift = immR
};
}
@ -148,5 +148,19 @@ namespace ARMeilleure.Decoders
{
return (((long)opCode << 45) >> 48) & ~3;
}
public static bool VectorArgumentsInvalid(bool q, params int[] args)
{
if (q) {
for (int i = 0; i < args.Length; i++)
{
if ((args[i] & 1) == 1)
{
return true;
}
}
}
return false;
}
}
}

View file

@ -23,6 +23,11 @@ namespace ARMeilleure.Decoders
Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
if (this.GetType() == typeof(OpCode32Simd)) // subclasses have their own handling of Vx to account for before checking!
{
DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm);
}
}
}
}

View file

@ -12,6 +12,10 @@ namespace ARMeilleure.Decoders
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Size = 3;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -9,6 +9,11 @@ namespace ARMeilleure.Decoders
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Size = (opCode >> 18) & 0x3; //fvector size: 1 for 16 bit
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -4,10 +4,8 @@ using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdDupElem : BaseOpCode32Simd
class OpCode32SimdDupElem : OpCode32Simd
{
public bool Q { get; private set; }
public int Index { get; private set; }
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
@ -31,13 +29,18 @@ namespace ARMeilleure.Decoders
}
else
{
throw new Exception("Undefined");
Instruction = InstDescriptor.Undefined;
}
Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
Q = (opCode & (1 << 6)) != 0;
if (Q) RegisterSize = RegisterSize.Simd128;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -4,23 +4,31 @@ using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdVdupGP : OpCode32, IOpCode32Simd
class OpCode32SimdDupGP : 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)
public OpCode32SimdDupGP(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.
if (Size == -1)
{
Instruction = InstDescriptor.Undefined;
}
Q = ((opCode >> 21) & 0x1) != 0;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
Rt = ((opCode >> 12) & 0xf);
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdExt : OpCode32SimdReg
{
public int Immediate { get; private set; }
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = (opCode >> 8) & 0xf;
Size = 0;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn) || (!Q && Immediate > 7))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -33,6 +33,11 @@ namespace ARMeilleure.Decoders
Size = parsedImm.Item2;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -35,7 +35,12 @@ namespace ARMeilleure.Decoders
}
else
{
throw new Exception("Unknown Encoding");
Instruction = InstDescriptor.Undefined;
}
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
{
Instruction = InstDescriptor.Undefined;
}
}
}

View file

@ -11,7 +11,6 @@ namespace ARMeilleure.Decoders
public int Size { get; private set; }
public bool Add { get; private set; }
public int Immediate { get; private set; }
public int Elems => 1;
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
@ -27,8 +26,6 @@ namespace ARMeilleure.Decoders
var single = Size != 0b11;
//RegisterSize = single ? RegisterSize.Simd32 : RegisterSize.Simd64;
if (single)
{
Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);

View file

@ -9,13 +9,10 @@ namespace ARMeilleure.Decoders
public int Rn { get; private set; }
public int Vd { get; private set; }
public int RegisterRange
{ get; private set; }
public int RegisterRange { get; private set; }
public int Offset { get; private set; }
public int PostOffset { get; private set; }
public bool IsLoad { get; private set; }
public bool DoubleWidth { get; private set; }
public bool Add { get; private set; }
@ -28,6 +25,11 @@ namespace ARMeilleure.Decoders
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
if (p == u && w)
{
Instruction = InstDescriptor.Undefined;
}
DoubleWidth = (opCode & (1 << 8)) != 0;
if (!DoubleWidth)
@ -60,6 +62,13 @@ namespace ARMeilleure.Decoders
}
IsLoad = isLoad;
int regs = DoubleWidth ? RegisterRange / 2 : RegisterRange;
if (RegisterRange == 0 || RegisterRange > 32 || Vd + regs > 32)
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -15,7 +15,6 @@ namespace ARMeilleure.Decoders
public bool RegisterIndex { get; private set; }
public int Size { get; private set; }
public bool Replicate { get; private set; }
public int Elems => GetBytesCount() >> Size;
public int Increment { get; private set; }
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{

View file

@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders
class OpCode32SimdMovGp : OpCode32, IOpCode32Simd
{
public int Size => 2;
public int Elems => 1;
public int Vn { get; private set; }
public int Rt { get; private set; }

View file

@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders
class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd
{
public int Size => 3;
public int Elems => 1;
public int Vm { get; private set; }
public int Rt { get; private set; }

View file

@ -7,7 +7,6 @@ namespace ARMeilleure.Decoders
class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd
{
public int Size { get; private set; }
public int Elems => 1;
public int Vd { get; private set; }
public int Rt { get; private set; }
@ -41,7 +40,7 @@ namespace ARMeilleure.Decoders
}
else
{
throw new Exception("Undefined");
Instruction = InstDescriptor.Undefined;
}
Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);

View file

@ -15,6 +15,12 @@ namespace ARMeilleure.Decoders
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
// subclasses have their own handling of Vx to account for before checking!
if (this.GetType() == typeof(OpCode32SimdReg) && DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -14,9 +14,12 @@ namespace ARMeilleure.Decoders
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
if (Size == 0b11) throw new Exception("Unknown Encoding!");
Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vn) || (Size == 0 || (Size == 1 && F)))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -10,8 +10,6 @@ namespace ARMeilleure.Decoders
public int Vm { get; private set; }
public int Opc { get; protected set; }
public int Size { get; protected set; }
public bool Q { get; private set; }
public int Elems => 1;
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{

View file

@ -10,6 +10,11 @@ namespace ARMeilleure.Decoders
{
Size = (opCode >> 18) & 0x1; //fvector size: 1 for 16 bit
F = ((opCode >> 8) & 0x1) != 0;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -7,6 +7,7 @@ namespace ARMeilleure.Decoders
class OpCode32SimdTbl : OpCode32SimdReg
{
public int Length { get; private set; }
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Length = (opCode >> 8) & 3;
@ -14,6 +15,11 @@ namespace ARMeilleure.Decoders
Opc = Q ? 1 : 0;
Q = false;
RegisterSize = RegisterSize.Simd64;
if (Vn + Length + 1 > 32)
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View file

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{
class OpCode32SimdVext : OpCode32SimdReg
{
public int Immediate { get; private set; }
public OpCode32SimdVext(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = (opCode >> 8) & 0xf;
Size = 0;
}
}
}

View file

@ -6,13 +6,14 @@ namespace ARMeilleure.Decoders
{
class OpCode32System : OpCode32
{
public int Opc1 { get; internal set; }
public int CRn { get; internal set; }
public int Rt { get; internal set; }
public int Opc2 { get; internal set; }
public int CRm { get; internal set; }
public int Opc1 { get; private set; }
public int CRn { get; private set; }
public int Rt { get; private set; }
public int Opc2 { get; private set; }
public int CRm { get; private set; }
public int MrrcOp { get; private set; }
public int Coproc { get; internal set; }
public int Coproc { get; private set; }
public OpCode32System(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
@ -21,6 +22,7 @@ namespace ARMeilleure.Decoders
Rt = (opCode >> 12) & 0xf;
Opc2 = (opCode >> 5) & 0x7;
CRm = (opCode >> 0) & 0xf;
MrrcOp = (opCode >> 4) & 0xf;
Coproc = (opCode >> 8) & 0xf;
}

View file

@ -781,10 +781,10 @@ namespace ARMeilleure.Decoders
SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // the many fp32 to int encodings (fp)
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdVdupGP));
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP));
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, typeof(OpCode32SimdDupElem));
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdVext));
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt));
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle));
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 1
@ -818,7 +818,8 @@ namespace ARMeilleure.Decoders
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg));
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, typeof(OpCode32SimdReg));
SetA32("111111101x00xxxxxxxx10>>xxx0xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_S, typeof(OpCode32SimdRegS));
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.VMMmn, InstEmit32.VmaxNm_S, typeof(OpCode32SimdRegS));
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.VMMmn, InstEmit32.VminNm_S, typeof(OpCode32SimdRegS));
SetA32("111100110xxxxxxxxxxx1111xxx1xxxx", InstName.VMMmn, InstEmit32.VmaxminNm_V, typeof(OpCode32SimdReg));
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS));

View file

@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
public static void Vdup(ArmEmitterContext context)
{
OpCode32SimdVdupGP op = (OpCode32SimdVdupGP)context.CurrOp;
OpCode32SimdDupGP op = (OpCode32SimdDupGP)context.CurrOp;
Operand insert = GetIntA32(context, op.Rt);
@ -112,7 +112,7 @@ namespace ARMeilleure.Instructions
}
public static void Vext(ArmEmitterContext context)
{
OpCode32SimdVext op = (OpCode32SimdVext)context.CurrOp;
OpCode32SimdExt op = (OpCode32SimdExt)context.CurrOp;
int elems = op.GetBytesCount();
int byteOff = op.Immediate;
@ -217,18 +217,20 @@ namespace ARMeilleure.Instructions
}
}
public static void VmaxminNm_S(ArmEmitterContext context)
public static void VmaxNm_S(ArmEmitterContext context)
{
bool max = (context.CurrOp.RawOpCode & (1 << 6)) == 0;
_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) => EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2));
}
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, f32, f64, op1, op2));
public static void VminNm_S(ArmEmitterContext context)
{
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2));
}
public static void VmaxminNm_V(ArmEmitterContext context)
{
bool max = (context.CurrOp.RawOpCode & (1 << 21)) == 0;
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
bool max = (op.Size & 2) == 0; // op is high bit of size (not used for fp)
_F32_F32_F32_Bool f32 = max ? new _F32_F32_F32_Bool(SoftFloat32.FPMaxNumFpscr) : new _F32_F32_F32_Bool(SoftFloat32.FPMinNumFpscr);
_F64_F64_F64_Bool f64 = max ? new _F64_F64_F64_Bool(SoftFloat64.FPMaxNumFpscr) : new _F64_F64_F64_Bool(SoftFloat64.FPMinNumFpscr);
@ -309,7 +311,7 @@ namespace ARMeilleure.Instructions
public static void Vmul_I(ArmEmitterContext context)
{
if (((context.CurrOp.RawOpCode >> 24) & 1) != 0) throw new Exception("Polynomial mode not supported");
if ((context.CurrOp as OpCode32SimdReg).U) throw new NotImplementedException("Polynomial mode not implemented");
EmitVectorBinaryOpSx32(context, (op1, op2) => context.Multiply(op1, op2));
}

View file

@ -202,7 +202,7 @@ namespace ARMeilleure.Instructions
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
bool cmpWithZero = (op.RawOpCode & (1 << 16)) != 0;
bool cmpWithZero = (op.Opc & 2) != 0;
{
int fSize = op.Size & 1;
OperandType type = fSize != 0 ? OperandType.FP64 : OperandType.FP32;

View file

@ -56,11 +56,11 @@ namespace ARMeilleure.Instructions
case 0b0001: //FPSCR
dlg = new _Void_U32(NativeInterface.SetFpscr); break;
case 0b0101: //MVFR2
throw new Exception("MVFR2");
throw new NotImplementedException("MVFR2");
case 0b0110: //MVFR1
throw new Exception("MVFR1");
throw new NotImplementedException("MVFR1");
case 0b0111: //MVFR0
throw new Exception("MVFR0");
throw new NotImplementedException("MVFR0");
case 0b1000: //FPEXC
throw new NotImplementedException("Supervisor Only");
default: throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
@ -154,7 +154,6 @@ namespace ARMeilleure.Instructions
switch (op.Opc2)
{
case 5: // Data Memory Barrier Register
return; // SUPER TODO: DO NOT KNOW HOW TO IMPLEMENT THIS
default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
}
@ -197,7 +196,7 @@ namespace ARMeilleure.Instructions
throw new NotImplementedException($"Unknown MRC Coprocessor ID 0x{op.Coproc:X16} at 0x{op.Address:X16}.");
}
var opc = (op.RawOpCode >> 4) & 0xf;
var opc = op.MrrcOp;
Delegate dlg;
switch (op.CRm)