Address Feedback

This commit is contained in:
riperiperi 2020-01-25 17:57:22 +00:00
commit 6476b3d24f
82 changed files with 591 additions and 806 deletions

View file

@ -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;

View file

@ -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)

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32AluBf
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32AluReg : IOpCode32Alu
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32AluUx : IOpCode32AluReg
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32MemEx : IOpCode32Mem
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32Simd : IOpCode32, IOpCodeSimd
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
interface IOpCode32SimdImm : IOpCode32Simd
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32AluBf : OpCode32, IOpCode32AluBf
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32AluMla : OpCode32, IOpCode32AluReg
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32AluReg : OpCode32Alu, IOpCode32AluReg
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32AluRsReg : OpCode32Alu
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32AluUmull : OpCode32
{

View file

@ -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)
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32Exception : OpCode32
{

View file

@ -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;

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32MemReg : OpCode32Mem
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32MemRsImm : OpCode32Mem
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32MemStEx : OpCode32Mem, IOpCode32MemEx
{

View file

@ -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);
}

View file

@ -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)
{
}
}

View file

@ -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;

View file

@ -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))
{

View file

@ -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;

View file

@ -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))
{

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdMemImm : OpCode32, IOpCode32Simd
{

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdRegElem : OpCode32SimdReg
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdRegS : OpCode32SimdS
{

View file

@ -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;
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdS : OpCode32, IOpCode32Simd
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdSel : OpCode32SimdRegS
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdSpecial : OpCode32
{

View file

@ -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))

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32SimdTbl : OpCode32SimdReg
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCode32System : OpCode32
{

View file

@ -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)

View file

@ -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));

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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)
{

View file

@ -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.
}
}
}

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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)
{

View file

@ -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);
}
});
}
}

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -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
{

View file

@ -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);

View file

@ -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
{

View file

@ -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));
}
}
}
}

View file

@ -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)
{
}
}
}

View file

@ -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
}
}

View file

@ -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)

View file

@ -3,7 +3,7 @@ using System;
namespace ARMeilleure.State
{
[Flags]
public enum FPCR : ulong
public enum FPCR : uint
{
Ufe = 1 << 11,
Fz = 1 << 24,

View file

@ -3,7 +3,7 @@ using System;
namespace ARMeilleure.State
{
[Flags]
public enum FPSR : ulong
public enum FPSR : uint
{
Ufc = 1 << 3,
Qc = 1 << 27,

View file

@ -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;

View file

@ -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;

View file

@ -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();
}

View file

@ -127,7 +127,7 @@ namespace Ryujinx.Tests.Unicorn.Native
CONTROL,
ENDING,
// alias registers
// Alias registers.
R13 = SP,
R14 = LR,
R15 = PC,

View file

@ -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)

View file

@ -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]);
}
}

View file

@ -1,8 +1,6 @@
#define Alu32
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.Tests.Cpu
{

View file

@ -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);

View file

@ -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
{

View file

@ -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);
}

View file

@ -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());

View file

@ -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,