Address Feedback
This commit is contained in:
parent
475327db74
commit
6476b3d24f
82 changed files with 591 additions and 806 deletions
|
@ -292,7 +292,6 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static bool IsCall(OpCode opCode)
|
||||
{
|
||||
// TODO (CQ): ARM32 support.
|
||||
return opCode.Instruction.Name == InstName.Bl ||
|
||||
opCode.Instruction.Name == InstName.Blr ||
|
||||
opCode.Instruction.Name == InstName.Blx;
|
||||
|
|
|
@ -151,7 +151,8 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static bool VectorArgumentsInvalid(bool q, params int[] args)
|
||||
{
|
||||
if (q) {
|
||||
if (q)
|
||||
{
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if ((args[i] & 1) == 1)
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32AluBf
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32AluReg : IOpCode32Alu
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32AluUx : IOpCode32AluReg
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32MemEx : IOpCode32Mem
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32Simd : IOpCode32, IOpCodeSimd
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
interface IOpCode32SimdImm : IOpCode32Simd
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32AluBf : OpCode32, IOpCode32AluBf
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32AluMla : OpCode32, IOpCode32AluReg
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32AluReg : OpCode32Alu, IOpCode32AluReg
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32AluRsReg : OpCode32Alu
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32AluUmull : OpCode32
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ARMeilleure.State;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
|
@ -8,7 +6,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
public int Rotate { get; private set; }
|
||||
public int RotateBits => Rotate * 8;
|
||||
public bool Add => Rn != 15;
|
||||
public bool Add => Rn != RegisterAlias.Aarch32Pc;
|
||||
|
||||
public OpCode32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32Exception : OpCode32
|
||||
{
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32MemLdEx : OpCode32Mem, IOpCode32MemEx
|
||||
{
|
||||
public int Rd { get; internal set; }
|
||||
public int Rd { get; private set; }
|
||||
public OpCode32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Rd = opCode & 0xf;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32MemReg : OpCode32Mem
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32MemRsImm : OpCode32Mem
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32MemStEx : OpCode32Mem, IOpCode32MemEx
|
||||
{
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32Simd : BaseOpCode32Simd
|
||||
class OpCode32Simd : OpCode32SimdBase
|
||||
{
|
||||
public int Opc { get; protected set; }
|
||||
public bool Q { get; protected set; }
|
||||
|
@ -13,7 +9,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Size = (opCode >> 20) & 0x3; //fvector size: 1 for 16 bit
|
||||
Size = (opCode >> 20) & 0x3;
|
||||
Q = ((opCode >> 6) & 0x1) != 0;
|
||||
F = ((opCode >> 10) & 0x1) != 0;
|
||||
U = ((opCode >> 24) & 0x1) != 0;
|
||||
|
@ -24,7 +20,7 @@ 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!
|
||||
if (this.GetType() == typeof(OpCode32Simd)) // Subclasses have their own handling of Vx to account for before checking.
|
||||
{
|
||||
DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
abstract class BaseOpCode32Simd : OpCode32, IOpCode32Simd
|
||||
abstract class OpCode32SimdBase : OpCode32, IOpCode32Simd
|
||||
{
|
||||
public int Vd { get; protected set; }
|
||||
public int Vm { get; protected set; }
|
||||
|
@ -29,7 +27,6 @@ namespace ARMeilleure.Decoders
|
|||
switch (RegisterSize)
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return index >> 1;
|
||||
case RegisterSize.Simd64:
|
||||
return index >> 1;
|
||||
}
|
||||
|
@ -50,7 +47,7 @@ namespace ARMeilleure.Decoders
|
|||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public BaseOpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
public OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
/// <summary>
|
||||
/// A special alias that always runs in 64 bit int, to speed up binary ops a little.
|
||||
|
@ -12,6 +8,7 @@ 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;
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdCmpZ : OpCode32Simd
|
||||
{
|
||||
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Size = (opCode >> 18) & 0x3; //fvector size: 1 for 16 bit
|
||||
Size = (opCode >> 18) & 0x3;
|
||||
|
||||
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
|
||||
{
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdCvtFI : OpCode32SimdS
|
||||
{
|
||||
public int Opc2 { get; private set; }
|
||||
|
||||
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Opc2 = (opCode >> 16) & 0x7;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdDupElem : OpCode32Simd
|
||||
{
|
||||
|
@ -34,8 +30,6 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
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))
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdDupGP : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
@ -13,7 +9,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
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.
|
||||
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
|
||||
if (Size == -1)
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
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;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdImm : OpCode32, IOpCode32SimdImm
|
||||
{
|
||||
|
@ -11,6 +7,7 @@ namespace ARMeilleure.Decoders
|
|||
public long Immediate { get; private set; }
|
||||
public int Size { get; private set; }
|
||||
public int Elems => GetBytesCount() >> Size;
|
||||
|
||||
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Vd = (opCode >> 12) & 0xf;
|
||||
|
@ -27,10 +24,7 @@ namespace ARMeilleure.Decoders
|
|||
imm |= ((uint)opCode >> 12) & 0x70;
|
||||
imm |= ((uint)opCode >> 17) & 0x80;
|
||||
|
||||
Tuple<long, int> parsedImm = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm, fpBaseSize: 2);
|
||||
|
||||
Immediate = parsedImm.Item1;
|
||||
Size = parsedImm.Item2;
|
||||
(Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm, fpBaseSize: 2);
|
||||
|
||||
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdImm44 : OpCode32, IOpCode32SimdImm
|
||||
{
|
||||
|
@ -10,6 +6,7 @@ namespace ARMeilleure.Decoders
|
|||
public long Immediate { get; private set; }
|
||||
public int Size { get; private set; }
|
||||
public int Elems { get; private set; }
|
||||
|
||||
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Size = (opCode >> 8) & 0x3;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdShift : OpCode32Simd
|
||||
{
|
||||
public int Immediate { get; private set; }
|
||||
public int Shift { get; private set; }
|
||||
|
||||
public OpCode32SimdShift(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Immediate = (opCode >> 16) & 0x3f;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMemImm : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMemMult : OpCode32
|
||||
{
|
||||
|
@ -45,7 +41,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
RegisterRange = opCode & 0xff;
|
||||
|
||||
int regsSize = RegisterRange * 4; // double mode is still measured in single register size
|
||||
int regsSize = RegisterRange * 4; // Double mode is still measured in single register size.
|
||||
|
||||
if (!u)
|
||||
{
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
||||
{
|
||||
private static Dictionary<int, int> RegsMap = new Dictionary<int, int>()
|
||||
private static int[] RegsMap =
|
||||
{
|
||||
{ 0b0111, 1 },
|
||||
{ 0b1010, 2 },
|
||||
{ 0b0110, 3 },
|
||||
{ 0b0010, 4 },
|
||||
|
||||
{ 0b1000, 1 },
|
||||
{ 0b1001, 1 },
|
||||
{ 0b0011, 2 },
|
||||
1, 1, 4, 2,
|
||||
1, 1, 3, 1,
|
||||
1, 1, 2, 1,
|
||||
1, 1, 1, 1
|
||||
};
|
||||
|
||||
public int Vd { get; private set; }
|
||||
public int Rn { get; private set; }
|
||||
public int Rm { get; private set; }
|
||||
|
@ -27,6 +22,7 @@ namespace ARMeilleure.Decoders
|
|||
public int Elems => 8 >> Size;
|
||||
public int Regs { get; private set; }
|
||||
public int Increment { get; private set; }
|
||||
|
||||
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Vd = (opCode >> 12) & 0xf;
|
||||
|
@ -41,12 +37,7 @@ namespace ARMeilleure.Decoders
|
|||
WBack = Rm != 15;
|
||||
RegisterIndex = (Rm != 15 && Rm != 13);
|
||||
|
||||
int regs;
|
||||
if (!RegsMap.TryGetValue((opCode >> 8) & 0xf, out regs))
|
||||
{
|
||||
regs = 1;
|
||||
}
|
||||
Regs = regs;
|
||||
Regs = RegsMap[(opCode >> 8) & 0xf];
|
||||
|
||||
Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ARMeilleure.State;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
|
@ -16,6 +14,7 @@ namespace ARMeilleure.Decoders
|
|||
public int Size { get; private set; }
|
||||
public bool Replicate { get; private set; }
|
||||
public int Increment { get; private set; }
|
||||
|
||||
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Vd = (opCode >> 12) & 0xf;
|
||||
|
@ -40,8 +39,8 @@ namespace ARMeilleure.Decoders
|
|||
Rm = (opCode >> 0) & 0xf;
|
||||
Rn = (opCode >> 16) & 0xf;
|
||||
|
||||
WBack = Rm != 15;
|
||||
RegisterIndex = (Rm != 15 && Rm != 13);
|
||||
WBack = Rm != RegisterAlias.Aarch32Pc;
|
||||
RegisterIndex = (Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMovGp : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
@ -14,9 +10,10 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public int Opc1 { get; private set; }
|
||||
public int Opc2 { get; private set; }
|
||||
|
||||
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
// which one is used is instruction dependant
|
||||
// Which one is used is instruction dependant.
|
||||
Op = ((opCode >> 20) & 0x1);
|
||||
|
||||
Opc1 = ((opCode >> 21) & 0x3);
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
@ -12,9 +8,10 @@ namespace ARMeilleure.Decoders
|
|||
public int Rt { get; private set; }
|
||||
public int Rt2 { get; private set; }
|
||||
public int Op { get; private set; }
|
||||
|
||||
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
// which one is used is instruction dependant
|
||||
// Which one is used is instruction dependant.
|
||||
Op = ((opCode >> 20) & 0x1);
|
||||
|
||||
Rt = (opCode >> 12) & 0xf;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
@ -15,7 +11,6 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public int Index { get; private set; }
|
||||
|
||||
|
||||
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Op = ((opCode >> 20) & 0x1);
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdReg : OpCode32Simd
|
||||
{
|
||||
|
@ -16,7 +12,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
|
||||
|
||||
// subclasses have their own handling of Vx to account for before checking!
|
||||
// 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;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdRegElem : OpCode32SimdReg
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdRegS : OpCode32SimdS
|
||||
{
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdRev : OpCode32SimdCmpZ
|
||||
{
|
||||
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
// Currently, this instruction is treated as though it's OPCODE is the true size.
|
||||
// which lets us deal with reversing vectors on a single element basis (eg. math magic an I64 rather than insert lots of I8s)
|
||||
// Currently, this instruction is treated as though it's OPCODE is the true size,
|
||||
// which lets us deal with reversing vectors on a single element basis (eg. math magic an I64 rather than insert lots of I8s).
|
||||
int tempSize = Size;
|
||||
Size = 3 - Opc; //op 0 is 64 bit, 1 is 32 and so on.
|
||||
Size = 3 - Opc; // Op 0 is 64 bit, 1 is 32 and so on.
|
||||
Opc = tempSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdS : OpCode32, IOpCode32Simd
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdSel : OpCode32SimdRegS
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdSpecial : OpCode32
|
||||
{
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdSqrte : OpCode32Simd
|
||||
{
|
||||
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
{
|
||||
Size = (opCode >> 18) & 0x1; //fvector size: 1 for 16 bit
|
||||
Size = (opCode >> 18) & 0x1;
|
||||
F = ((opCode >> 8) & 0x1) != 0;
|
||||
|
||||
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdTbl : OpCode32SimdReg
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32System : OpCode32
|
||||
{
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Decoders
|
||||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
public static class OpCodeSimdHelper
|
||||
{
|
||||
public static Tuple<long, int> GetSimdImmediateAndSize(int cMode, int op, long imm, int fpBaseSize = 0)
|
||||
public static (long Immediate, int Size) GetSimdImmediateAndSize(int cMode, int op, long imm, int fpBaseSize = 0)
|
||||
{
|
||||
int modeLow = cMode & 1;
|
||||
int modeHigh = cMode >> 1;
|
||||
|
@ -74,7 +70,7 @@ namespace ARMeilleure.Decoders
|
|||
size = 0;
|
||||
}
|
||||
|
||||
return new Tuple<long, int>(imm, size);
|
||||
return (imm, size);
|
||||
}
|
||||
|
||||
public static long VFPExpandImm(long imm, int n)
|
||||
|
|
|
@ -599,147 +599,147 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
#region "OpCode Table (AArch32)"
|
||||
// Base
|
||||
SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxx0xx1xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000100xxxxxxxxxxxxx0xx1xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010000xxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000000xxxxxxxxxxxxxxxx0xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000000xxxxxxxxxxxxx0xx1xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstName.B, InstEmit32.B, typeof(OpCode32BImm));
|
||||
SetA32("<<<<0111110xxxxxxxxxxxxxx0011111", InstName.Bfc, InstEmit32.Bfc, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<0111110xxxxxxxxxxxxxx001xxxx", InstName.Bfi, InstEmit32.Bfi, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<0011110xxxxxxxxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001110xxxxxxxxxxxxxxxx0xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001110xxxxxxxxxxxxx0xx1xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, typeof(OpCode32BImm));
|
||||
SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, typeof(OpCode32BImm));
|
||||
SetA32("<<<<000100101111111111110011xxxx", InstName.Blx, InstEmit32.Blxr, typeof(OpCode32BReg));
|
||||
SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, typeof(OpCode32BReg));
|
||||
SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, typeof(OpCodeT16BReg));
|
||||
SetA32("11110101011111111111000000011111", InstName.Clrex, InstEmit32.Clrex, typeof(OpCode32));
|
||||
SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, typeof(OpCode32AluReg));
|
||||
SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsReg));
|
||||
SetA32("1111010101111111111100000101xxxx", InstName.Dmb, InstEmit32.Dmb, typeof(OpCode32));
|
||||
SetA32("1111010101111111111100000100xxxx", InstName.Dsb, InstEmit32.Dsb, typeof(OpCode32));
|
||||
SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsReg));
|
||||
SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, typeof(OpCode32));
|
||||
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011001xxxxxxxx111010011111", InstName.Ldaex, InstEmit32.Ldaex, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx111010011111", InstName.Ldaexb,InstEmit32.Ldaexb,typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011011xxxxxxxx111010011111", InstName.Ldaexd,InstEmit32.Ldaexd,typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx111010011111", InstName.Ldaexh,InstEmit32.Ldaexh,typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx110010011111", InstName.Ldah, InstEmit32.Ldah, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult));
|
||||
SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx0x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<010xx1x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx1x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<00011001xxxxxxxx111110011111", InstName.Ldrex, InstEmit32.Ldrex, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx111110011111", InstName.Ldrexb,InstEmit32.Ldrexb,typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011011xxxxxxxx111110011111", InstName.Ldrexd,InstEmit32.Ldrexd,typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx111110011111", InstName.Ldrexh,InstEmit32.Ldrexh,typeof(OpCode32MemLdEx));
|
||||
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));
|
||||
SetA32("<<<<0011101x0000xxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001101x0000xxxxxxxx0xx1xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<00110000xxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm16));
|
||||
SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCodeT16AluImm8));
|
||||
SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, typeof(OpCode32AluImm16));
|
||||
SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, typeof(OpCode32System));
|
||||
SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, typeof(OpCode32System));
|
||||
SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001111x0000xxxxxxxxxxx0xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001111x0000xxxxxxxx0xx1xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsReg));
|
||||
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, but nop
|
||||
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));
|
||||
SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
|
||||
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("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smulh, InstEmit32.Smulh, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxx1001xxxx", InstName.Smull, InstEmit32.Smull, typeof(OpCode32AluUmull));
|
||||
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxxxxxx11101001xxxx", InstName.Stlexb,InstEmit32.Stlexb,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011010xxxxxxxx11101001xxxx", InstName.Stlexd,InstEmit32.Stlexd,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxxxxxx11101001xxxx", InstName.Stlexh,InstEmit32.Stlexh,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxx111111001001xxxx", InstName.Stlh, InstEmit32.Stlh, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult));
|
||||
SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx0x0xxxxxxxxxxxxxxx0xxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<010xx1x0xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx1x0xxxxxxxxxxxxxxx0xxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<00011000xxxxxxxx11111001xxxx", InstName.Strex, InstEmit32.Strex, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxxxxxx11111001xxxx", InstName.Strexb,InstEmit32.Strexb,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011010xxxxxxxx11111001xxxx", InstName.Strexd,InstEmit32.Strexd,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxxxxxx11111001xxxx", InstName.Strexh,InstEmit32.Strexh,typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000010xxxxxxxxxxxxxxxx0xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsImm));
|
||||
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));
|
||||
SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, typeof(OpCode32Exception));
|
||||
SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
|
||||
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));
|
||||
SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxx0xx1xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000100xxxxxxxxxxxxx0xx1xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010000xxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000000xxxxxxxxxxxxxxxx0xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000000xxxxxxxxxxxxx0xx1xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstName.B, InstEmit32.B, typeof(OpCode32BImm));
|
||||
SetA32("<<<<0111110xxxxxxxxxxxxxx0011111", InstName.Bfc, InstEmit32.Bfc, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<0111110xxxxxxxxxxxxxx001xxxx", InstName.Bfi, InstEmit32.Bfi, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<0011110xxxxxxxxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001110xxxxxxxxxxxxxxxx0xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001110xxxxxxxxxxxxx0xx1xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, typeof(OpCode32BImm));
|
||||
SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, typeof(OpCode32BImm));
|
||||
SetA32("<<<<000100101111111111110011xxxx", InstName.Blx, InstEmit32.Blxr, typeof(OpCode32BReg));
|
||||
SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, typeof(OpCode32BReg));
|
||||
SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, typeof(OpCodeT16BReg));
|
||||
SetA32("11110101011111111111000000011111", InstName.Clrex, InstEmit32.Clrex, typeof(OpCode32));
|
||||
SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, typeof(OpCode32AluReg));
|
||||
SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsReg));
|
||||
SetA32("1111010101111111111100000101xxxx", InstName.Dmb, InstEmit32.Dmb, typeof(OpCode32));
|
||||
SetA32("1111010101111111111100000100xxxx", InstName.Dsb, InstEmit32.Dsb, typeof(OpCode32));
|
||||
SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsReg));
|
||||
SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, typeof(OpCode32));
|
||||
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011001xxxxxxxx111010011111", InstName.Ldaex, InstEmit32.Ldaex, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx111010011111", InstName.Ldaexb, InstEmit32.Ldaexb, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011011xxxxxxxx111010011111", InstName.Ldaexd, InstEmit32.Ldaexd, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx111010011111", InstName.Ldaexh, InstEmit32.Ldaexh, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx110010011111", InstName.Ldah, InstEmit32.Ldah, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult));
|
||||
SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx0x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<010xx1x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx1x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<00011001xxxxxxxx111110011111", InstName.Ldrex, InstEmit32.Ldrex, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011101xxxxxxxx111110011111", InstName.Ldrexb, InstEmit32.Ldrexb, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011011xxxxxxxx111110011111", InstName.Ldrexd, InstEmit32.Ldrexd, typeof(OpCode32MemLdEx));
|
||||
SetA32("<<<<00011111xxxxxxxx111110011111", InstName.Ldrexh, InstEmit32.Ldrexh, typeof(OpCode32MemLdEx));
|
||||
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));
|
||||
SetA32("<<<<0011101x0000xxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001101x0000xxxxxxxx0xx1xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<00110000xxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm16));
|
||||
SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCodeT16AluImm8));
|
||||
SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, typeof(OpCode32AluImm16));
|
||||
SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, typeof(OpCode32System));
|
||||
SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, typeof(OpCode32System));
|
||||
SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0001111x0000xxxxxxxxxxx0xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0001111x0000xxxxxxxx0xx1xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsReg));
|
||||
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));
|
||||
SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32));
|
||||
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));
|
||||
SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
|
||||
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("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smulh, InstEmit32.Smulh, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0000110xxxxxxxxxxxxx1001xxxx", InstName.Smull, InstEmit32.Smull, typeof(OpCode32AluUmull));
|
||||
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxxxxxx11101001xxxx", InstName.Stlexb, InstEmit32.Stlexb, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011010xxxxxxxx11101001xxxx", InstName.Stlexd, InstEmit32.Stlexd, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxxxxxx11101001xxxx", InstName.Stlexh, InstEmit32.Stlexh, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxx111111001001xxxx", InstName.Stlh, InstEmit32.Stlh, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult));
|
||||
SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx0x0xxxxxxxxxxxxxxx0xxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<010xx1x0xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemImm));
|
||||
SetA32("<<<<011xx1x0xxxxxxxxxxxxxxx0xxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemRsImm));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<00011000xxxxxxxx11111001xxxx", InstName.Strex, InstEmit32.Strex, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011100xxxxxxxx11111001xxxx", InstName.Strexb, InstEmit32.Strexb, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011010xxxxxxxx11111001xxxx", InstName.Strexd, InstEmit32.Strexd, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<00011110xxxxxxxx11111001xxxx", InstName.Strexh, InstEmit32.Strexh, typeof(OpCode32MemStEx));
|
||||
SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8));
|
||||
SetA32("<<<<000xx0x0xxxxxxxx00001011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemReg));
|
||||
SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<0000010xxxxxxxxxxxxxxxx0xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsImm));
|
||||
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));
|
||||
SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, typeof(OpCode32Exception));
|
||||
SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluImm));
|
||||
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsImm));
|
||||
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsReg));
|
||||
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
|
||||
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
|
||||
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)
|
||||
|
||||
|
@ -757,15 +757,15 @@ namespace ARMeilleure.Decoders
|
|||
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary));
|
||||
|
||||
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ));
|
||||
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
|
||||
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg));
|
||||
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg));
|
||||
|
||||
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ));
|
||||
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
|
||||
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg));
|
||||
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg));
|
||||
|
||||
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ));
|
||||
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg)); //note: size is 16/32 only
|
||||
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg));
|
||||
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg));
|
||||
|
||||
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("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS));
|
||||
SetA32("111100111x11xx11xxxx011xxxx0xxxx", 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("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // fp32 to int
|
||||
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("111100111x11xx11xxxx011xxxx0xxxx", 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("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // FP32 to int.
|
||||
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("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
|
||||
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP));
|
||||
|
@ -787,20 +787,20 @@ namespace ARMeilleure.Decoders
|
|||
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
|
||||
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 2
|
||||
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 3
|
||||
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 4
|
||||
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 1.
|
||||
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 2.
|
||||
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 3.
|
||||
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 4.
|
||||
|
||||
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); //regs = 1, inc = 1/2 (itype)
|
||||
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); //regs = 2, inc = 2
|
||||
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); // Regs = 1, inc = 1/2 (itype).
|
||||
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
|
||||
|
||||
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemPair)); //inc = 1/2 (itype)
|
||||
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
|
||||
|
||||
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, typeof(OpCode32SimdMemPair)); //inc = 1/2 (itype)
|
||||
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
|
||||
|
||||
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
|
||||
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
|
||||
|
@ -832,18 +832,18 @@ namespace ARMeilleure.Decoders
|
|||
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, typeof(OpCode32SimdReg));
|
||||
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, typeof(OpCode32SimdRegElem));
|
||||
|
||||
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); //d/q vector i32
|
||||
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm44)); //scalar f16/32/64 based on size 01 10 11
|
||||
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); //d/q i16
|
||||
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); //d/q (dt - from cmode)
|
||||
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); //d/q i64
|
||||
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q vector I32.
|
||||
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm44)); // Scalar f16/32/64 based on size 01 10 11.
|
||||
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q I16.
|
||||
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q (dt - from cmode).
|
||||
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q I64.
|
||||
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, typeof(OpCode32SimdS));
|
||||
|
||||
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, typeof(OpCode32SimdMovGpDouble)); //to/from gen purpose x2 and double precision
|
||||
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); //from gen purpose
|
||||
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, typeof(OpCode32SimdMovGp)); //to/from gen purpose and single precision
|
||||
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); //to gen purpose
|
||||
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, typeof(OpCode32SimdMovGpDouble)); //to/from gen purpose x2 and single precision x2
|
||||
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, typeof(OpCode32SimdMovGpDouble)); // To/from gen purpose x2 and double precision.
|
||||
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); // From gen purpose.
|
||||
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, typeof(OpCode32SimdMovGp)); // To/from gen purpose and single precision.
|
||||
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); // To gen purpose.
|
||||
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, typeof(OpCode32SimdMovGpDouble)); // To/from gen purpose x2 and single precision x2.
|
||||
|
||||
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, typeof(OpCode32SimdSpecial));
|
||||
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, typeof(OpCode32SimdSpecial));
|
||||
|
@ -853,7 +853,7 @@ namespace ARMeilleure.Decoders
|
|||
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("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
|
||||
|
||||
|
@ -879,20 +879,20 @@ namespace ARMeilleure.Decoders
|
|||
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShift));
|
||||
|
||||
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 1
|
||||
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 2
|
||||
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 3
|
||||
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 4
|
||||
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 1.
|
||||
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 2.
|
||||
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 3.
|
||||
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 4.
|
||||
|
||||
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); //regs = 1, inc = 1/2 (itype)
|
||||
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); //regs = 2, inc = 2
|
||||
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); // Regs = 1, inc = 1/2 (itype).
|
||||
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
|
||||
|
||||
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemPair)); //inc = 1/2 (itype)
|
||||
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
|
||||
|
||||
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, typeof(OpCode32SimdMemSingle));
|
||||
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, typeof(OpCode32SimdMemPair)); //inc = 1/2 (itype)
|
||||
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
|
||||
|
||||
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
|
||||
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
|
||||
|
|
|
@ -276,23 +276,6 @@ namespace ARMeilleure.Instructions
|
|||
SetAluDOrZR(context, d);
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBits32Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32);
|
||||
|
||||
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaau)), Const(1)),
|
||||
context.ShiftLeft (context.BitwiseAnd(op, Const(0x55555555u)), Const(1)));
|
||||
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccu)), Const(2)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x33333333u)), Const(2)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0u)), Const(4)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0f0f0f0fu)), Const(4)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00u)), Const(8)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x00ff00ffu)), Const(8)));
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(val, Const(16)), context.ShiftLeft(val, Const(16)));
|
||||
}
|
||||
|
||||
private static Operand EmitReverseBits64Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
@ -331,23 +314,6 @@ namespace ARMeilleure.Instructions
|
|||
SetAluDOrZR(context, d);
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBytes16_32Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32);
|
||||
|
||||
Operand val = EmitReverseBytes16_64Op(context, context.ZeroExtend32(OperandType.I64, op));
|
||||
|
||||
return context.ConvertI64ToI32(val);
|
||||
}
|
||||
|
||||
private static Operand EmitReverseBytes16_64Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xff00ff00ff00ff00ul)), Const(8)),
|
||||
context.ShiftLeft (context.BitwiseAnd(op, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
}
|
||||
|
||||
public static void Rev32(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
@ -367,7 +333,7 @@ namespace ARMeilleure.Instructions
|
|||
SetAluDOrZR(context, d);
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBytes32_64Op(ArmEmitterContext context, Operand op)
|
||||
private static Operand EmitReverseBytes32_64Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitAddsCCheck(context, n, res);
|
||||
EmitAddsVCheck(context, n, m, res);
|
||||
}
|
||||
|
||||
public static void Eor(ArmEmitterContext context)
|
||||
{
|
||||
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||||
|
@ -365,8 +366,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
res = context.BitwiseOr(
|
||||
context.ZeroExtend16(OperandType.I32, low16),
|
||||
context.ShiftLeft(context.ZeroExtend16(OperandType.I32, high16), Const(16))
|
||||
);
|
||||
context.ShiftLeft(context.ZeroExtend16(OperandType.I32, high16), Const(16)));
|
||||
|
||||
EmitAluStore(context, res);
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ namespace ARMeilleure.Instructions
|
|||
if (!unsigned)
|
||||
{
|
||||
// If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow).
|
||||
// assume this is the same as ARM64 for now - tests to follow.
|
||||
// Assume this is the same as ARM64 for now - tests to follow.
|
||||
|
||||
Operand intMin = Const(int.MinValue);
|
||||
Operand minus1 = Const(-1);
|
||||
|
@ -466,7 +466,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
|
||||
|
||||
Operand d = GetIntA32(context, op.Rd);
|
||||
Operand imm = Const(op.Immediate << 16); //immeditate value as top halfword
|
||||
Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
|
||||
Operand res = context.BitwiseAnd(d, Const(0x0000ffff));
|
||||
res = context.BitwiseOr(res, imm);
|
||||
|
||||
|
@ -512,7 +512,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetAluN(context);
|
||||
Operand m = GetAluM(context);
|
||||
|
||||
Operand res = InstEmit.EmitReverseBits32Op(context, m);
|
||||
Operand res;
|
||||
|
||||
bool tbform = op.ShiftType == ShiftType.Asr;
|
||||
if (tbform)
|
||||
|
@ -531,7 +531,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand m = GetAluM(context);
|
||||
|
||||
Operand res = InstEmit.EmitReverseBits32Op(context, m);
|
||||
Operand res = EmitReverseBits32Op(context, m);
|
||||
|
||||
EmitAluStore(context, res);
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand m = GetAluM(context);
|
||||
|
||||
Operand res = InstEmit.EmitReverseBytes16_32Op(context, m);
|
||||
Operand res = EmitReverseBytes16_32Op(context, m);
|
||||
|
||||
EmitAluStore(context, res);
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand m = GetAluM(context);
|
||||
|
||||
Operand res = InstEmit.EmitReverseBytes16_32Op(context, m);
|
||||
Operand res = EmitReverseBytes16_32Op(context, m);
|
||||
|
||||
EmitAluStore(context, context.SignExtend16(OperandType.I32, res));
|
||||
}
|
||||
|
@ -591,7 +591,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
||||
|
||||
var msb = op.Lsb + op.Msb; //for this instruction, the msb is actually a width
|
||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||
|
||||
Operand n = GetIntA32(context, op.Rn);
|
||||
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
||||
|
@ -603,7 +603,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
||||
|
||||
var msb = op.Lsb + op.Msb; //for this instruction, the msb is actually a width
|
||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||
|
||||
Operand n = GetIntA32(context, op.Rn);
|
||||
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb));
|
||||
|
@ -614,47 +614,7 @@ namespace ARMeilleure.Instructions
|
|||
private static void EmitAluStore(ArmEmitterContext context, Operand value)
|
||||
{
|
||||
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||||
|
||||
if (op.Rd == RegisterAlias.Aarch32Pc)
|
||||
{
|
||||
if (op.SetFlags)
|
||||
{
|
||||
// TODO: Load SPSR etc.
|
||||
Operand isThumb = GetFlag(PState.TFlag);
|
||||
|
||||
Operand lblThumb = Label();
|
||||
|
||||
context.BranchIfTrue(lblThumb, isThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~3))));
|
||||
|
||||
context.MarkLabel(lblThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitAluWritePc(context, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntA32(context, op.Rd, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitAluWritePc(ArmEmitterContext context, Operand value)
|
||||
{
|
||||
context.StoreToContext();
|
||||
|
||||
if (IsThumb(context.CurrOp))
|
||||
{
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBxWritePc(context, value);
|
||||
}
|
||||
EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using System.Diagnostics;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -77,6 +77,83 @@ namespace ARMeilleure.Instructions
|
|||
SetFlag(context, PState.VFlag, vOut);
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBits32Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32);
|
||||
|
||||
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaau)), Const(1)),
|
||||
context.ShiftLeft(context.BitwiseAnd(op, Const(0x55555555u)), Const(1)));
|
||||
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccu)), Const(2)),
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x33333333u)), Const(2)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0u)), Const(4)),
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0f0f0f0fu)), Const(4)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00u)), Const(8)),
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x00ff00ffu)), Const(8)));
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(val, Const(16)), context.ShiftLeft(val, Const(16)));
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBytes16_64Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xff00ff00ff00ff00ul)), Const(8)),
|
||||
context.ShiftLeft(context.BitwiseAnd(op, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
}
|
||||
|
||||
public static Operand EmitReverseBytes16_32Op(ArmEmitterContext context, Operand op)
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32);
|
||||
|
||||
Operand val = EmitReverseBytes16_64Op(context, context.ZeroExtend32(OperandType.I64, op));
|
||||
|
||||
return context.ConvertI64ToI32(val);
|
||||
}
|
||||
|
||||
private static void EmitAluWritePc(ArmEmitterContext context, Operand value)
|
||||
{
|
||||
context.StoreToContext();
|
||||
|
||||
if (IsThumb(context.CurrOp))
|
||||
{
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitBxWritePc(context, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitGenericAluStoreA32(ArmEmitterContext context, int rd, bool setFlags, Operand value)
|
||||
{
|
||||
if (rd == RegisterAlias.Aarch32Pc && setFlags)
|
||||
{
|
||||
if (setFlags)
|
||||
{
|
||||
// TODO: Load SPSR etc.
|
||||
Operand isThumb = GetFlag(PState.TFlag);
|
||||
|
||||
Operand lblThumb = Label();
|
||||
|
||||
context.BranchIfTrue(lblThumb, isThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~3))));
|
||||
|
||||
context.MarkLabel(lblThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitAluWritePc(context, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntA32(context, rd, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Operand GetAluN(ArmEmitterContext context)
|
||||
{
|
||||
|
@ -256,7 +333,6 @@ namespace ARMeilleure.Instructions
|
|||
public static Operand EmitLslC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero)
|
||||
{
|
||||
Operand shiftLarge = context.ICompareGreaterOrEqual(shift, Const(32));
|
||||
|
||||
Operand result = context.ShiftLeft(m, shift);
|
||||
if (setCarry)
|
||||
{
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand addr = GetIntA32(context, op.Rm);
|
||||
Operand bitOne = context.BitwiseAnd(addr, Const(1));
|
||||
addr = context.BitwiseOr(addr, Const(1)); // set call flag
|
||||
addr = context.BitwiseOr(addr, Const(1)); // Set call flag.
|
||||
|
||||
bool isThumb = IsThumb(context.CurrOp);
|
||||
|
||||
|
@ -88,11 +88,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
SetFlag(context, PState.TFlag, bitOne);
|
||||
|
||||
context.Return(addr); // call
|
||||
}
|
||||
|
||||
public static void Nop(ArmEmitterContext context)
|
||||
{
|
||||
context.Return(addr); // Call.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,10 +21,10 @@ namespace ARMeilleure.Instructions
|
|||
[Flags]
|
||||
enum AccessType
|
||||
{
|
||||
Store = 0,
|
||||
Signed = 1,
|
||||
Load = 2,
|
||||
Ordered = 4,
|
||||
Store = 0,
|
||||
Signed = 1,
|
||||
Load = 2,
|
||||
Ordered = 4,
|
||||
Exclusive = 8,
|
||||
|
||||
LoadZx = Load,
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
|
||||
}
|
||||
|
||||
public static void Lda(ArmEmitterContext context)
|
||||
{
|
||||
EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
|
||||
|
@ -71,7 +72,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
|
||||
}
|
||||
|
||||
// stores
|
||||
// Stores.
|
||||
|
||||
public static void Strex(ArmEmitterContext context)
|
||||
{
|
||||
|
@ -149,7 +150,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (size == DWordSizeLog2)
|
||||
{
|
||||
// keep loads atomic - make the call to get the whole region and then decompose it into parts
|
||||
// Keep loads atomic - make the call to get the whole region and then decompose it into parts
|
||||
// for the registers.
|
||||
|
||||
Operand value = EmitExLoad(context, address, exclusive, size);
|
||||
|
@ -184,15 +185,12 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Operand s = null;
|
||||
|
||||
if (size == DWordSizeLog2)
|
||||
{
|
||||
//split the result into 2 words (based on endianness)
|
||||
// Split the result into 2 words (based on endianness)
|
||||
|
||||
Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
|
||||
Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
|
||||
Operand toStore = Local(OperandType.I64);
|
||||
|
||||
Operand lblBigEndian = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
@ -215,8 +213,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
s = EmitExStore(context, address, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)), exclusive, size);
|
||||
Operand s = EmitExStore(context, address, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)), exclusive, size);
|
||||
// This is only needed for exclusive stores. The function returns 0
|
||||
// when the store is successful, and 1 otherwise.
|
||||
if (exclusive) SetIntA32(context, op.Rd, s);
|
||||
|
|
|
@ -511,7 +511,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (context.CurrOp)
|
||||
{
|
||||
// ARM32.
|
||||
case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
|
||||
case OpCode32MemReg op: return GetIntA32(context, op.Rm);
|
||||
|
|
|
@ -71,8 +71,8 @@ namespace ARMeilleure.Instructions
|
|||
EmitNZFlagsCheck(context, res);
|
||||
}
|
||||
|
||||
EmitGenericStore(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericStore(context, op.RdLo, op.SetFlags, lo);
|
||||
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
|
||||
}
|
||||
|
||||
public static void Smull(ArmEmitterContext context)
|
||||
|
@ -92,8 +92,8 @@ namespace ARMeilleure.Instructions
|
|||
EmitNZFlagsCheck(context, res);
|
||||
}
|
||||
|
||||
EmitGenericStore(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericStore(context, op.RdLo, op.SetFlags, lo);
|
||||
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
|
||||
}
|
||||
|
||||
public static void Smmla(ArmEmitterContext context)
|
||||
|
@ -136,10 +136,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand hi = context.ConvertI64ToI32(context.ShiftRightSI(res, Const(32)));
|
||||
|
||||
EmitGenericStore(context, op.Rd, false, hi);
|
||||
EmitGenericAluStoreA32(context, op.Rd, false, hi);
|
||||
}
|
||||
|
||||
|
||||
public static void Smlab(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
||||
|
@ -170,9 +169,9 @@ namespace ARMeilleure.Instructions
|
|||
Operand a = GetIntA32(context, op.Ra);
|
||||
res = context.Add(res, a);
|
||||
|
||||
//todo: set Q flag when last addition overflows (saturation)?
|
||||
// TODO: set Q flag when last addition overflows (saturation)?
|
||||
|
||||
EmitGenericStore(context, op.Rd, false, res);
|
||||
EmitGenericAluStoreA32(context, op.Rd, false, res);
|
||||
}
|
||||
|
||||
public static void Smlal(ArmEmitterContext context)
|
||||
|
@ -217,8 +216,8 @@ namespace ARMeilleure.Instructions
|
|||
EmitNZFlagsCheck(context, res);
|
||||
}
|
||||
|
||||
EmitGenericStore(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericStore(context, op.RdLo, op.SetFlags, lo);
|
||||
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
|
||||
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
|
||||
}
|
||||
|
||||
public static void Smlalh(ArmEmitterContext context)
|
||||
|
@ -255,8 +254,8 @@ namespace ARMeilleure.Instructions
|
|||
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
|
||||
Operand lo = context.ConvertI64ToI32(res);
|
||||
|
||||
EmitGenericStore(context, op.RdHi, false, hi);
|
||||
EmitGenericStore(context, op.RdLo, false, lo);
|
||||
EmitGenericAluStoreA32(context, op.RdHi, false, hi);
|
||||
EmitGenericAluStoreA32(context, op.RdLo, false, lo);
|
||||
}
|
||||
|
||||
public static void Smulh(ArmEmitterContext context)
|
||||
|
@ -286,37 +285,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand res = context.Multiply(n, m);
|
||||
|
||||
EmitGenericStore(context, op.Rd, false, res);
|
||||
}
|
||||
|
||||
private static void EmitGenericStore(ArmEmitterContext context, int Rd, bool setFlags, Operand value)
|
||||
{
|
||||
if (Rd == RegisterAlias.Aarch32Pc)
|
||||
{
|
||||
if (setFlags)
|
||||
{
|
||||
// TODO: Load SPSR etc.
|
||||
Operand isThumb = GetFlag(PState.TFlag);
|
||||
|
||||
Operand lblThumb = Label();
|
||||
|
||||
context.BranchIfTrue(lblThumb, isThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~3))));
|
||||
|
||||
context.MarkLabel(lblThumb);
|
||||
|
||||
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseAnd(value, Const(~1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitAluWritePc(context, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntA32(context, Rd, value);
|
||||
}
|
||||
EmitGenericAluStoreA32(context, op.Rd, false, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vabs_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1));
|
||||
|
@ -73,7 +74,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand insert = GetIntA32(context, op.Rt);
|
||||
|
||||
// zero extend into an I64, then replicate. Saves the most time over elementwise inserts
|
||||
// Zero extend into an I64, then replicate. Saves the most time over elementwise inserts.
|
||||
switch (op.Size)
|
||||
{
|
||||
case 2:
|
||||
|
@ -86,7 +87,7 @@ namespace ARMeilleure.Instructions
|
|||
insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown Vdup Size!");
|
||||
throw new ArgumentOutOfRangeException("Unknown Vdup Size!");
|
||||
}
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -102,7 +103,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand insert = EmitVectorExtractZx32(context, op.Vm >> 1, ((op.Vm & 1) << (3 - op.Size)) + op.Index, op.Size);
|
||||
|
||||
// zero extend into an I64, then replicate. Saves the most time over elementwise inserts
|
||||
// Zero extend into an I64, then replicate. Saves the most time over elementwise inserts.
|
||||
switch (op.Size)
|
||||
{
|
||||
case 2:
|
||||
|
@ -115,7 +116,7 @@ namespace ARMeilleure.Instructions
|
|||
insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown Vdup Size!");
|
||||
throw new ArgumentOutOfRangeException("Unknown Vdup Size!");
|
||||
}
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -124,6 +125,7 @@ namespace ARMeilleure.Instructions
|
|||
InsertScalar(context, op.Vd | 1, insert);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vext(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdExt op = (OpCode32SimdExt)context.CurrOp;
|
||||
|
@ -244,7 +246,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void VmaxminNm_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
bool max = (op.Size & 2) == 0; // op is high bit of size (not used for fp)
|
||||
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);
|
||||
|
||||
|
@ -332,6 +334,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmul_1(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP)
|
||||
|
@ -390,6 +393,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmla_1(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP)
|
||||
|
@ -448,6 +452,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmls_1(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP)
|
||||
|
@ -479,17 +484,18 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vrev(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
EmitVectorUnaryOpZx32(context, (op1) =>
|
||||
{
|
||||
switch (op.Opc)
|
||||
{
|
||||
case 0:
|
||||
switch (op.Size) //swap bytes
|
||||
switch (op.Size) // Swap bytes.
|
||||
{
|
||||
default:
|
||||
return op1;
|
||||
case 1:
|
||||
return InstEmit.EmitReverseBytes16_32Op(context, op1);
|
||||
return InstEmitAluHelper.EmitReverseBytes16_32Op(context, op1);
|
||||
case 2:
|
||||
case 3:
|
||||
return context.ByteSwap(op1);
|
||||
|
@ -511,7 +517,7 @@ namespace ARMeilleure.Instructions
|
|||
);
|
||||
}
|
||||
case 2:
|
||||
//swap upper and lower
|
||||
// Swap upper and lower halves.
|
||||
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffffffff00000000ul)), Const(32)),
|
||||
context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000fffffffful)), Const(32)));
|
||||
|
||||
|
@ -523,6 +529,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vrecpe(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
|
@ -547,6 +554,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vrsqrte(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
|
@ -569,7 +577,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Vsel(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32SimdSel)context.CurrOp;
|
||||
OpCode32SimdSel op = (OpCode32SimdSel)context.CurrOp;
|
||||
|
||||
Operand condition = null;
|
||||
switch (op.Cc)
|
||||
{
|
||||
|
|
|
@ -22,13 +22,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
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)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareEQFpscr, SoftFloat64.FPCompareEQFpscr, true);
|
||||
|
@ -47,12 +47,14 @@ namespace ARMeilleure.Instructions
|
|||
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)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGEFpscr, SoftFloat64.FPCompareGEFpscr, true);
|
||||
|
@ -71,12 +73,14 @@ namespace ARMeilleure.Instructions
|
|||
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)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGTFpscr, SoftFloat64.FPCompareGTFpscr, true);
|
||||
|
@ -90,6 +94,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vcle_Z(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareLEFpscr, SoftFloat64.FPCompareLEFpscr, true);
|
||||
|
@ -103,6 +108,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vclt_Z(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
if (op.F)
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareLTFpscr, SoftFloat64.FPCompareLTFpscr, true);
|
||||
|
@ -126,8 +132,14 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OperandType type = m.Type;
|
||||
|
||||
if (type == OperandType.FP64) return context.Call(f64, m, new Operand(0.0), one);
|
||||
else return context.Call(f32, m, new Operand(0.0), one);
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(f64, m, new Operand(0.0), one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(f32, m, new Operand(0.0f), one);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -136,8 +148,14 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OperandType type = n.Type;
|
||||
|
||||
if (type == OperandType.FP64) return context.Call(f64, n, m, one);
|
||||
else return context.Call(f32, n, m, one);
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(f64, n, m, one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(f32, n, m, one);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (lowBit)
|
||||
{
|
||||
//move the low bit to the top
|
||||
// Move the low bit to the top.
|
||||
return ((vd & 0x1) << 4) | (vd >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//move the high bit to the bottom
|
||||
// Move the high bit to the bottom.
|
||||
return ((vd & 0xf) << 1) | (vd >> 4);
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,12 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vcvt_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
bool unsigned = (op.Opc & 1) != 0;
|
||||
bool toInteger = (op.Opc & 2) != 0;
|
||||
OperandType floatSize = (op.Size == 2) ? OperandType.FP32 : OperandType.FP64;
|
||||
|
||||
if (op.Size != 2) throw new Exception("CVT vector mode only currently defined for 32-bit");
|
||||
if (op.Size != 2) throw new InvalidOperationException("CVT vector mode only defined for 32-bit.");
|
||||
if (toInteger)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
|
@ -87,7 +88,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size == 3)
|
||||
{
|
||||
vd = FlipVdBits(op.Vd, false);
|
||||
// double to single
|
||||
// Double to single.
|
||||
Operand fp = ExtractScalar(context, OperandType.FP64, vm);
|
||||
|
||||
Operand res = context.ConvertToFP(OperandType.FP32, fp);
|
||||
|
@ -97,7 +98,7 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
vd = FlipVdBits(op.Vd, true);
|
||||
// single to double
|
||||
// Single to double.
|
||||
Operand fp = ExtractScalar(context, OperandType.FP32, vm);
|
||||
|
||||
Operand res = context.ConvertToFP(OperandType.FP64, fp);
|
||||
|
@ -123,10 +124,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand asInteger;
|
||||
|
||||
// TODO: Fast Path
|
||||
// TODO: Fast Path.
|
||||
if (roundWithFpscr)
|
||||
{
|
||||
// these need to get the FPSCR value, so it's worth noting we'd need to do a c# call at some point.
|
||||
// These need to get the FPSCR value, so it's worth noting we'd need to do a c# call at some point.
|
||||
if (floatSize == OperandType.FP64)
|
||||
{
|
||||
if (unsigned)
|
||||
|
@ -154,7 +155,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
// round towards zero
|
||||
// Round towards zero.
|
||||
if (floatSize == OperandType.FP64)
|
||||
{
|
||||
if (unsigned)
|
||||
|
@ -236,16 +237,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.Opc2)
|
||||
{
|
||||
case 0b00: //away
|
||||
case 0b00: // Away
|
||||
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
|
||||
break;
|
||||
case 0b01: //nearest
|
||||
case 0b01: // Nearest
|
||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: //+infinity
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
|
||||
break;
|
||||
case 0b11: //negative
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
|
||||
break;
|
||||
}
|
||||
|
@ -262,7 +263,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
asInteger = context.Call(new _S32_F64(CastDoubleToInt32), toConvert);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -279,7 +279,6 @@ namespace ARMeilleure.Instructions
|
|||
InsertScalar(context, op.Vd, asInteger);
|
||||
}
|
||||
|
||||
|
||||
public static void Vrint_RM(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp;
|
||||
|
@ -290,16 +289,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.Opc2)
|
||||
{
|
||||
case 0b00: //away
|
||||
case 0b00: // Away
|
||||
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
|
||||
break;
|
||||
case 0b01: //nearest
|
||||
case 0b01: // Nearest
|
||||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: //+infinity
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
|
||||
break;
|
||||
case 0b11: //negative
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
|
||||
break;
|
||||
}
|
||||
|
@ -321,10 +320,12 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
return (uint)value;
|
||||
}
|
||||
|
||||
private static int CastFloatToInt32(float value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
private static uint CastFloatToUInt32(float value)
|
||||
{
|
||||
return (uint)value;
|
||||
|
|
|
@ -28,19 +28,19 @@ namespace ARMeilleure.Instructions
|
|||
return (index >> 2, index & 3);
|
||||
}
|
||||
|
||||
throw new NotImplementedException("Unrecognized Vector Register Size!");
|
||||
throw new NotImplementedException("Unrecognized Vector Register Size.");
|
||||
}
|
||||
|
||||
public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg)
|
||||
{
|
||||
if (type == OperandType.FP64 || type == OperandType.I64)
|
||||
{
|
||||
// from dreg
|
||||
// From dreg.
|
||||
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// from sreg
|
||||
// From sreg.
|
||||
return context.VectorExtract(type, GetVecA32(reg >> 2), reg & 3);
|
||||
}
|
||||
}
|
||||
|
@ -50,14 +50,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand vec, insert;
|
||||
if (value.Type == OperandType.FP64 || value.Type == OperandType.I64)
|
||||
{
|
||||
// from dreg
|
||||
// From dreg.
|
||||
vec = GetVecA32(reg >> 1);
|
||||
insert = context.VectorInsert(vec, value, reg & 1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// from sreg
|
||||
// From sreg.
|
||||
vec = GetVecA32(reg >> 2);
|
||||
insert = context.VectorInsert(vec, value, reg & 3);
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
// INTEGER
|
||||
// Integer
|
||||
|
||||
public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed)
|
||||
{
|
||||
|
@ -292,7 +292,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitVectorTernaryOpI32(context, emit, false);
|
||||
}
|
||||
|
||||
// VEC BY SCALAR
|
||||
// Vector by scalar
|
||||
|
||||
public static void EmitVectorByScalarOpF32(ArmEmitterContext context, Func2I emit)
|
||||
{
|
||||
|
@ -323,7 +323,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
|
||||
|
||||
if (op.Size < 1) throw new Exception("Undefined");
|
||||
Operand m = EmitVectorExtract32(context, op.Vm >> (4 - op.Size), op.Vm & ((1 << (4 - op.Size)) - 1), op.Size, signed);
|
||||
|
||||
Operand res = GetVecA32(op.Qd);
|
||||
|
@ -347,7 +346,6 @@ namespace ARMeilleure.Instructions
|
|||
int sizeF = op.Size & 1;
|
||||
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
|
||||
if (op.Size < 2) throw new Exception("FP ops <32 bit unimplemented!");
|
||||
|
||||
int elems = op.GetBytesCount() >> sizeF + 2;
|
||||
|
||||
|
@ -370,7 +368,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
|
||||
|
||||
if (op.Size < 1) throw new Exception("Undefined");
|
||||
Operand m = EmitVectorExtract32(context, op.Vm >> (4 - op.Size), op.Vm & ((1 << (4 - op.Size)) - 1), op.Size, signed);
|
||||
|
||||
Operand res = GetVecA32(op.Qd);
|
||||
|
@ -388,16 +385,12 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
// PAIRWISE
|
||||
// Pairwise
|
||||
|
||||
public static void EmitVectorPairwiseOpF32(ArmEmitterContext context, Func2I emit)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
if (op.Q)
|
||||
{
|
||||
throw new Exception("Q mode not supported for pairwise");
|
||||
}
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
|
||||
|
@ -431,11 +424,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
if (op.Q)
|
||||
{
|
||||
throw new Exception("Q mode not supported for pairwise");
|
||||
}
|
||||
|
||||
int elems = op.GetBytesCount() >> op.Size;
|
||||
int pairs = elems >> 1;
|
||||
|
||||
|
@ -561,6 +549,5 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
|
|
|
@ -16,14 +16,17 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVStoreOrLoadN(context, 1, false);
|
||||
}
|
||||
|
||||
public static void Vst2(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 2, false);
|
||||
}
|
||||
|
||||
public static void Vst3(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 3, false);
|
||||
}
|
||||
|
||||
public static void Vst4(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 4, false);
|
||||
|
@ -33,14 +36,17 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVStoreOrLoadN(context, 1, true);
|
||||
}
|
||||
|
||||
public static void Vld2(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 2, true);
|
||||
}
|
||||
|
||||
public static void Vld3(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 3, true);
|
||||
}
|
||||
|
||||
public static void Vld4(ArmEmitterContext context)
|
||||
{
|
||||
EmitVStoreOrLoadN(context, 4, true);
|
||||
|
@ -52,18 +58,17 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32SimdMemSingle op = (OpCode32SimdMemSingle)context.CurrOp;
|
||||
|
||||
if (op.Replicate && !load) throw new Exception("Replicate+Store is undefined for STn");
|
||||
int eBytes = 1 << op.Size;
|
||||
|
||||
Operand n = context.Copy(GetIntA32(context, op.Rn));
|
||||
|
||||
//check alignment (?)
|
||||
// TODO: Check alignment.
|
||||
int offset = 0;
|
||||
int d = op.Vd;
|
||||
|
||||
for (int i=0; i<count; i++)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//write an element from a double simd register
|
||||
// Write an element from a double simd register.
|
||||
Operand address = context.Add(n, Const(offset));
|
||||
if (eBytes == 8)
|
||||
{
|
||||
|
@ -140,8 +145,8 @@ namespace ARMeilleure.Instructions
|
|||
int elemD = d + reg;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// write an element from a double simd register
|
||||
// add ebytes for each element
|
||||
// Write an element from a double simd register
|
||||
// add ebytes for each element.
|
||||
Operand address = context.Add(n, Const(offset));
|
||||
int index = ((elemD & 1) << (3 - op.Size)) + elem;
|
||||
if (eBytes == 8)
|
||||
|
@ -324,7 +329,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if ((accType & AccessType.Load) != 0)
|
||||
{
|
||||
|
||||
if (size == DWordSizeLog2)
|
||||
{
|
||||
EmitDVectorLoad(context, address, op.Vd);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -26,16 +25,17 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmov_GS(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdMovGp op = (OpCode32SimdMovGp)context.CurrOp;
|
||||
|
||||
Operand vec = GetVecA32(op.Vn >> 2);
|
||||
if (op.Op == 1)
|
||||
{
|
||||
// to general purpose
|
||||
// To general purpose.
|
||||
Operand value = context.VectorExtract(OperandType.I32, vec, op.Vn & 0x3);
|
||||
SetIntA32(context, op.Rt, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// from general purpose
|
||||
// From general purpose.
|
||||
Operand value = GetIntA32(context, op.Rt);
|
||||
context.Copy(vec, context.VectorInsert(vec, value, op.Vn & 0x3));
|
||||
}
|
||||
|
@ -44,16 +44,17 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmov_G1(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdMovGpElem op = (OpCode32SimdMovGpElem)context.CurrOp;
|
||||
|
||||
int index = op.Index + ((op.Vd & 1) << (3 - op.Size));
|
||||
if (op.Op == 1)
|
||||
{
|
||||
// to general purpose
|
||||
// To general purpose.
|
||||
Operand value = EmitVectorExtract32(context, op.Vd >> 1, index, op.Size, !op.U);
|
||||
SetIntA32(context, op.Rt, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// from general purpose
|
||||
// From general purpose.
|
||||
Operand vec = GetVecA32(op.Vd >> 1);
|
||||
Operand value = GetIntA32(context, op.Rt);
|
||||
context.Copy(vec, EmitVectorInsert(context, vec, value, index, op.Size));
|
||||
|
@ -63,13 +64,14 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vmov_G2(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
|
||||
|
||||
Operand vec = GetVecA32(op.Vm >> 2);
|
||||
int vm1 = (op.Vm + 1);
|
||||
bool sameOwnerVec = (op.Vm >> 2) == (vm1 >> 2);
|
||||
Operand vec2 = sameOwnerVec ? vec : GetVecA32(vm1 >> 2);
|
||||
if (op.Op == 1)
|
||||
{
|
||||
// to general purpose
|
||||
// To general purpose.
|
||||
Operand lowValue = context.VectorExtract(OperandType.I32, vec, op.Vm & 3);
|
||||
SetIntA32(context, op.Rt, lowValue);
|
||||
|
||||
|
@ -78,7 +80,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
// from general purpose
|
||||
// From general purpose.
|
||||
Operand lowValue = GetIntA32(context, op.Rt);
|
||||
Operand resultVec = context.VectorInsert(vec, lowValue, op.Vm & 3);
|
||||
|
||||
|
@ -93,31 +95,30 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(vec, resultVec);
|
||||
context.Copy(vec2, context.VectorInsert(vec2, highValue, vm1 & 3));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vmov_GD(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
|
||||
|
||||
Operand vec = GetVecA32(op.Vm >> 1);
|
||||
if (op.Op == 1)
|
||||
{
|
||||
// to general purpose
|
||||
// To general purpose.
|
||||
Operand value = context.VectorExtract(OperandType.I64, vec, op.Vm & 1);
|
||||
SetIntA32(context, op.Rt, context.ConvertI64ToI32(value));
|
||||
SetIntA32(context, op.Rt2, context.ConvertI64ToI32(context.ShiftRightUI(value, Const(32))));
|
||||
}
|
||||
else
|
||||
{
|
||||
// from general purpose
|
||||
// From general purpose.
|
||||
Operand lowValue = GetIntA32(context, op.Rt);
|
||||
Operand highValue = GetIntA32(context, op.Rt2);
|
||||
|
||||
Operand value = context.BitwiseOr(
|
||||
context.ZeroExtend32(OperandType.I64, lowValue),
|
||||
context.ShiftLeft(context.ZeroExtend32(OperandType.I64, highValue), Const(32))
|
||||
);
|
||||
context.ShiftLeft(context.ZeroExtend32(OperandType.I64, highValue), Const(32)));
|
||||
|
||||
context.Copy(vec, context.VectorInsert(vec, value, op.Vm & 1));
|
||||
}
|
||||
|
@ -133,11 +134,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int length = op.Length + 1;
|
||||
|
||||
Tuple<int, int>[] tableTuples = new Tuple<int, int>[length];
|
||||
(int Qx, int Ix)[] tableTuples = new (int qx, int ix)[length];
|
||||
for (int i=0; i< length; i++)
|
||||
{
|
||||
(int vn, int en) = GetQuadwordAndSubindex(op.Vn + i, op.RegisterSize);
|
||||
tableTuples[i] = new Tuple<int, int>(vn, en);
|
||||
tableTuples[i] = (vn, en);
|
||||
}
|
||||
|
||||
int byteLength = length * 8;
|
||||
|
@ -151,41 +152,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand end = Label();
|
||||
Operand inRange = context.ICompareLess(selectedIndex, Const(byteLength));
|
||||
Operand elemRes = null; // note: this is I64 for ease of calculation
|
||||
Operand elemRes = null; // Note: This is I64 for ease of calculation.
|
||||
|
||||
// for some reason this branch ruins everything so we do an extract + conditional select instead
|
||||
// granted that is slower
|
||||
// --- context.BranchIfFalse(end, inRange); ---
|
||||
// TODO: Branching rather than conditional select.
|
||||
|
||||
// get indexed byte
|
||||
// to simplify (ha) the il, we get bytes from every vector and use a nested conditional select to choose the right result
|
||||
// does have to extract `length` times for every element but certainly not as bad as it could be
|
||||
// Get indexed byte.
|
||||
// To simplify (ha) the il, we get bytes from every vector and use a nested conditional select to choose the right result.
|
||||
// This does have to extract `length` times for every element but certainly not as bad as it could be.
|
||||
|
||||
// which vector number is the index on
|
||||
// Which vector number is the index on.
|
||||
Operand vecIndex = context.ShiftRightUI(selectedIndex, Const(3));
|
||||
// what should we shift by to extract it
|
||||
// What should we shift by to extract it.
|
||||
Operand subVecIndexShift = context.ShiftLeft(context.BitwiseAnd(selectedIndex, Const(7)), Const(3));
|
||||
|
||||
for (int i=0; i < length; i++)
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Tuple<int, int> vectorLocation = tableTuples[i];
|
||||
// get the whole vector, we'll get a byte out of it
|
||||
(int qx, int ix) = tableTuples[i];
|
||||
// Get the whole vector, we'll get a byte out of it.
|
||||
Operand lookupResult;
|
||||
if (vectorLocation.Item1 == op.Qd)
|
||||
if (qx == op.Qd)
|
||||
{
|
||||
// result contains the current state of the vector
|
||||
lookupResult = context.VectorExtract(OperandType.I64, res, vectorLocation.Item2);
|
||||
// Result contains the current state of the vector.
|
||||
lookupResult = context.VectorExtract(OperandType.I64, res, ix);
|
||||
}
|
||||
else
|
||||
{
|
||||
lookupResult = EmitVectorExtract32(context, vectorLocation.Item1, vectorLocation.Item2, 3, false); //I64
|
||||
lookupResult = EmitVectorExtract32(context, qx, ix, 3, false); // I64
|
||||
}
|
||||
|
||||
lookupResult = context.ShiftRightUI(lookupResult, subVecIndexShift); // get the relevant byte from this vector
|
||||
lookupResult = context.ShiftRightUI(lookupResult, subVecIndexShift); // Get the relevant byte from this vector.
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
elemRes = lookupResult; //first result is always default
|
||||
elemRes = lookupResult; // First result is always default.
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -15,12 +15,14 @@ namespace ARMeilleure.Instructions
|
|||
public static void Vshl(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdShift op = (OpCode32SimdShift)context.CurrOp;
|
||||
|
||||
EmitVectorUnaryOpZx32(context, (op1) => context.ShiftLeft(op1, Const(op1.Type, op.Shift)));
|
||||
}
|
||||
|
||||
public static void Vshl_I(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
||||
if (op.U)
|
||||
{
|
||||
EmitVectorBinaryOpZx32(context, (op1, op2) => EmitShlRegOp(context, op2, op1, op.Size, true));
|
||||
|
@ -59,7 +61,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand isOutOfRange0 = context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size));
|
||||
Operand isOutOfRangeN = context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size));
|
||||
|
||||
//also zero if shift is too negative, but value was positive
|
||||
// Also zero if shift is too negative, but value was positive.
|
||||
isOutOfRange0 = context.BitwiseOr(isOutOfRange0, context.BitwiseAnd(isOutOfRangeN, context.ICompareGreaterOrEqual(op, Const(op.Type, 0))));
|
||||
|
||||
Operand min = (op.Type == OperandType.I64) ? Const(-1L) : Const(-1);
|
||||
|
@ -67,6 +69,5 @@ namespace ARMeilleure.Instructions
|
|||
return context.ConditionalSelect(isOutOfRange0, Const(op.Type, 0), context.ConditionalSelect(isOutOfRangeN, min, res));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static void Vmrs(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
if (op.Rt == 15 && op.Sreg == 0b0001)
|
||||
if (op.Rt == RegisterAlias.Aarch32Pc && op.Sreg == 0b0001)
|
||||
{
|
||||
//special behavior: copy NZCV flags into APSR
|
||||
// Special behavior: copy NZCV flags into APSR.
|
||||
SetFlag(context, PState.VFlag, GetFpFlag(FPState.VFlag));
|
||||
SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
|
||||
SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
|
||||
|
@ -29,17 +29,17 @@ namespace ARMeilleure.Instructions
|
|||
Delegate dlg;
|
||||
switch (op.Sreg)
|
||||
{
|
||||
case 0b0000: //FPSID
|
||||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: //FPSCR
|
||||
case 0b0001: // FPSCR
|
||||
dlg = new _U32(NativeInterface.GetFpscr); break;
|
||||
case 0b0101: //MVFR2
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: //MVFR1
|
||||
case 0b0110: // MVFR1
|
||||
throw new NotImplementedException("MVFR1");
|
||||
case 0b0111: //MVFR0
|
||||
case 0b0111: // MVFR0
|
||||
throw new NotImplementedException("MVFR0");
|
||||
case 0b1000: //FPEXC
|
||||
case 0b1000: // FPEXC
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
default: throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
@ -49,22 +49,22 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Vmsr(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
switch (op.Sreg)
|
||||
{
|
||||
case 0b0000: //FPSID
|
||||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: //FPSCR
|
||||
case 0b0001: // FPSCR
|
||||
dlg = new _Void_U32(NativeInterface.SetFpscr); break;
|
||||
case 0b0101: //MVFR2
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: //MVFR1
|
||||
case 0b0110: // MVFR1
|
||||
throw new NotImplementedException("MVFR1");
|
||||
case 0b0111: //MVFR0
|
||||
case 0b0111: // MVFR0
|
||||
throw new NotImplementedException("MVFR0");
|
||||
case 0b1000: //FPEXC
|
||||
case 0b1000: // FPEXC
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
default: throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Mrc(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32System)context.CurrOp;
|
||||
OpCode32System op = (OpCode32System)context.CurrOp;
|
||||
|
||||
if (op.Coproc != 15)
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ namespace ARMeilleure.Instructions
|
|||
Delegate dlg;
|
||||
switch (op.CRn)
|
||||
{
|
||||
case 13: // Process and Thread Info
|
||||
case 13: // Process and Thread Info.
|
||||
if (op.CRm != 0)
|
||||
{
|
||||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
|
||||
|
@ -107,9 +107,9 @@ namespace ARMeilleure.Instructions
|
|||
default: throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
if (op.Rt == 15)
|
||||
if (op.Rt == RegisterAlias.Aarch32Pc)
|
||||
{
|
||||
//special behavior: copy NZCV flags into APSR
|
||||
// Special behavior: copy NZCV flags into APSR.
|
||||
EmitSetNzcv(context, context.Call(dlg));
|
||||
return;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Mcr(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32System)context.CurrOp;
|
||||
OpCode32System op = (OpCode32System)context.CurrOp;
|
||||
|
||||
if (op.Coproc != 15)
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ namespace ARMeilleure.Instructions
|
|||
Delegate dlg;
|
||||
switch (op.CRn)
|
||||
{
|
||||
case 13: // Process and Thread Info
|
||||
case 13: // Process and Thread Info.
|
||||
if (op.CRm != 0)
|
||||
{
|
||||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
|
||||
|
@ -151,13 +151,13 @@ namespace ARMeilleure.Instructions
|
|||
break;
|
||||
|
||||
case 7:
|
||||
switch (op.CRm) // Cache and Memory barrier
|
||||
switch (op.CRm) // Cache and Memory barrier.
|
||||
{
|
||||
case 10:
|
||||
switch (op.Opc2)
|
||||
{
|
||||
case 5: // Data Memory Barrier Register
|
||||
return; // no-op
|
||||
case 5: // Data Memory Barrier Register.
|
||||
return; // No-op.
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Mrrc(ArmEmitterContext context)
|
||||
{
|
||||
var op = (OpCode32System)context.CurrOp;
|
||||
OpCode32System op = (OpCode32System)context.CurrOp;
|
||||
|
||||
if (op.Coproc != 15)
|
||||
{
|
||||
|
@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
|
|||
Delegate dlg;
|
||||
switch (op.CRm)
|
||||
{
|
||||
case 14: // Timer
|
||||
case 14: // Timer.
|
||||
switch (opc)
|
||||
{
|
||||
case 0:
|
||||
|
@ -222,5 +222,9 @@ namespace ARMeilleure.Instructions
|
|||
SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
|
||||
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
|
||||
}
|
||||
|
||||
public static void Nop(ArmEmitterContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -545,9 +545,10 @@ namespace ARMeilleure.Instructions
|
|||
Vldr,
|
||||
Vmax,
|
||||
Vmin,
|
||||
VMMmn,
|
||||
Vmla,
|
||||
Vmls,
|
||||
VMMmn,
|
||||
Vmov,
|
||||
Vmrs,
|
||||
Vmsr,
|
||||
Vmul,
|
||||
|
@ -578,7 +579,5 @@ namespace ARMeilleure.Instructions
|
|||
Vtrn,
|
||||
Vuzp,
|
||||
Vzip,
|
||||
|
||||
Vmov
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1535,6 +1535,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2826,6 +2827,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3026,7 +3028,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static double FPThree(bool sign)
|
||||
{
|
||||
return sign ? -2d : +2d;
|
||||
return sign ? -3d : +3d;
|
||||
}
|
||||
|
||||
private static double FPOnePointFive(bool sign)
|
||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
|||
namespace ARMeilleure.State
|
||||
{
|
||||
[Flags]
|
||||
public enum FPCR : ulong
|
||||
public enum FPCR : uint
|
||||
{
|
||||
Ufe = 1 << 11,
|
||||
Fz = 1 << 24,
|
||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
|||
namespace ARMeilleure.State
|
||||
{
|
||||
[Flags]
|
||||
public enum FPSR : ulong
|
||||
public enum FPSR : uint
|
||||
{
|
||||
Ufc = 1 << 3,
|
||||
Qc = 1 << 27,
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace ARMeilleure.State
|
|||
public const int SpFiq = 29;
|
||||
public const int LrFiq = 30;
|
||||
|
||||
public const int Aarch32Sp = 13;
|
||||
public const int Aarch32Lr = 14;
|
||||
public const int Aarch32Pc = 15;
|
||||
|
||||
|
|
|
@ -403,7 +403,6 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private static long ClearCallerSavedIntRegs(long mask)
|
||||
{
|
||||
// TODO: ARM32 support.
|
||||
mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask);
|
||||
|
||||
return mask;
|
||||
|
@ -411,7 +410,6 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private static long ClearCallerSavedVecRegs(long mask)
|
||||
{
|
||||
// TODO: ARM32 support.
|
||||
mask &= ~(CallerSavedVecRegistersMask | FpStateNzcvFlagsMask);
|
||||
|
||||
return mask;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
|
||||
|
||||
private PriorityQueue<Tuple<ulong, ExecutionMode>> _backgroundQueue;
|
||||
private PriorityQueue<(ulong Address, ExecutionMode Mode)> _backgroundQueue;
|
||||
|
||||
private AutoResetEvent _backgroundTranslatorEvent;
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
|
||||
|
||||
_backgroundQueue = new PriorityQueue<Tuple<ulong, ExecutionMode>>(2);
|
||||
_backgroundQueue = new PriorityQueue<(ulong, ExecutionMode)>(2);
|
||||
|
||||
_backgroundTranslatorEvent = new AutoResetEvent(false);
|
||||
}
|
||||
|
@ -41,11 +41,11 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
while (_threadCount != 0)
|
||||
{
|
||||
if (_backgroundQueue.TryDequeue(out Tuple<ulong, ExecutionMode> request))
|
||||
if (_backgroundQueue.TryDequeue(out (ulong Address, ExecutionMode Mode) request))
|
||||
{
|
||||
TranslatedFunction func = Translate(request.Item1, request.Item2, highCq: true);
|
||||
TranslatedFunction func = Translate(request.Address, request.Mode, highCq: true);
|
||||
|
||||
_funcs.AddOrUpdate(request.Item1, func, (key, oldFunc) => func);
|
||||
_funcs.AddOrUpdate(request.Address, func, (key, oldFunc) => func);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
else if (isCallTarget && func.ShouldRejit())
|
||||
{
|
||||
_backgroundQueue.Enqueue(0, new Tuple<ulong, ExecutionMode>(address, mode));
|
||||
_backgroundQueue.Enqueue(0, (address, mode));
|
||||
|
||||
_backgroundTranslatorEvent.Set();
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace Ryujinx.Tests.Unicorn.Native
|
|||
CONTROL,
|
||||
ENDING,
|
||||
|
||||
// alias registers
|
||||
// Alias registers.
|
||||
R13 = SP,
|
||||
R14 = LR,
|
||||
R15 = PC,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using Ryujinx.Tests.Unicorn.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Unicorn
|
||||
{
|
||||
|
@ -148,7 +146,7 @@ namespace Ryujinx.Tests.Unicorn
|
|||
|
||||
public uint GetX(int index)
|
||||
{
|
||||
if ((uint)index > 30)
|
||||
if ((uint)index > 15)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
@ -158,7 +156,7 @@ namespace Ryujinx.Tests.Unicorn
|
|||
|
||||
public void SetX(int index, uint value)
|
||||
{
|
||||
if ((uint)index > 30)
|
||||
if ((uint)index > 15)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
@ -173,7 +171,8 @@ namespace Ryujinx.Tests.Unicorn
|
|||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
return GetVector((Arm32Register)((int)Arm32Register.D0 + index * 2)); //QRegisters[index]);
|
||||
// Getting quadword registers from Unicorn A32 seems to be broken, so we combine its 2 doubleword registers instead.
|
||||
return GetVector((Arm32Register)((int)Arm32Register.D0 + index * 2));
|
||||
}
|
||||
|
||||
public void SetQ(int index, SimdValue value)
|
||||
|
|
|
@ -4,10 +4,7 @@ using ARMeilleure.Translation;
|
|||
using NUnit.Framework;
|
||||
using Ryujinx.Tests.Unicorn;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
|
@ -361,7 +358,8 @@ namespace Ryujinx.Tests.Cpu
|
|||
byte[] meilleureMem = _memory.ReadBytes((long)(0x2000), _size);
|
||||
byte[] unicornMem = _unicornEmu.MemoryRead((ulong)(0x2000), (ulong)_size);
|
||||
|
||||
for (int i = 0; i < _size; i++) {
|
||||
for (int i = 0; i < _size; i++)
|
||||
{
|
||||
Assert.AreEqual(meilleureMem[i], unicornMem[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#define Alu32
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
|
@ -19,7 +17,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
|
||||
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb)
|
||||
{
|
||||
msb = Math.Max(lsb, msb); // don't test unpredictable for now
|
||||
msb = Math.Max(lsb, msb); // Don't test unpredictable for now.
|
||||
uint opcode = 0xe7c0001fu; // BFC R0, #0, #1
|
||||
opcode |= ((rd & 0xf) << 12);
|
||||
opcode |= ((msb & 31) << 16) | ((lsb & 31) << 7);
|
||||
|
@ -40,7 +38,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImmr)] uint lsb,
|
||||
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb)
|
||||
{
|
||||
msb = Math.Max(lsb, msb); // don't test unpredictable for now
|
||||
msb = Math.Max(lsb, msb); // Don't test unpredictable for now.
|
||||
uint opcode = 0xe7c00010u; // BFI R0, R0, #0, #1
|
||||
opcode |= ((rd & 0xf) << 12);
|
||||
opcode |= ((rn & 0xf) << 0);
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#define SimdLogical32
|
||||
using ARMeilleure.State;
|
||||
using NUnit.Framework;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
using ARMeilleure.State;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Tests.Cpu
|
||||
{
|
||||
|
@ -16,26 +13,26 @@ namespace Ryujinx.Tests.Cpu
|
|||
private const int RndCntImm = 2;
|
||||
|
||||
private uint[] LDSTModes =
|
||||
{
|
||||
//LD1
|
||||
0b0111,
|
||||
0b1010,
|
||||
0b0110,
|
||||
0b0010,
|
||||
{
|
||||
// LD1
|
||||
0b0111,
|
||||
0b1010,
|
||||
0b0110,
|
||||
0b0010,
|
||||
|
||||
//LD2
|
||||
0b1000,
|
||||
0b1001,
|
||||
0b0011,
|
||||
// LD2
|
||||
0b1000,
|
||||
0b1001,
|
||||
0b0011,
|
||||
|
||||
//LD3
|
||||
0b0100,
|
||||
0b0101,
|
||||
// LD3
|
||||
0b0100,
|
||||
0b0101,
|
||||
|
||||
//LD4
|
||||
0b0000,
|
||||
0b0001
|
||||
};
|
||||
// LD4
|
||||
0b0000,
|
||||
0b0001
|
||||
};
|
||||
|
||||
[Test, Pairwise, Description("VLDn.<size> <list>, [<Rn> {:<align>}]{ /!/, <Rm>} (single n element structure)")]
|
||||
public void Vldn_Single([Values(0u, 1u, 2u)] uint size,
|
||||
|
@ -60,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= ((vd & 0x10) << 18);
|
||||
opcode |= ((vd & 0xf) << 12);
|
||||
|
||||
opcode |= (n & 3) << 8; //LD1 is 0, LD2 is 1 etc
|
||||
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
||||
|
||||
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
|
||||
|
||||
|
@ -86,8 +83,8 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= ((vd & 0x10) << 18);
|
||||
opcode |= ((vd & 0xf) << 12);
|
||||
|
||||
opcode |= (n & 3) << 8; //LD1 is 0, LD2 is 1 etc
|
||||
if (t) opcode |= 1 << 5; //LD1 is 0, LD2 is 1 etc
|
||||
opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
|
||||
if (t) opcode |= 1 << 5;
|
||||
|
||||
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
|
||||
|
||||
|
@ -142,7 +139,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= ((vd & 0x10) << 18);
|
||||
opcode |= ((vd & 0xf) << 12);
|
||||
|
||||
opcode |= (n & 3) << 8; //ST1 is 0, ST2 is 1 etc
|
||||
opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
|
||||
|
||||
SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500);
|
||||
|
||||
|
@ -187,10 +184,10 @@ namespace Ryujinx.Tests.Cpu
|
|||
uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0
|
||||
|
||||
uint[] vldmModes = {
|
||||
//note: 3rd 0 leaves a space for "D"
|
||||
0b0100, // increment after
|
||||
0b0101, // increment after !
|
||||
0b1001 // decrement before !
|
||||
// Note: 3rd 0 leaves a space for "D".
|
||||
0b0100, // Increment after.
|
||||
0b0101, // Increment after. (!)
|
||||
0b1001 // Decrement before. (!)
|
||||
};
|
||||
|
||||
opcode |= ((vldmModes[mode] & 15) << 21);
|
||||
|
@ -201,15 +198,15 @@ namespace Ryujinx.Tests.Cpu
|
|||
|
||||
opcode |= ((uint)(single ? 0 : 1) << 8);
|
||||
|
||||
if (!single) regs = (regs << 1); //low bit must be 0 - must be even number of registers.
|
||||
if (!single) regs = (regs << 1); // Low bit must be 0 - must be even number of registers.
|
||||
uint regSize = single ? 1u : 2u;
|
||||
|
||||
if (vd + (regs / regSize) > 32) //can't address further than s31 or d31
|
||||
if (vd + (regs / regSize) > 32) // Can't address further than S31 or D31.
|
||||
{
|
||||
regs -= (vd + (regs / regSize)) - 32;
|
||||
}
|
||||
|
||||
if (regs / regSize > 16) //can't do more than 16 registers at a time
|
||||
if (regs / regSize > 16) // Can't do more than 16 registers at a time.
|
||||
{
|
||||
regs = 16 * regSize;
|
||||
}
|
||||
|
@ -222,7 +219,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
}
|
||||
|
||||
[Test, Pairwise, Description("VLDR.<size> <Sd>, [<Rn> {, #{+/-}<imm>}]")]
|
||||
public void Vldr([Values(2u, 3u)] uint size, //fp16 is not supported for now
|
||||
public void Vldr([Values(2u, 3u)] uint size, // FP16 is not supported for now
|
||||
[Values(0u)] uint rn,
|
||||
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
|
||||
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
|
||||
|
@ -249,7 +246,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= ((sd & 0x10) << 18);
|
||||
opcode |= ((sd & 0xf) << 12);
|
||||
}
|
||||
opcode |= (uint)imm & 0xff;
|
||||
opcode |= imm & 0xff;
|
||||
|
||||
SingleOpcode(opcode, r0: 0x2500);
|
||||
|
||||
|
@ -257,7 +254,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
}
|
||||
|
||||
[Test, Pairwise, Description("VSTR.<size> <Sd>, [<Rn> {, #{+/-}<imm>}]")]
|
||||
public void Vstr([Values(2u, 3u)] uint size, //fp16 is not supported for now
|
||||
public void Vstr([Values(2u, 3u)] uint size, // FP16 is not supported for now
|
||||
[Values(0u)] uint rn,
|
||||
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
|
||||
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
|
||||
|
@ -284,7 +281,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= ((sd & 0x10) << 18);
|
||||
opcode |= ((sd & 0xf) << 12);
|
||||
}
|
||||
opcode |= (uint)imm & 0xff;
|
||||
opcode |= imm & 0xff;
|
||||
|
||||
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
|
||||
|
||||
|
@ -308,7 +305,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
int floatLength = length >> 2;
|
||||
float[] data = new float[floatLength];
|
||||
|
||||
for (int i=0; i<floatLength; i++)
|
||||
for (int i = 0; i < floatLength; i++)
|
||||
{
|
||||
data[i] = i + (i / 9f);
|
||||
}
|
||||
|
|
|
@ -22,17 +22,17 @@ namespace Ryujinx.Tests.Cpu
|
|||
{
|
||||
uint[] variants =
|
||||
{
|
||||
//I32
|
||||
// I32
|
||||
0b0000_0,
|
||||
0b0010_0,
|
||||
0b0100_0,
|
||||
0b0110_0,
|
||||
|
||||
//I16
|
||||
// I16
|
||||
0b1000_0,
|
||||
0b1010_0,
|
||||
|
||||
//dt
|
||||
// DT
|
||||
0b1100_0,
|
||||
0b1101_0,
|
||||
0b1110_0,
|
||||
|
@ -149,7 +149,6 @@ namespace Ryujinx.Tests.Cpu
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: new V128(valueVn2, valueVn1));
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
|
@ -191,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
[Random(RndCntImm)] ulong valueVn2,
|
||||
[Values] bool op)
|
||||
{
|
||||
uint opcode = 0xec400a10u; //VMOV S0, S1, R0, R0
|
||||
uint opcode = 0xec400a10u; // VMOV S0, S1, R0, R0
|
||||
opcode |= (vm & 1) << 5;
|
||||
opcode |= (vm & 0x1e) >> 1;
|
||||
opcode |= (rt & 0xf) << 12;
|
||||
|
@ -216,7 +215,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
uint opcode = 0xf3b20080u; // VTRN.8 D0, D0
|
||||
if (vm == vd)
|
||||
{
|
||||
return; //undefined
|
||||
return; // Undefined.
|
||||
}
|
||||
|
||||
if (q)
|
||||
|
@ -246,10 +245,10 @@ namespace Ryujinx.Tests.Cpu
|
|||
[Values(0u, 1u, 2u)] uint size,
|
||||
[Values] bool q)
|
||||
{
|
||||
uint opcode = 0xf3b20180u; // VZIP.8 d0, d0
|
||||
uint opcode = 0xf3b20180u; // VZIP.8 D0, D0
|
||||
if (vm == vd || (size == 2 && !q))
|
||||
{
|
||||
return; //undefined
|
||||
return; // Undefined.
|
||||
}
|
||||
|
||||
if (q)
|
||||
|
@ -282,7 +281,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
uint opcode = 0xf3b20100u; // VUZP.8 d0, d0
|
||||
if (vm == vd || (size == 2 && !q))
|
||||
{
|
||||
return; //undefined
|
||||
return; // Undefined.
|
||||
}
|
||||
|
||||
if (q)
|
||||
|
@ -307,16 +306,16 @@ namespace Ryujinx.Tests.Cpu
|
|||
}
|
||||
|
||||
[Test, Combinatorial, Description("VTBL.8 <Dd>, {list}, <Dm>")]
|
||||
public void Vtbl([Range(0u, 6u)] uint vm, //indices, include potentially invalid
|
||||
[Range(4u, 12u)] uint vn, //selection
|
||||
[Values(0u, 1u)] uint vd, //destinations
|
||||
public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid.
|
||||
[Range(4u, 12u)] uint vn, // Selection.
|
||||
[Values(0u, 1u)] uint vd, // Destinations.
|
||||
[Range(0u, 3u)] uint length,
|
||||
[Values] bool x)
|
||||
{
|
||||
uint opcode = 0xf3b00800u; // VTBL.8 D0, {D0}, D0
|
||||
if (vn + length > 31)
|
||||
{
|
||||
return; //undefined
|
||||
return; // Undefined.
|
||||
}
|
||||
|
||||
if (x)
|
||||
|
@ -371,7 +370,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
}
|
||||
else if (imm4 > 7)
|
||||
{
|
||||
return; //undefined
|
||||
return; // Undefined.
|
||||
}
|
||||
opcode |= (vm & 0x10) << 1;
|
||||
opcode |= (vm & 0xf);
|
||||
|
@ -412,8 +411,8 @@ namespace Ryujinx.Tests.Cpu
|
|||
opcode |= (vd & 0xf) << 16;
|
||||
opcode |= (rt & 0xf) << 12;
|
||||
|
||||
opcode |= (size & 1) << 5; // e
|
||||
opcode |= (size & 2) << 21; // b
|
||||
opcode |= (size & 1) << 5; // E
|
||||
opcode |= (size & 2) << 21; // B
|
||||
|
||||
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ namespace Ryujinx.Tests.Cpu
|
|||
private static readonly bool NoInfs = false;
|
||||
private static readonly bool NoNaNs = false;
|
||||
|
||||
[Explicit]
|
||||
[Test, Pairwise, Description("VADD.f32 V0, V0, V0")]
|
||||
public void Vadd_f32([Values(0u)] uint rd,
|
||||
[Values(0u, 1u)] uint rn,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue