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) private static bool IsCall(OpCode opCode)
{ {
// TODO (CQ): ARM32 support.
return opCode.Instruction.Name == InstName.Bl || return opCode.Instruction.Name == InstName.Bl ||
opCode.Instruction.Name == InstName.Blr || opCode.Instruction.Name == InstName.Blr ||
opCode.Instruction.Name == InstName.Blx; opCode.Instruction.Name == InstName.Blx;

View file

@ -151,7 +151,8 @@ namespace ARMeilleure.Decoders
public static bool VectorArgumentsInvalid(bool q, params int[] args) public static bool VectorArgumentsInvalid(bool q, params int[] args)
{ {
if (q) { if (q)
{
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
{ {
if ((args[i] & 1) == 1) if ((args[i] & 1) == 1)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,4 @@
using System; using ARMeilleure.State;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
@ -8,7 +6,7 @@ namespace ARMeilleure.Decoders
{ {
public int Rotate { get; private set; } public int Rotate { get; private set; }
public int RotateBits => Rotate * 8; 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) public OpCode32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {

View file

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

View file

@ -1,12 +1,8 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32MemLdEx : OpCode32Mem, IOpCode32MemEx 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) public OpCode32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = opCode & 0xf; Rd = opCode & 0xf;

View file

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

View file

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

View file

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

View file

@ -1,10 +1,6 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32Simd : BaseOpCode32Simd class OpCode32Simd : OpCode32SimdBase
{ {
public int Opc { get; protected set; } public int Opc { get; protected set; }
public bool Q { 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) 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; Q = ((opCode >> 6) & 0x1) != 0;
F = ((opCode >> 10) & 0x1) != 0; F = ((opCode >> 10) & 0x1) != 0;
U = ((opCode >> 24) & 0x1) != 0; U = ((opCode >> 24) & 0x1) != 0;
@ -24,7 +20,7 @@ namespace ARMeilleure.Decoders
Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf); Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 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); DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm);
} }

View file

@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
abstract class BaseOpCode32Simd : OpCode32, IOpCode32Simd abstract class OpCode32SimdBase : OpCode32, IOpCode32Simd
{ {
public int Vd { get; protected set; } public int Vd { get; protected set; }
public int Vm { get; protected set; } public int Vm { get; protected set; }
@ -29,7 +27,6 @@ namespace ARMeilleure.Decoders
switch (RegisterSize) switch (RegisterSize)
{ {
case RegisterSize.Simd128: case RegisterSize.Simd128:
return index >> 1;
case RegisterSize.Simd64: case RegisterSize.Simd64:
return index >> 1; return index >> 1;
} }
@ -50,7 +47,7 @@ namespace ARMeilleure.Decoders
throw new InvalidOperationException(); 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; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
/// <summary> /// <summary>
/// A special alias that always runs in 64 bit int, to speed up binary ops a little. /// 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) public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Size = 3; Size = 3;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn)) if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
{ {
Instruction = InstDescriptor.Undefined; Instruction = InstDescriptor.Undefined;

View file

@ -1,14 +1,10 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdCmpZ : OpCode32Simd class OpCode32SimdCmpZ : OpCode32Simd
{ {
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) 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)) if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
{ {

View file

@ -1,12 +1,9 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdCvtFI : OpCode32SimdS class OpCode32SimdCvtFI : OpCode32SimdS
{ {
public int Opc2 { get; private set; } public int Opc2 { get; private set; }
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Opc2 = (opCode >> 16) & 0x7; Opc2 = (opCode >> 16) & 0x7;

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdDupElem : OpCode32Simd class OpCode32SimdDupElem : OpCode32Simd
{ {
@ -34,8 +30,6 @@ namespace ARMeilleure.Decoders
Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf); Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf); Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
Q = (opCode & (1 << 6)) != 0;
if (Q) RegisterSize = RegisterSize.Simd128;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd)) if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
{ {

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdDupGP : OpCode32, IOpCode32Simd class OpCode32SimdDupGP : OpCode32, IOpCode32Simd
{ {
@ -13,7 +9,7 @@ namespace ARMeilleure.Decoders
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); //B:E - 0 for 32, 16 then 8. Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
if (Size == -1) if (Size == -1)
{ {
Instruction = InstDescriptor.Undefined; Instruction = InstDescriptor.Undefined;

View file

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

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdImm : OpCode32, IOpCode32SimdImm class OpCode32SimdImm : OpCode32, IOpCode32SimdImm
{ {
@ -11,6 +7,7 @@ namespace ARMeilleure.Decoders
public long Immediate { get; private set; } public long Immediate { get; private set; }
public int Size { get; private set; } public int Size { get; private set; }
public int Elems => GetBytesCount() >> Size; public int Elems => GetBytesCount() >> Size;
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
@ -27,10 +24,7 @@ namespace ARMeilleure.Decoders
imm |= ((uint)opCode >> 12) & 0x70; imm |= ((uint)opCode >> 12) & 0x70;
imm |= ((uint)opCode >> 17) & 0x80; imm |= ((uint)opCode >> 17) & 0x80;
Tuple<long, int> parsedImm = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm, fpBaseSize: 2); (Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm, fpBaseSize: 2);
Immediate = parsedImm.Item1;
Size = parsedImm.Item2;
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64; RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdImm44 : OpCode32, IOpCode32SimdImm class OpCode32SimdImm44 : OpCode32, IOpCode32SimdImm
{ {
@ -10,6 +6,7 @@ namespace ARMeilleure.Decoders
public long Immediate { get; private set; } public long Immediate { get; private set; }
public int Size { get; private set; } public int Size { get; private set; }
public int Elems { get; private set; } public int Elems { get; private set; }
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Size = (opCode >> 8) & 0x3; Size = (opCode >> 8) & 0x3;

View file

@ -1,13 +1,10 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdShift : OpCode32Simd class OpCode32SimdShift : OpCode32Simd
{ {
public int Immediate { get; private set; } public int Immediate { get; private set; }
public int Shift { get; private set; } public int Shift { get; private set; }
public OpCode32SimdShift(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdShift(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Immediate = (opCode >> 16) & 0x3f; Immediate = (opCode >> 16) & 0x3f;

View file

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

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMemMult : OpCode32 class OpCode32SimdMemMult : OpCode32
{ {
@ -45,7 +41,7 @@ namespace ARMeilleure.Decoders
RegisterRange = opCode & 0xff; 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) if (!u)
{ {

View file

@ -1,22 +1,17 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
{ {
private static Dictionary<int, int> RegsMap = new Dictionary<int, int>() private static int[] RegsMap =
{ {
{ 0b0111, 1 }, 1, 1, 4, 2,
{ 0b1010, 2 }, 1, 1, 3, 1,
{ 0b0110, 3 }, 1, 1, 2, 1,
{ 0b0010, 4 }, 1, 1, 1, 1
{ 0b1000, 1 },
{ 0b1001, 1 },
{ 0b0011, 2 },
}; };
public int Vd { get; private set; } public int Vd { get; private set; }
public int Rn { get; private set; } public int Rn { get; private set; }
public int Rm { get; private set; } public int Rm { get; private set; }
@ -27,6 +22,7 @@ namespace ARMeilleure.Decoders
public int Elems => 8 >> Size; public int Elems => 8 >> Size;
public int Regs { get; private set; } public int Regs { get; private set; }
public int Increment { get; private set; } public int Increment { get; private set; }
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
@ -41,12 +37,7 @@ namespace ARMeilleure.Decoders
WBack = Rm != 15; WBack = Rm != 15;
RegisterIndex = (Rm != 15 && Rm != 13); RegisterIndex = (Rm != 15 && Rm != 13);
int regs; Regs = RegsMap[(opCode >> 8) & 0xf];
if (!RegsMap.TryGetValue((opCode >> 8) & 0xf, out regs))
{
regs = 1;
}
Regs = regs;
Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1); Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1);
} }

View file

@ -1,6 +1,4 @@
using System; using ARMeilleure.State;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
@ -16,6 +14,7 @@ namespace ARMeilleure.Decoders
public int Size { get; private set; } public int Size { get; private set; }
public bool Replicate { get; private set; } public bool Replicate { get; private set; }
public int Increment { get; private set; } public int Increment { get; private set; }
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Vd = (opCode >> 12) & 0xf; Vd = (opCode >> 12) & 0xf;
@ -40,8 +39,8 @@ namespace ARMeilleure.Decoders
Rm = (opCode >> 0) & 0xf; Rm = (opCode >> 0) & 0xf;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
WBack = Rm != 15; WBack = Rm != RegisterAlias.Aarch32Pc;
RegisterIndex = (Rm != 15 && Rm != 13); RegisterIndex = (Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp);
} }
} }
} }

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMovGp : OpCode32, IOpCode32Simd class OpCode32SimdMovGp : OpCode32, IOpCode32Simd
{ {
@ -14,9 +10,10 @@ namespace ARMeilleure.Decoders
public int Opc1 { get; private set; } public int Opc1 { get; private set; }
public int Opc2 { get; private set; } public int Opc2 { get; private set; }
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) 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); Op = ((opCode >> 20) & 0x1);
Opc1 = ((opCode >> 21) & 0x3); Opc1 = ((opCode >> 21) & 0x3);

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd
{ {
@ -12,9 +8,10 @@ namespace ARMeilleure.Decoders
public int Rt { get; private set; } public int Rt { get; private set; }
public int Rt2 { get; private set; } public int Rt2 { get; private set; }
public int Op { get; private set; } public int Op { get; private set; }
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) 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); Op = ((opCode >> 20) & 0x1);
Rt = (opCode >> 12) & 0xf; Rt = (opCode >> 12) & 0xf;

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd
{ {
@ -15,7 +11,6 @@ namespace ARMeilleure.Decoders
public int Index { get; private set; } public int Index { get; private set; }
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Op = ((opCode >> 20) & 0x1); Op = ((opCode >> 20) & 0x1);

View file

@ -1,8 +1,4 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdReg : OpCode32Simd class OpCode32SimdReg : OpCode32Simd
{ {
@ -16,7 +12,7 @@ namespace ARMeilleure.Decoders
{ {
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf); 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)) if (this.GetType() == typeof(OpCode32SimdReg) && DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
{ {
Instruction = InstDescriptor.Undefined; Instruction = InstDescriptor.Undefined;

View file

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

View file

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

View file

@ -1,17 +1,13 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdRev : OpCode32SimdCmpZ class OpCode32SimdRev : OpCode32SimdCmpZ
{ {
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) 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. // 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) // 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; 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; Opc = tempSize;
} }
} }

View file

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

View file

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

View file

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

View file

@ -1,14 +1,10 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
class OpCode32SimdSqrte : OpCode32Simd class OpCode32SimdSqrte : OpCode32Simd
{ {
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) 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; F = ((opCode >> 8) & 0x1) != 0;
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm)) if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))

View file

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

View file

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

View file

@ -1,12 +1,8 @@
using System; namespace ARMeilleure.Decoders
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.Decoders
{ {
public static class OpCodeSimdHelper 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 modeLow = cMode & 1;
int modeHigh = cMode >> 1; int modeHigh = cMode >> 1;
@ -74,7 +70,7 @@ namespace ARMeilleure.Decoders
size = 0; size = 0;
} }
return new Tuple<long, int>(imm, size); return (imm, size);
} }
public static long VFPExpandImm(long imm, int n) public static long VFPExpandImm(long imm, int n)

View file

@ -635,9 +635,9 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, typeof(OpCode32MemLdEx)); SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, typeof(OpCode32MemLdEx));
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, typeof(OpCode32MemLdEx)); SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, typeof(OpCode32MemLdEx));
SetA32("<<<<00011001xxxxxxxx111010011111", InstName.Ldaex, InstEmit32.Ldaex, typeof(OpCode32MemLdEx)); SetA32("<<<<00011001xxxxxxxx111010011111", InstName.Ldaex, InstEmit32.Ldaex, typeof(OpCode32MemLdEx));
SetA32("<<<<00011101xxxxxxxx111010011111", InstName.Ldaexb,InstEmit32.Ldaexb,typeof(OpCode32MemLdEx)); SetA32("<<<<00011101xxxxxxxx111010011111", InstName.Ldaexb, InstEmit32.Ldaexb, typeof(OpCode32MemLdEx));
SetA32("<<<<00011011xxxxxxxx111010011111", InstName.Ldaexd,InstEmit32.Ldaexd,typeof(OpCode32MemLdEx)); SetA32("<<<<00011011xxxxxxxx111010011111", InstName.Ldaexd, InstEmit32.Ldaexd, typeof(OpCode32MemLdEx));
SetA32("<<<<00011111xxxxxxxx111010011111", InstName.Ldaexh,InstEmit32.Ldaexh,typeof(OpCode32MemLdEx)); SetA32("<<<<00011111xxxxxxxx111010011111", InstName.Ldaexh, InstEmit32.Ldaexh, typeof(OpCode32MemLdEx));
SetA32("<<<<00011111xxxxxxxx110010011111", InstName.Ldah, InstEmit32.Ldah, typeof(OpCode32MemLdEx)); SetA32("<<<<00011111xxxxxxxx110010011111", InstName.Ldah, InstEmit32.Ldah, typeof(OpCode32MemLdEx));
SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult)); SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult));
SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm)); SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm));
@ -647,9 +647,9 @@ namespace ARMeilleure.Decoders
SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8)); SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x0xxxxxxxx00001101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemReg)); SetA32("<<<<000xx0x0xxxxxxxx00001101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemReg));
SetA32("<<<<00011001xxxxxxxx111110011111", InstName.Ldrex, InstEmit32.Ldrex, typeof(OpCode32MemLdEx)); SetA32("<<<<00011001xxxxxxxx111110011111", InstName.Ldrex, InstEmit32.Ldrex, typeof(OpCode32MemLdEx));
SetA32("<<<<00011101xxxxxxxx111110011111", InstName.Ldrexb,InstEmit32.Ldrexb,typeof(OpCode32MemLdEx)); SetA32("<<<<00011101xxxxxxxx111110011111", InstName.Ldrexb, InstEmit32.Ldrexb, typeof(OpCode32MemLdEx));
SetA32("<<<<00011011xxxxxxxx111110011111", InstName.Ldrexd,InstEmit32.Ldrexd,typeof(OpCode32MemLdEx)); SetA32("<<<<00011011xxxxxxxx111110011111", InstName.Ldrexd, InstEmit32.Ldrexd, typeof(OpCode32MemLdEx));
SetA32("<<<<00011111xxxxxxxx111110011111", InstName.Ldrexh,InstEmit32.Ldrexh,typeof(OpCode32MemLdEx)); SetA32("<<<<00011111xxxxxxxx111110011111", InstName.Ldrexh, InstEmit32.Ldrexh, typeof(OpCode32MemLdEx));
SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemImm8)); SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x1xxxxxxxx00001011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemReg)); SetA32("<<<<000xx0x1xxxxxxxx00001011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemReg));
SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemImm8)); SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemImm8));
@ -675,8 +675,8 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0001100xxxxxxxxxxxxxxxx0xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsImm)); SetA32("<<<<0001100xxxxxxxxxxxxxxxx0xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsImm));
SetA32("<<<<0001100xxxxxxxxxxxxx0xx1xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsReg)); SetA32("<<<<0001100xxxxxxxxxxxxx0xx1xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsReg));
SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, typeof(OpCode32AluRsImm)); SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, typeof(OpCode32AluRsImm));
SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32)); //preload hint for cache - nop SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32));
SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32)); //rs imm, but nop SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32));
SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, typeof(OpCode32AluReg)); SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, typeof(OpCode32AluReg));
SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, typeof(OpCode32AluReg)); SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, typeof(OpCode32AluReg));
SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, typeof(OpCode32AluReg)); SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, typeof(OpCode32AluReg));
@ -694,7 +694,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla)); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smlab, InstEmit32.Smlab, typeof(OpCode32AluMla)); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smlab, InstEmit32.Smlab, typeof(OpCode32AluMla));
SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, typeof(OpCode32AluUmull)); SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, typeof(OpCode32AluUmull));
SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlalh,InstEmit32.Smlalh,typeof(OpCode32AluUmull)); SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlalh, InstEmit32.Smlalh, typeof(OpCode32AluUmull));
SetA32("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla)); SetA32("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla));
SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla)); SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla));
SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smulh, InstEmit32.Smulh, typeof(OpCode32AluMla)); SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smulh, InstEmit32.Smulh, typeof(OpCode32AluMla));
@ -702,9 +702,9 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx)); SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx)); SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx)); SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
SetA32("<<<<00011100xxxxxxxx11101001xxxx", InstName.Stlexb,InstEmit32.Stlexb,typeof(OpCode32MemStEx)); SetA32("<<<<00011100xxxxxxxx11101001xxxx", InstName.Stlexb, InstEmit32.Stlexb, typeof(OpCode32MemStEx));
SetA32("<<<<00011010xxxxxxxx11101001xxxx", InstName.Stlexd,InstEmit32.Stlexd,typeof(OpCode32MemStEx)); SetA32("<<<<00011010xxxxxxxx11101001xxxx", InstName.Stlexd, InstEmit32.Stlexd, typeof(OpCode32MemStEx));
SetA32("<<<<00011110xxxxxxxx11101001xxxx", InstName.Stlexh,InstEmit32.Stlexh,typeof(OpCode32MemStEx)); SetA32("<<<<00011110xxxxxxxx11101001xxxx", InstName.Stlexh, InstEmit32.Stlexh, typeof(OpCode32MemStEx));
SetA32("<<<<00011110xxxx111111001001xxxx", InstName.Stlh, InstEmit32.Stlh, typeof(OpCode32MemStEx)); SetA32("<<<<00011110xxxx111111001001xxxx", InstName.Stlh, InstEmit32.Stlh, typeof(OpCode32MemStEx));
SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult)); SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult));
SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm)); SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm));
@ -714,9 +714,9 @@ namespace ARMeilleure.Decoders
SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8)); SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x0xxxxxxxx00001111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemReg)); SetA32("<<<<000xx0x0xxxxxxxx00001111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemReg));
SetA32("<<<<00011000xxxxxxxx11111001xxxx", InstName.Strex, InstEmit32.Strex, typeof(OpCode32MemStEx)); SetA32("<<<<00011000xxxxxxxx11111001xxxx", InstName.Strex, InstEmit32.Strex, typeof(OpCode32MemStEx));
SetA32("<<<<00011100xxxxxxxx11111001xxxx", InstName.Strexb,InstEmit32.Strexb,typeof(OpCode32MemStEx)); SetA32("<<<<00011100xxxxxxxx11111001xxxx", InstName.Strexb, InstEmit32.Strexb, typeof(OpCode32MemStEx));
SetA32("<<<<00011010xxxxxxxx11111001xxxx", InstName.Strexd,InstEmit32.Strexd,typeof(OpCode32MemStEx)); SetA32("<<<<00011010xxxxxxxx11111001xxxx", InstName.Strexd, InstEmit32.Strexd, typeof(OpCode32MemStEx));
SetA32("<<<<00011110xxxxxxxx11111001xxxx", InstName.Strexh,InstEmit32.Strexh,typeof(OpCode32MemStEx)); SetA32("<<<<00011110xxxxxxxx11111001xxxx", InstName.Strexh, InstEmit32.Strexh, typeof(OpCode32MemStEx));
SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8)); SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8));
SetA32("<<<<000xx0x0xxxxxxxx00001011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemReg)); SetA32("<<<<000xx0x0xxxxxxxx00001011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemReg));
SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm)); SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm));
@ -724,7 +724,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000010xxxxxxxxxxxxx0xx1xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsReg)); SetA32("<<<<0000010xxxxxxxxxxxxx0xx1xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsReg));
SetA32("<<<<1111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Svc, InstEmit32.Svc, typeof(OpCode32Exception)); SetA32("<<<<1111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Svc, InstEmit32.Svc, typeof(OpCode32Exception));
SetA32("<<<<01101010xxxxxxxxxx000111xxxx", InstName.Sxtb, InstEmit32.Sxtb, typeof(OpCode32AluUx)); SetA32("<<<<01101010xxxxxxxxxx000111xxxx", InstName.Sxtb, InstEmit32.Sxtb, typeof(OpCode32AluUx));
SetA32("<<<<01101000xxxxxxxxxx000111xxxx", InstName.Sxtb16,InstEmit32.Sxtb16,typeof(OpCode32AluUx)); SetA32("<<<<01101000xxxxxxxxxx000111xxxx", InstName.Sxtb16, InstEmit32.Sxtb16, typeof(OpCode32AluUx));
SetA32("<<<<01101011xxxxxxxxxx000111xxxx", InstName.Sxth, InstEmit32.Sxth, typeof(OpCode32AluUx)); SetA32("<<<<01101011xxxxxxxxxx000111xxxx", InstName.Sxth, InstEmit32.Sxth, typeof(OpCode32AluUx));
SetA32("<<<<00110011xxxx0000xxxxxxxxxxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluImm)); SetA32("<<<<00110011xxxx0000xxxxxxxxxxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluImm));
SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsImm)); SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsImm));
@ -738,7 +738,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull)); SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull)); SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx)); SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16,InstEmit32.Uxtb16,typeof(OpCode32AluUx)); SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx));
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx)); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
// FP & SIMD (AArch32) // FP & SIMD (AArch32)
@ -757,15 +757,15 @@ namespace ARMeilleure.Decoders
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary)); SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary));
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ)); 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("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ)); 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("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ)); 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("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg));
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ)); SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ));
@ -774,11 +774,11 @@ namespace ARMeilleure.Decoders
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS)); SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS));
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS)); SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS));
SetA32("111100111x11xx11xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, typeof(OpCode32SimdCmpZ)); // fp and integer, vector 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("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, typeof(OpCode32SimdS)); // FP 32 and 64, scalar.
SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // fp32 to int SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // FP32 to int.
SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // int to fp32 SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // Int to FP32.
SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // the many fp32 to int encodings (fp) SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // The many FP32 to int encodings (fp).
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS)); SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP)); SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP));
@ -787,20 +787,20 @@ namespace ARMeilleure.Decoders
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt)); SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt));
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle)); SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle));
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 1 SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 1.
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 2 SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 2.
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 3 SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 3.
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); //regs = 4 SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 4.
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemSingle)); SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemSingle));
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); //regs = 1, inc = 1/2 (itype) 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("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemSingle)); 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("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("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", 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("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, typeof(OpCode32SimdRegElem)); SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, typeof(OpCode32SimdRegElem));
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); //d/q vector i32 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("<<<<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("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("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("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q I64.
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, typeof(OpCode32SimdS)); 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("<<<<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("<<<<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("<<<<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("<<<<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("<<<<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("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, typeof(OpCode32SimdSpecial));
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, 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("1111001x0xxxxxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, typeof(OpCode32SimdRegElem)); SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, typeof(OpCode32SimdRegElem));
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); //d/q vector i32 SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); // D/Q vector I32.
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
@ -879,20 +879,20 @@ namespace ARMeilleure.Decoders
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShift)); SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShift));
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemSingle)); SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemSingle));
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 1 SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 1.
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 2 SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 2.
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 3 SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 3.
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); //regs = 4 SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 4.
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemSingle)); SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemSingle));
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); //regs = 1, inc = 1/2 (itype) 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("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemSingle)); 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("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("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", 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); 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) private static Operand EmitReverseBits64Op(ArmEmitterContext context, Operand op)
{ {
Debug.Assert(op.Type == OperandType.I64); Debug.Assert(op.Type == OperandType.I64);
@ -331,23 +314,6 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); 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) public static void Rev32(ArmEmitterContext context)
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
@ -367,7 +333,7 @@ namespace ARMeilleure.Instructions
SetAluDOrZR(context, d); 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); Debug.Assert(op.Type == OperandType.I64);

View file

@ -124,6 +124,7 @@ namespace ARMeilleure.Instructions
EmitAddsCCheck(context, n, res); EmitAddsCCheck(context, n, res);
EmitAddsVCheck(context, n, m, res); EmitAddsVCheck(context, n, m, res);
} }
public static void Eor(ArmEmitterContext context) public static void Eor(ArmEmitterContext context)
{ {
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
@ -365,8 +366,7 @@ namespace ARMeilleure.Instructions
res = context.BitwiseOr( res = context.BitwiseOr(
context.ZeroExtend16(OperandType.I32, low16), 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); EmitAluStore(context, res);
} }
@ -427,7 +427,7 @@ namespace ARMeilleure.Instructions
if (!unsigned) if (!unsigned)
{ {
// If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow). // 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 intMin = Const(int.MinValue);
Operand minus1 = Const(-1); Operand minus1 = Const(-1);
@ -466,7 +466,7 @@ namespace ARMeilleure.Instructions
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp; OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
Operand d = GetIntA32(context, op.Rd); 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)); Operand res = context.BitwiseAnd(d, Const(0x0000ffff));
res = context.BitwiseOr(res, imm); res = context.BitwiseOr(res, imm);
@ -512,7 +512,7 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context); Operand n = GetAluN(context);
Operand m = GetAluM(context); Operand m = GetAluM(context);
Operand res = InstEmit.EmitReverseBits32Op(context, m); Operand res;
bool tbform = op.ShiftType == ShiftType.Asr; bool tbform = op.ShiftType == ShiftType.Asr;
if (tbform) if (tbform)
@ -531,7 +531,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetAluM(context); Operand m = GetAluM(context);
Operand res = InstEmit.EmitReverseBits32Op(context, m); Operand res = EmitReverseBits32Op(context, m);
EmitAluStore(context, res); EmitAluStore(context, res);
} }
@ -549,7 +549,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetAluM(context); Operand m = GetAluM(context);
Operand res = InstEmit.EmitReverseBytes16_32Op(context, m); Operand res = EmitReverseBytes16_32Op(context, m);
EmitAluStore(context, res); EmitAluStore(context, res);
} }
@ -558,7 +558,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetAluM(context); Operand m = GetAluM(context);
Operand res = InstEmit.EmitReverseBytes16_32Op(context, m); Operand res = EmitReverseBytes16_32Op(context, m);
EmitAluStore(context, context.SignExtend16(OperandType.I32, res)); EmitAluStore(context, context.SignExtend16(OperandType.I32, res));
} }
@ -591,7 +591,7 @@ namespace ARMeilleure.Instructions
{ {
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp; 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 n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightUI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); 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; 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 n = GetIntA32(context, op.Rn);
Operand res = context.ShiftRightSI(context.ShiftLeft(n, Const(31 - msb)), Const(31 - op.Msb)); 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) private static void EmitAluStore(ArmEmitterContext context, Operand value)
{ {
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
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);
}
} }
} }
} }

View file

@ -3,7 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -77,6 +77,83 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.VFlag, vOut); 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) 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) public static Operand EmitLslC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero)
{ {
Operand shiftLarge = context.ICompareGreaterOrEqual(shift, Const(32)); Operand shiftLarge = context.ICompareGreaterOrEqual(shift, Const(32));
Operand result = context.ShiftLeft(m, shift); Operand result = context.ShiftLeft(m, shift);
if (setCarry) if (setCarry)
{ {

View file

@ -76,7 +76,7 @@ namespace ARMeilleure.Instructions
Operand addr = GetIntA32(context, op.Rm); Operand addr = GetIntA32(context, op.Rm);
Operand bitOne = context.BitwiseAnd(addr, Const(1)); 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); bool isThumb = IsThumb(context.CurrOp);
@ -88,11 +88,7 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.TFlag, bitOne); SetFlag(context, PState.TFlag, bitOne);
context.Return(addr); // call context.Return(addr); // Call.
}
public static void Nop(ArmEmitterContext context)
{
} }
} }
} }

View file

@ -36,6 +36,7 @@ namespace ARMeilleure.Instructions
{ {
EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive); EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
} }
public static void Lda(ArmEmitterContext context) public static void Lda(ArmEmitterContext context)
{ {
EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Ordered); EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
@ -71,7 +72,7 @@ namespace ARMeilleure.Instructions
EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered); EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
} }
// stores // Stores.
public static void Strex(ArmEmitterContext context) public static void Strex(ArmEmitterContext context)
{ {
@ -149,7 +150,7 @@ namespace ARMeilleure.Instructions
{ {
if (size == DWordSizeLog2) 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. // for the registers.
Operand value = EmitExLoad(context, address, exclusive, size); Operand value = EmitExLoad(context, address, exclusive, size);
@ -184,15 +185,12 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
Operand s = null;
if (size == DWordSizeLog2) 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 lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1)); Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
Operand toStore = Local(OperandType.I64);
Operand lblBigEndian = Label(); Operand lblBigEndian = Label();
Operand lblEnd = Label(); Operand lblEnd = Label();
@ -215,8 +213,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
Operand s = EmitExStore(context, address, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)), exclusive, size);
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 // This is only needed for exclusive stores. The function returns 0
// when the store is successful, and 1 otherwise. // when the store is successful, and 1 otherwise.
if (exclusive) SetIntA32(context, op.Rd, s); if (exclusive) SetIntA32(context, op.Rd, s);

View file

@ -511,7 +511,6 @@ namespace ARMeilleure.Instructions
{ {
switch (context.CurrOp) switch (context.CurrOp)
{ {
// ARM32.
case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry); case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case OpCode32MemReg op: return GetIntA32(context, op.Rm); case OpCode32MemReg op: return GetIntA32(context, op.Rm);

View file

@ -71,8 +71,8 @@ namespace ARMeilleure.Instructions
EmitNZFlagsCheck(context, res); EmitNZFlagsCheck(context, res);
} }
EmitGenericStore(context, op.RdHi, op.SetFlags, hi); EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericStore(context, op.RdLo, op.SetFlags, lo); EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
} }
public static void Smull(ArmEmitterContext context) public static void Smull(ArmEmitterContext context)
@ -92,8 +92,8 @@ namespace ARMeilleure.Instructions
EmitNZFlagsCheck(context, res); EmitNZFlagsCheck(context, res);
} }
EmitGenericStore(context, op.RdHi, op.SetFlags, hi); EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericStore(context, op.RdLo, op.SetFlags, lo); EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
} }
public static void Smmla(ArmEmitterContext context) public static void Smmla(ArmEmitterContext context)
@ -136,10 +136,9 @@ namespace ARMeilleure.Instructions
Operand hi = context.ConvertI64ToI32(context.ShiftRightSI(res, Const(32))); 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) public static void Smlab(ArmEmitterContext context)
{ {
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp; OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
@ -170,9 +169,9 @@ namespace ARMeilleure.Instructions
Operand a = GetIntA32(context, op.Ra); Operand a = GetIntA32(context, op.Ra);
res = context.Add(res, a); 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) public static void Smlal(ArmEmitterContext context)
@ -217,8 +216,8 @@ namespace ARMeilleure.Instructions
EmitNZFlagsCheck(context, res); EmitNZFlagsCheck(context, res);
} }
EmitGenericStore(context, op.RdHi, op.SetFlags, hi); EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericStore(context, op.RdLo, op.SetFlags, lo); EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
} }
public static void Smlalh(ArmEmitterContext context) public static void Smlalh(ArmEmitterContext context)
@ -255,8 +254,8 @@ namespace ARMeilleure.Instructions
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32))); Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res); Operand lo = context.ConvertI64ToI32(res);
EmitGenericStore(context, op.RdHi, false, hi); EmitGenericAluStoreA32(context, op.RdHi, false, hi);
EmitGenericStore(context, op.RdLo, false, lo); EmitGenericAluStoreA32(context, op.RdLo, false, lo);
} }
public static void Smulh(ArmEmitterContext context) public static void Smulh(ArmEmitterContext context)
@ -286,37 +285,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Multiply(n, m); Operand res = context.Multiply(n, m);
EmitGenericStore(context, op.Rd, false, res); EmitGenericAluStoreA32(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);
}
} }
} }
} }

View file

@ -21,6 +21,7 @@ namespace ARMeilleure.Instructions
public static void Vabs_V(ArmEmitterContext context) public static void Vabs_V(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1)); EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1));
@ -73,7 +74,7 @@ namespace ARMeilleure.Instructions
Operand insert = GetIntA32(context, op.Rt); 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) switch (op.Size)
{ {
case 2: case 2:
@ -86,7 +87,7 @@ namespace ARMeilleure.Instructions
insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)); insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u));
break; break;
default: default:
throw new Exception("Unknown Vdup Size!"); throw new ArgumentOutOfRangeException("Unknown Vdup Size!");
} }
InsertScalar(context, op.Vd, insert); 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); 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) switch (op.Size)
{ {
case 2: case 2:
@ -115,7 +116,7 @@ namespace ARMeilleure.Instructions
insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)); insert = context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u));
break; break;
default: default:
throw new Exception("Unknown Vdup Size!"); throw new ArgumentOutOfRangeException("Unknown Vdup Size!");
} }
InsertScalar(context, op.Vd, insert); InsertScalar(context, op.Vd, insert);
@ -124,6 +125,7 @@ namespace ARMeilleure.Instructions
InsertScalar(context, op.Vd | 1, insert); InsertScalar(context, op.Vd | 1, insert);
} }
} }
public static void Vext(ArmEmitterContext context) public static void Vext(ArmEmitterContext context)
{ {
OpCode32SimdExt op = (OpCode32SimdExt)context.CurrOp; OpCode32SimdExt op = (OpCode32SimdExt)context.CurrOp;
@ -244,7 +246,7 @@ namespace ARMeilleure.Instructions
public static void VmaxminNm_V(ArmEmitterContext context) public static void VmaxminNm_V(ArmEmitterContext context)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; 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); _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); _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) public static void Vmul_1(ArmEmitterContext context)
{ {
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
if (op.F) if (op.F)
{ {
if (Optimizations.FastFP) if (Optimizations.FastFP)
@ -390,6 +393,7 @@ namespace ARMeilleure.Instructions
public static void Vmla_1(ArmEmitterContext context) public static void Vmla_1(ArmEmitterContext context)
{ {
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
if (op.F) if (op.F)
{ {
if (Optimizations.FastFP) if (Optimizations.FastFP)
@ -448,6 +452,7 @@ namespace ARMeilleure.Instructions
public static void Vmls_1(ArmEmitterContext context) public static void Vmls_1(ArmEmitterContext context)
{ {
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;
if (op.F) if (op.F)
{ {
if (Optimizations.FastFP) if (Optimizations.FastFP)
@ -479,17 +484,18 @@ namespace ARMeilleure.Instructions
public static void Vrev(ArmEmitterContext context) public static void Vrev(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorUnaryOpZx32(context, (op1) => EmitVectorUnaryOpZx32(context, (op1) =>
{ {
switch (op.Opc) switch (op.Opc)
{ {
case 0: case 0:
switch (op.Size) //swap bytes switch (op.Size) // Swap bytes.
{ {
default: default:
return op1; return op1;
case 1: case 1:
return InstEmit.EmitReverseBytes16_32Op(context, op1); return InstEmitAluHelper.EmitReverseBytes16_32Op(context, op1);
case 2: case 2:
case 3: case 3:
return context.ByteSwap(op1); return context.ByteSwap(op1);
@ -511,7 +517,7 @@ namespace ARMeilleure.Instructions
); );
} }
case 2: case 2:
//swap upper and lower // Swap upper and lower halves.
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffffffff00000000ul)), Const(32)), return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffffffff00000000ul)), Const(32)),
context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000fffffffful)), Const(32))); context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000fffffffful)), Const(32)));
@ -523,6 +529,7 @@ namespace ARMeilleure.Instructions
public static void Vrecpe(ArmEmitterContext context) public static void Vrecpe(ArmEmitterContext context)
{ {
OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp; OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitVectorUnaryOpF32(context, (op1) =>
@ -547,6 +554,7 @@ namespace ARMeilleure.Instructions
public static void Vrsqrte(ArmEmitterContext context) public static void Vrsqrte(ArmEmitterContext context)
{ {
OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp; OpCode32SimdSqrte op = (OpCode32SimdSqrte)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitVectorUnaryOpF32(context, (op1) =>
@ -569,7 +577,8 @@ namespace ARMeilleure.Instructions
public static void Vsel(ArmEmitterContext context) public static void Vsel(ArmEmitterContext context)
{ {
var op = (OpCode32SimdSel)context.CurrOp; OpCode32SimdSel op = (OpCode32SimdSel)context.CurrOp;
Operand condition = null; Operand condition = null;
switch (op.Cc) switch (op.Cc)
{ {

View file

@ -22,13 +22,13 @@ namespace ARMeilleure.Instructions
public static void Vceq_I(ArmEmitterContext context) public static void Vceq_I(ArmEmitterContext context)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, false, false); EmitCmpOpI32(context, context.ICompareEqual, context.ICompareEqual, false, false);
} }
public static void Vceq_Z(ArmEmitterContext context) public static void Vceq_Z(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitCmpOpF32(context, SoftFloat32.FPCompareEQFpscr, SoftFloat64.FPCompareEQFpscr, true); EmitCmpOpF32(context, SoftFloat32.FPCompareEQFpscr, SoftFloat64.FPCompareEQFpscr, true);
@ -47,12 +47,14 @@ namespace ARMeilleure.Instructions
public static void Vcge_I(ArmEmitterContext context) public static void Vcge_I(ArmEmitterContext context)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, false, !op.U); EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, false, !op.U);
} }
public static void Vcge_Z(ArmEmitterContext context) public static void Vcge_Z(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitCmpOpF32(context, SoftFloat32.FPCompareGEFpscr, SoftFloat64.FPCompareGEFpscr, true); EmitCmpOpF32(context, SoftFloat32.FPCompareGEFpscr, SoftFloat64.FPCompareGEFpscr, true);
@ -71,12 +73,14 @@ namespace ARMeilleure.Instructions
public static void Vcgt_I(ArmEmitterContext context) public static void Vcgt_I(ArmEmitterContext context)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, false, !op.U); EmitCmpOpI32(context, context.ICompareGreater, context.ICompareGreaterUI, false, !op.U);
} }
public static void Vcgt_Z(ArmEmitterContext context) public static void Vcgt_Z(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitCmpOpF32(context, SoftFloat32.FPCompareGTFpscr, SoftFloat64.FPCompareGTFpscr, true); EmitCmpOpF32(context, SoftFloat32.FPCompareGTFpscr, SoftFloat64.FPCompareGTFpscr, true);
@ -90,6 +94,7 @@ namespace ARMeilleure.Instructions
public static void Vcle_Z(ArmEmitterContext context) public static void Vcle_Z(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitCmpOpF32(context, SoftFloat32.FPCompareLEFpscr, SoftFloat64.FPCompareLEFpscr, true); EmitCmpOpF32(context, SoftFloat32.FPCompareLEFpscr, SoftFloat64.FPCompareLEFpscr, true);
@ -103,6 +108,7 @@ namespace ARMeilleure.Instructions
public static void Vclt_Z(ArmEmitterContext context) public static void Vclt_Z(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
if (op.F) if (op.F)
{ {
EmitCmpOpF32(context, SoftFloat32.FPCompareLTFpscr, SoftFloat64.FPCompareLTFpscr, true); EmitCmpOpF32(context, SoftFloat32.FPCompareLTFpscr, SoftFloat64.FPCompareLTFpscr, true);
@ -126,8 +132,14 @@ namespace ARMeilleure.Instructions
{ {
OperandType type = m.Type; OperandType type = m.Type;
if (type == OperandType.FP64) return context.Call(f64, m, new Operand(0.0), one); if (type == OperandType.FP64)
else return context.Call(f32, m, new Operand(0.0), one); {
return context.Call(f64, m, new Operand(0.0), one);
}
else
{
return context.Call(f32, m, new Operand(0.0f), one);
}
}); });
} }
else else
@ -136,8 +148,14 @@ namespace ARMeilleure.Instructions
{ {
OperandType type = n.Type; OperandType type = n.Type;
if (type == OperandType.FP64) return context.Call(f64, n, m, one); if (type == OperandType.FP64)
else return context.Call(f32, n, m, one); {
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) if (lowBit)
{ {
//move the low bit to the top // Move the low bit to the top.
return ((vd & 0x1) << 4) | (vd >> 1); return ((vd & 0x1) << 4) | (vd >> 1);
} }
else else
{ {
//move the high bit to the bottom // Move the high bit to the bottom.
return ((vd & 0xf) << 1) | (vd >> 4); return ((vd & 0xf) << 1) | (vd >> 4);
} }
} }
@ -30,11 +30,12 @@ namespace ARMeilleure.Instructions
public static void Vcvt_V(ArmEmitterContext context) public static void Vcvt_V(ArmEmitterContext context)
{ {
OpCode32Simd op = (OpCode32Simd)context.CurrOp; OpCode32Simd op = (OpCode32Simd)context.CurrOp;
bool unsigned = (op.Opc & 1) != 0; bool unsigned = (op.Opc & 1) != 0;
bool toInteger = (op.Opc & 2) != 0; bool toInteger = (op.Opc & 2) != 0;
OperandType floatSize = (op.Size == 2) ? OperandType.FP32 : OperandType.FP64; 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) if (toInteger)
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitVectorUnaryOpF32(context, (op1) =>
@ -87,7 +88,7 @@ namespace ARMeilleure.Instructions
if (op.Size == 3) if (op.Size == 3)
{ {
vd = FlipVdBits(op.Vd, false); vd = FlipVdBits(op.Vd, false);
// double to single // Double to single.
Operand fp = ExtractScalar(context, OperandType.FP64, vm); Operand fp = ExtractScalar(context, OperandType.FP64, vm);
Operand res = context.ConvertToFP(OperandType.FP32, fp); Operand res = context.ConvertToFP(OperandType.FP32, fp);
@ -97,7 +98,7 @@ namespace ARMeilleure.Instructions
else else
{ {
vd = FlipVdBits(op.Vd, true); vd = FlipVdBits(op.Vd, true);
// single to double // Single to double.
Operand fp = ExtractScalar(context, OperandType.FP32, vm); Operand fp = ExtractScalar(context, OperandType.FP32, vm);
Operand res = context.ConvertToFP(OperandType.FP64, fp); Operand res = context.ConvertToFP(OperandType.FP64, fp);
@ -123,10 +124,10 @@ namespace ARMeilleure.Instructions
Operand asInteger; Operand asInteger;
// TODO: Fast Path // TODO: Fast Path.
if (roundWithFpscr) 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 (floatSize == OperandType.FP64)
{ {
if (unsigned) if (unsigned)
@ -154,7 +155,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
// round towards zero // Round towards zero.
if (floatSize == OperandType.FP64) if (floatSize == OperandType.FP64)
{ {
if (unsigned) if (unsigned)
@ -236,16 +237,16 @@ namespace ARMeilleure.Instructions
switch (op.Opc2) switch (op.Opc2)
{ {
case 0b00: //away case 0b00: // Away
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
break; break;
case 0b01: //nearest case 0b01: // Nearest
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break; break;
case 0b10: //+infinity case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert); toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
break; break;
case 0b11: //negative case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert); toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
break; break;
} }
@ -262,7 +263,6 @@ namespace ARMeilleure.Instructions
{ {
asInteger = context.Call(new _S32_F64(CastDoubleToInt32), toConvert); asInteger = context.Call(new _S32_F64(CastDoubleToInt32), toConvert);
} }
} }
else else
{ {
@ -279,7 +279,6 @@ namespace ARMeilleure.Instructions
InsertScalar(context, op.Vd, asInteger); InsertScalar(context, op.Vd, asInteger);
} }
public static void Vrint_RM(ArmEmitterContext context) public static void Vrint_RM(ArmEmitterContext context)
{ {
OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp; OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp;
@ -290,16 +289,16 @@ namespace ARMeilleure.Instructions
switch (op.Opc2) switch (op.Opc2)
{ {
case 0b00: //away case 0b00: // Away
toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.AwayFromZero, toConvert);
break; break;
case 0b01: //nearest case 0b01: // Nearest
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break; break;
case 0b10: //+infinity case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert); toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
break; break;
case 0b11: //negative case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert); toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
break; break;
} }
@ -321,10 +320,12 @@ namespace ARMeilleure.Instructions
{ {
return (uint)value; return (uint)value;
} }
private static int CastFloatToInt32(float value) private static int CastFloatToInt32(float value)
{ {
return (int)value; return (int)value;
} }
private static uint CastFloatToUInt32(float value) private static uint CastFloatToUInt32(float value)
{ {
return (uint)value; return (uint)value;

View file

@ -28,19 +28,19 @@ namespace ARMeilleure.Instructions
return (index >> 2, index & 3); 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) public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg)
{ {
if (type == OperandType.FP64 || type == OperandType.I64) if (type == OperandType.FP64 || type == OperandType.I64)
{ {
// from dreg // From dreg.
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1); return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
} }
else else
{ {
// from sreg // From sreg.
return context.VectorExtract(type, GetVecA32(reg >> 2), reg & 3); return context.VectorExtract(type, GetVecA32(reg >> 2), reg & 3);
} }
} }
@ -50,14 +50,14 @@ namespace ARMeilleure.Instructions
Operand vec, insert; Operand vec, insert;
if (value.Type == OperandType.FP64 || value.Type == OperandType.I64) if (value.Type == OperandType.FP64 || value.Type == OperandType.I64)
{ {
// from dreg // From dreg.
vec = GetVecA32(reg >> 1); vec = GetVecA32(reg >> 1);
insert = context.VectorInsert(vec, value, reg & 1); insert = context.VectorInsert(vec, value, reg & 1);
} }
else else
{ {
// from sreg // From sreg.
vec = GetVecA32(reg >> 2); vec = GetVecA32(reg >> 2);
insert = context.VectorInsert(vec, value, reg & 3); insert = context.VectorInsert(vec, value, reg & 3);
} }
@ -203,7 +203,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res); context.Copy(GetVecA32(op.Qd), res);
} }
// INTEGER // Integer
public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed) public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed)
{ {
@ -292,7 +292,7 @@ namespace ARMeilleure.Instructions
EmitVectorTernaryOpI32(context, emit, false); EmitVectorTernaryOpI32(context, emit, false);
} }
// VEC BY SCALAR // Vector by scalar
public static void EmitVectorByScalarOpF32(ArmEmitterContext context, Func2I emit) public static void EmitVectorByScalarOpF32(ArmEmitterContext context, Func2I emit)
{ {
@ -323,7 +323,6 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; 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 m = EmitVectorExtract32(context, op.Vm >> (4 - op.Size), op.Vm & ((1 << (4 - op.Size)) - 1), op.Size, signed);
Operand res = GetVecA32(op.Qd); Operand res = GetVecA32(op.Qd);
@ -347,7 +346,6 @@ namespace ARMeilleure.Instructions
int sizeF = op.Size & 1; int sizeF = op.Size & 1;
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; 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; int elems = op.GetBytesCount() >> sizeF + 2;
@ -370,7 +368,6 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; 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 m = EmitVectorExtract32(context, op.Vm >> (4 - op.Size), op.Vm & ((1 << (4 - op.Size)) - 1), op.Size, signed);
Operand res = GetVecA32(op.Qd); Operand res = GetVecA32(op.Qd);
@ -388,16 +385,12 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res); context.Copy(GetVecA32(op.Qd), res);
} }
// PAIRWISE // Pairwise
public static void EmitVectorPairwiseOpF32(ArmEmitterContext context, Func2I emit) public static void EmitVectorPairwiseOpF32(ArmEmitterContext context, Func2I emit)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.Q)
{
throw new Exception("Q mode not supported for pairwise");
}
int sizeF = op.Size & 1; int sizeF = op.Size & 1;
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
@ -431,11 +424,6 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.Q)
{
throw new Exception("Q mode not supported for pairwise");
}
int elems = op.GetBytesCount() >> op.Size; int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1; int pairs = elems >> 1;
@ -561,6 +549,5 @@ namespace ARMeilleure.Instructions
return res; return res;
} }
} }
} }

View file

@ -1,16 +1,9 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System;
using System.Collections.Generic;
using System.Text;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32; using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
using System.Diagnostics;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {

View file

@ -16,14 +16,17 @@ namespace ARMeilleure.Instructions
{ {
EmitVStoreOrLoadN(context, 1, false); EmitVStoreOrLoadN(context, 1, false);
} }
public static void Vst2(ArmEmitterContext context) public static void Vst2(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 2, false); EmitVStoreOrLoadN(context, 2, false);
} }
public static void Vst3(ArmEmitterContext context) public static void Vst3(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 3, false); EmitVStoreOrLoadN(context, 3, false);
} }
public static void Vst4(ArmEmitterContext context) public static void Vst4(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 4, false); EmitVStoreOrLoadN(context, 4, false);
@ -33,14 +36,17 @@ namespace ARMeilleure.Instructions
{ {
EmitVStoreOrLoadN(context, 1, true); EmitVStoreOrLoadN(context, 1, true);
} }
public static void Vld2(ArmEmitterContext context) public static void Vld2(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 2, true); EmitVStoreOrLoadN(context, 2, true);
} }
public static void Vld3(ArmEmitterContext context) public static void Vld3(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 3, true); EmitVStoreOrLoadN(context, 3, true);
} }
public static void Vld4(ArmEmitterContext context) public static void Vld4(ArmEmitterContext context)
{ {
EmitVStoreOrLoadN(context, 4, true); EmitVStoreOrLoadN(context, 4, true);
@ -52,18 +58,17 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdMemSingle op = (OpCode32SimdMemSingle)context.CurrOp; OpCode32SimdMemSingle op = (OpCode32SimdMemSingle)context.CurrOp;
if (op.Replicate && !load) throw new Exception("Replicate+Store is undefined for STn");
int eBytes = 1 << op.Size; int eBytes = 1 << op.Size;
Operand n = context.Copy(GetIntA32(context, op.Rn)); Operand n = context.Copy(GetIntA32(context, op.Rn));
//check alignment (?) // TODO: Check alignment.
int offset = 0; int offset = 0;
int d = op.Vd; 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)); Operand address = context.Add(n, Const(offset));
if (eBytes == 8) if (eBytes == 8)
{ {
@ -140,8 +145,8 @@ namespace ARMeilleure.Instructions
int elemD = d + reg; int elemD = d + reg;
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
// add ebytes for each element // add ebytes for each element.
Operand address = context.Add(n, Const(offset)); Operand address = context.Add(n, Const(offset));
int index = ((elemD & 1) << (3 - op.Size)) + elem; int index = ((elemD & 1) << (3 - op.Size)) + elem;
if (eBytes == 8) if (eBytes == 8)
@ -324,7 +329,6 @@ namespace ARMeilleure.Instructions
if ((accType & AccessType.Load) != 0) if ((accType & AccessType.Load) != 0)
{ {
if (size == DWordSizeLog2) if (size == DWordSizeLog2)
{ {
EmitDVectorLoad(context, address, op.Vd); EmitDVectorLoad(context, address, op.Vd);

View file

@ -2,7 +2,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Collections.Generic;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
@ -26,16 +25,17 @@ namespace ARMeilleure.Instructions
public static void Vmov_GS(ArmEmitterContext context) public static void Vmov_GS(ArmEmitterContext context)
{ {
OpCode32SimdMovGp op = (OpCode32SimdMovGp)context.CurrOp; OpCode32SimdMovGp op = (OpCode32SimdMovGp)context.CurrOp;
Operand vec = GetVecA32(op.Vn >> 2); Operand vec = GetVecA32(op.Vn >> 2);
if (op.Op == 1) if (op.Op == 1)
{ {
// to general purpose // To general purpose.
Operand value = context.VectorExtract(OperandType.I32, vec, op.Vn & 0x3); Operand value = context.VectorExtract(OperandType.I32, vec, op.Vn & 0x3);
SetIntA32(context, op.Rt, value); SetIntA32(context, op.Rt, value);
} }
else else
{ {
// from general purpose // From general purpose.
Operand value = GetIntA32(context, op.Rt); Operand value = GetIntA32(context, op.Rt);
context.Copy(vec, context.VectorInsert(vec, value, op.Vn & 0x3)); context.Copy(vec, context.VectorInsert(vec, value, op.Vn & 0x3));
} }
@ -44,16 +44,17 @@ namespace ARMeilleure.Instructions
public static void Vmov_G1(ArmEmitterContext context) public static void Vmov_G1(ArmEmitterContext context)
{ {
OpCode32SimdMovGpElem op = (OpCode32SimdMovGpElem)context.CurrOp; OpCode32SimdMovGpElem op = (OpCode32SimdMovGpElem)context.CurrOp;
int index = op.Index + ((op.Vd & 1) << (3 - op.Size)); int index = op.Index + ((op.Vd & 1) << (3 - op.Size));
if (op.Op == 1) if (op.Op == 1)
{ {
// to general purpose // To general purpose.
Operand value = EmitVectorExtract32(context, op.Vd >> 1, index, op.Size, !op.U); Operand value = EmitVectorExtract32(context, op.Vd >> 1, index, op.Size, !op.U);
SetIntA32(context, op.Rt, value); SetIntA32(context, op.Rt, value);
} }
else else
{ {
// from general purpose // From general purpose.
Operand vec = GetVecA32(op.Vd >> 1); Operand vec = GetVecA32(op.Vd >> 1);
Operand value = GetIntA32(context, op.Rt); Operand value = GetIntA32(context, op.Rt);
context.Copy(vec, EmitVectorInsert(context, vec, value, index, op.Size)); context.Copy(vec, EmitVectorInsert(context, vec, value, index, op.Size));
@ -63,13 +64,14 @@ namespace ARMeilleure.Instructions
public static void Vmov_G2(ArmEmitterContext context) public static void Vmov_G2(ArmEmitterContext context)
{ {
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp; OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
Operand vec = GetVecA32(op.Vm >> 2); Operand vec = GetVecA32(op.Vm >> 2);
int vm1 = (op.Vm + 1); int vm1 = (op.Vm + 1);
bool sameOwnerVec = (op.Vm >> 2) == (vm1 >> 2); bool sameOwnerVec = (op.Vm >> 2) == (vm1 >> 2);
Operand vec2 = sameOwnerVec ? vec : GetVecA32(vm1 >> 2); Operand vec2 = sameOwnerVec ? vec : GetVecA32(vm1 >> 2);
if (op.Op == 1) if (op.Op == 1)
{ {
// to general purpose // To general purpose.
Operand lowValue = context.VectorExtract(OperandType.I32, vec, op.Vm & 3); Operand lowValue = context.VectorExtract(OperandType.I32, vec, op.Vm & 3);
SetIntA32(context, op.Rt, lowValue); SetIntA32(context, op.Rt, lowValue);
@ -78,7 +80,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
// from general purpose // From general purpose.
Operand lowValue = GetIntA32(context, op.Rt); Operand lowValue = GetIntA32(context, op.Rt);
Operand resultVec = context.VectorInsert(vec, lowValue, op.Vm & 3); Operand resultVec = context.VectorInsert(vec, lowValue, op.Vm & 3);
@ -93,31 +95,30 @@ namespace ARMeilleure.Instructions
context.Copy(vec, resultVec); context.Copy(vec, resultVec);
context.Copy(vec2, context.VectorInsert(vec2, highValue, vm1 & 3)); context.Copy(vec2, context.VectorInsert(vec2, highValue, vm1 & 3));
} }
} }
} }
public static void Vmov_GD(ArmEmitterContext context) public static void Vmov_GD(ArmEmitterContext context)
{ {
OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp; OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;
Operand vec = GetVecA32(op.Vm >> 1); Operand vec = GetVecA32(op.Vm >> 1);
if (op.Op == 1) if (op.Op == 1)
{ {
// to general purpose // To general purpose.
Operand value = context.VectorExtract(OperandType.I64, vec, op.Vm & 1); Operand value = context.VectorExtract(OperandType.I64, vec, op.Vm & 1);
SetIntA32(context, op.Rt, context.ConvertI64ToI32(value)); SetIntA32(context, op.Rt, context.ConvertI64ToI32(value));
SetIntA32(context, op.Rt2, context.ConvertI64ToI32(context.ShiftRightUI(value, Const(32)))); SetIntA32(context, op.Rt2, context.ConvertI64ToI32(context.ShiftRightUI(value, Const(32))));
} }
else else
{ {
// from general purpose // From general purpose.
Operand lowValue = GetIntA32(context, op.Rt); Operand lowValue = GetIntA32(context, op.Rt);
Operand highValue = GetIntA32(context, op.Rt2); Operand highValue = GetIntA32(context, op.Rt2);
Operand value = context.BitwiseOr( Operand value = context.BitwiseOr(
context.ZeroExtend32(OperandType.I64, lowValue), 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)); context.Copy(vec, context.VectorInsert(vec, value, op.Vm & 1));
} }
@ -133,11 +134,11 @@ namespace ARMeilleure.Instructions
int length = op.Length + 1; 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++) for (int i=0; i< length; i++)
{ {
(int vn, int en) = GetQuadwordAndSubindex(op.Vn + i, op.RegisterSize); (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; int byteLength = length * 8;
@ -151,41 +152,39 @@ namespace ARMeilleure.Instructions
Operand end = Label(); Operand end = Label();
Operand inRange = context.ICompareLess(selectedIndex, Const(byteLength)); 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 // TODO: Branching rather than conditional select.
// granted that is slower
// --- context.BranchIfFalse(end, inRange); ---
// get indexed byte // 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 // 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 // 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)); 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)); 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]; (int qx, int ix) = tableTuples[i];
// get the whole vector, we'll get a byte out of it // Get the whole vector, we'll get a byte out of it.
Operand lookupResult; Operand lookupResult;
if (vectorLocation.Item1 == op.Qd) if (qx == op.Qd)
{ {
// result contains the current state of the vector // Result contains the current state of the vector.
lookupResult = context.VectorExtract(OperandType.I64, res, vectorLocation.Item2); lookupResult = context.VectorExtract(OperandType.I64, res, ix);
} }
else 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) if (i == 0)
{ {
elemRes = lookupResult; //first result is always default elemRes = lookupResult; // First result is always default.
} }
else else
{ {

View file

@ -15,12 +15,14 @@ namespace ARMeilleure.Instructions
public static void Vshl(ArmEmitterContext context) public static void Vshl(ArmEmitterContext context)
{ {
OpCode32SimdShift op = (OpCode32SimdShift)context.CurrOp; OpCode32SimdShift op = (OpCode32SimdShift)context.CurrOp;
EmitVectorUnaryOpZx32(context, (op1) => context.ShiftLeft(op1, Const(op1.Type, op.Shift))); EmitVectorUnaryOpZx32(context, (op1) => context.ShiftLeft(op1, Const(op1.Type, op.Shift)));
} }
public static void Vshl_I(ArmEmitterContext context) public static void Vshl_I(ArmEmitterContext context)
{ {
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.U) if (op.U)
{ {
EmitVectorBinaryOpZx32(context, (op1, op2) => EmitShlRegOp(context, op2, op1, op.Size, true)); 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 isOutOfRange0 = context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size));
Operand isOutOfRangeN = context.ICompareGreaterOrEqual(negShiftLsB, 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)))); isOutOfRange0 = context.BitwiseOr(isOutOfRange0, context.BitwiseAnd(isOutOfRangeN, context.ICompareGreaterOrEqual(op, Const(op.Type, 0))));
Operand min = (op.Type == OperandType.I64) ? Const(-1L) : Const(-1); 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)); 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) 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.VFlag, GetFpFlag(FPState.VFlag));
SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag)); SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag)); SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
@ -29,17 +29,17 @@ namespace ARMeilleure.Instructions
Delegate dlg; Delegate dlg;
switch (op.Sreg) switch (op.Sreg)
{ {
case 0b0000: //FPSID case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
case 0b0001: //FPSCR case 0b0001: // FPSCR
dlg = new _U32(NativeInterface.GetFpscr); break; dlg = new _U32(NativeInterface.GetFpscr); break;
case 0b0101: //MVFR2 case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2"); throw new NotImplementedException("MVFR2");
case 0b0110: //MVFR1 case 0b0110: // MVFR1
throw new NotImplementedException("MVFR1"); throw new NotImplementedException("MVFR1");
case 0b0111: //MVFR0 case 0b0111: // MVFR0
throw new NotImplementedException("MVFR0"); throw new NotImplementedException("MVFR0");
case 0b1000: //FPEXC case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
default: throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); 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) public static void Vmsr(ArmEmitterContext context)
{ {
var op = (OpCode32SimdSpecial)context.CurrOp; OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
Delegate dlg; Delegate dlg;
switch (op.Sreg) switch (op.Sreg)
{ {
case 0b0000: //FPSID case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
case 0b0001: //FPSCR case 0b0001: // FPSCR
dlg = new _Void_U32(NativeInterface.SetFpscr); break; dlg = new _Void_U32(NativeInterface.SetFpscr); break;
case 0b0101: //MVFR2 case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2"); throw new NotImplementedException("MVFR2");
case 0b0110: //MVFR1 case 0b0110: // MVFR1
throw new NotImplementedException("MVFR1"); throw new NotImplementedException("MVFR1");
case 0b0111: //MVFR0 case 0b0111: // MVFR0
throw new NotImplementedException("MVFR0"); throw new NotImplementedException("MVFR0");
case 0b1000: //FPEXC case 0b1000: // FPEXC
throw new NotImplementedException("Supervisor Only"); throw new NotImplementedException("Supervisor Only");
default: throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); 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) public static void Mrc(ArmEmitterContext context)
{ {
var op = (OpCode32System)context.CurrOp; OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15) if (op.Coproc != 15)
{ {
@ -89,7 +89,7 @@ namespace ARMeilleure.Instructions
Delegate dlg; Delegate dlg;
switch (op.CRn) switch (op.CRn)
{ {
case 13: // Process and Thread Info case 13: // Process and Thread Info.
if (op.CRm != 0) if (op.CRm != 0)
{ {
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); 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}."); 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)); EmitSetNzcv(context, context.Call(dlg));
return; return;
} }
@ -121,7 +121,7 @@ namespace ARMeilleure.Instructions
public static void Mcr(ArmEmitterContext context) public static void Mcr(ArmEmitterContext context)
{ {
var op = (OpCode32System)context.CurrOp; OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15) if (op.Coproc != 15)
{ {
@ -136,7 +136,7 @@ namespace ARMeilleure.Instructions
Delegate dlg; Delegate dlg;
switch (op.CRn) switch (op.CRn)
{ {
case 13: // Process and Thread Info case 13: // Process and Thread Info.
if (op.CRm != 0) if (op.CRm != 0)
{ {
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
@ -151,13 +151,13 @@ namespace ARMeilleure.Instructions
break; break;
case 7: case 7:
switch (op.CRm) // Cache and Memory barrier switch (op.CRm) // Cache and Memory barrier.
{ {
case 10: case 10:
switch (op.Opc2) switch (op.Opc2)
{ {
case 5: // Data Memory Barrier Register case 5: // Data Memory Barrier Register.
return; // no-op return; // No-op.
default: default:
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}."); 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) public static void Mrrc(ArmEmitterContext context)
{ {
var op = (OpCode32System)context.CurrOp; OpCode32System op = (OpCode32System)context.CurrOp;
if (op.Coproc != 15) if (op.Coproc != 15)
{ {
@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
Delegate dlg; Delegate dlg;
switch (op.CRm) switch (op.CRm)
{ {
case 14: // Timer case 14: // Timer.
switch (opc) switch (opc)
{ {
case 0: case 0:
@ -222,5 +222,9 @@ namespace ARMeilleure.Instructions
SetIntA32(context, op.Rt, context.ConvertI64ToI32(result)); SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32)))); 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, Vldr,
Vmax, Vmax,
Vmin, Vmin,
VMMmn,
Vmla, Vmla,
Vmls, Vmls,
VMMmn,
Vmov,
Vmrs, Vmrs,
Vmsr, Vmsr,
Vmul, Vmul,
@ -578,7 +579,5 @@ namespace ARMeilleure.Instructions
Vtrn, Vtrn,
Vuzp, Vuzp,
Vzip, Vzip,
Vmov
} }
} }

View file

@ -1535,6 +1535,7 @@ namespace ARMeilleure.Instructions
} }
} }
} }
return result; return result;
} }
@ -2826,6 +2827,7 @@ namespace ARMeilleure.Instructions
} }
} }
} }
return result; return result;
} }
@ -3026,7 +3028,7 @@ namespace ARMeilleure.Instructions
private static double FPThree(bool sign) private static double FPThree(bool sign)
{ {
return sign ? -2d : +2d; return sign ? -3d : +3d;
} }
private static double FPOnePointFive(bool sign) private static double FPOnePointFive(bool sign)

View file

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

View file

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

View file

@ -32,6 +32,7 @@ namespace ARMeilleure.State
public const int SpFiq = 29; public const int SpFiq = 29;
public const int LrFiq = 30; public const int LrFiq = 30;
public const int Aarch32Sp = 13;
public const int Aarch32Lr = 14; public const int Aarch32Lr = 14;
public const int Aarch32Pc = 15; public const int Aarch32Pc = 15;

View file

@ -403,7 +403,6 @@ namespace ARMeilleure.Translation
private static long ClearCallerSavedIntRegs(long mask) private static long ClearCallerSavedIntRegs(long mask)
{ {
// TODO: ARM32 support.
mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask); mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask);
return mask; return mask;
@ -411,7 +410,6 @@ namespace ARMeilleure.Translation
private static long ClearCallerSavedVecRegs(long mask) private static long ClearCallerSavedVecRegs(long mask)
{ {
// TODO: ARM32 support.
mask &= ~(CallerSavedVecRegistersMask | FpStateNzcvFlagsMask); mask &= ~(CallerSavedVecRegistersMask | FpStateNzcvFlagsMask);
return mask; return mask;

View file

@ -20,7 +20,7 @@ namespace ARMeilleure.Translation
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs; private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
private PriorityQueue<Tuple<ulong, ExecutionMode>> _backgroundQueue; private PriorityQueue<(ulong Address, ExecutionMode Mode)> _backgroundQueue;
private AutoResetEvent _backgroundTranslatorEvent; private AutoResetEvent _backgroundTranslatorEvent;
@ -32,7 +32,7 @@ namespace ARMeilleure.Translation
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>(); _funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
_backgroundQueue = new PriorityQueue<Tuple<ulong, ExecutionMode>>(2); _backgroundQueue = new PriorityQueue<(ulong, ExecutionMode)>(2);
_backgroundTranslatorEvent = new AutoResetEvent(false); _backgroundTranslatorEvent = new AutoResetEvent(false);
} }
@ -41,11 +41,11 @@ namespace ARMeilleure.Translation
{ {
while (_threadCount != 0) 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 else
{ {
@ -114,7 +114,7 @@ namespace ARMeilleure.Translation
} }
else if (isCallTarget && func.ShouldRejit()) else if (isCallTarget && func.ShouldRejit())
{ {
_backgroundQueue.Enqueue(0, new Tuple<ulong, ExecutionMode>(address, mode)); _backgroundQueue.Enqueue(0, (address, mode));
_backgroundTranslatorEvent.Set(); _backgroundTranslatorEvent.Set();
} }

View file

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

View file

@ -1,7 +1,5 @@
using Ryujinx.Tests.Unicorn.Native; using Ryujinx.Tests.Unicorn.Native;
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.Tests.Unicorn namespace Ryujinx.Tests.Unicorn
{ {
@ -148,7 +146,7 @@ namespace Ryujinx.Tests.Unicorn
public uint GetX(int index) public uint GetX(int index)
{ {
if ((uint)index > 30) if ((uint)index > 15)
{ {
throw new ArgumentOutOfRangeException(nameof(index)); throw new ArgumentOutOfRangeException(nameof(index));
} }
@ -158,7 +156,7 @@ namespace Ryujinx.Tests.Unicorn
public void SetX(int index, uint value) public void SetX(int index, uint value)
{ {
if ((uint)index > 30) if ((uint)index > 15)
{ {
throw new ArgumentOutOfRangeException(nameof(index)); throw new ArgumentOutOfRangeException(nameof(index));
} }
@ -173,7 +171,8 @@ namespace Ryujinx.Tests.Unicorn
throw new ArgumentOutOfRangeException(nameof(index)); 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) public void SetQ(int index, SimdValue value)

View file

@ -4,10 +4,7 @@ using ARMeilleure.Translation;
using NUnit.Framework; using NUnit.Framework;
using Ryujinx.Tests.Unicorn; using Ryujinx.Tests.Unicorn;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
@ -361,7 +358,8 @@ namespace Ryujinx.Tests.Cpu
byte[] meilleureMem = _memory.ReadBytes((long)(0x2000), _size); byte[] meilleureMem = _memory.ReadBytes((long)(0x2000), _size);
byte[] unicornMem = _unicornEmu.MemoryRead((ulong)(0x2000), (ulong)_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]); Assert.AreEqual(meilleureMem[i], unicornMem[i]);
} }
} }

View file

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

View file

@ -1,7 +1,5 @@
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.Tests.Cpu 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, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb) [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 uint opcode = 0xe7c0001fu; // BFC R0, #0, #1
opcode |= ((rd & 0xf) << 12); opcode |= ((rd & 0xf) << 12);
opcode |= ((msb & 31) << 16) | ((lsb & 31) << 7); 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, RndCntImmr)] uint lsb,
[Values(0u, 15u, 16u, 31u)] [Random(0u, 31u, RndCntImms)] uint msb) [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 uint opcode = 0xe7c00010u; // BFI R0, R0, #0, #1
opcode |= ((rd & 0xf) << 12); opcode |= ((rd & 0xf) << 12);
opcode |= ((rn & 0xf) << 0); opcode |= ((rn & 0xf) << 0);

View file

@ -1,10 +1,7 @@
#define SimdLogical32 #define SimdLogical32
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {

View file

@ -3,9 +3,6 @@
using ARMeilleure.State; using ARMeilleure.State;
using NUnit.Framework; using NUnit.Framework;
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Ryujinx.Tests.Cpu namespace Ryujinx.Tests.Cpu
{ {
@ -17,22 +14,22 @@ namespace Ryujinx.Tests.Cpu
private uint[] LDSTModes = private uint[] LDSTModes =
{ {
//LD1 // LD1
0b0111, 0b0111,
0b1010, 0b1010,
0b0110, 0b0110,
0b0010, 0b0010,
//LD2 // LD2
0b1000, 0b1000,
0b1001, 0b1001,
0b0011, 0b0011,
//LD3 // LD3
0b0100, 0b0100,
0b0101, 0b0101,
//LD4 // LD4
0b0000, 0b0000,
0b0001 0b0001
}; };
@ -60,7 +57,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); 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); SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
@ -86,8 +83,8 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); 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.
if (t) opcode |= 1 << 5; //LD1 is 0, LD2 is 1 etc if (t) opcode |= 1 << 5;
SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500); SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
@ -142,7 +139,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((vd & 0x10) << 18); opcode |= ((vd & 0x10) << 18);
opcode |= ((vd & 0xf) << 12); 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); 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 opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0
uint[] vldmModes = { uint[] vldmModes = {
//note: 3rd 0 leaves a space for "D" // Note: 3rd 0 leaves a space for "D".
0b0100, // increment after 0b0100, // Increment after.
0b0101, // increment after ! 0b0101, // Increment after. (!)
0b1001 // decrement before ! 0b1001 // Decrement before. (!)
}; };
opcode |= ((vldmModes[mode] & 15) << 21); opcode |= ((vldmModes[mode] & 15) << 21);
@ -201,15 +198,15 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((uint)(single ? 0 : 1) << 8); 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; 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; 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; regs = 16 * regSize;
} }
@ -222,7 +219,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("VLDR.<size> <Sd>, [<Rn> {, #{+/-}<imm>}]")] [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)] uint rn,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd, [Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm, [Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
@ -249,7 +246,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0x10) << 18);
opcode |= ((sd & 0xf) << 12); opcode |= ((sd & 0xf) << 12);
} }
opcode |= (uint)imm & 0xff; opcode |= imm & 0xff;
SingleOpcode(opcode, r0: 0x2500); SingleOpcode(opcode, r0: 0x2500);
@ -257,7 +254,7 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise, Description("VSTR.<size> <Sd>, [<Rn> {, #{+/-}<imm>}]")] [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)] uint rn,
[Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd, [Values(0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u)] uint sd,
[Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm, [Values(0x0u)] [Random(0u, 0xffu, RndCntImm)] uint imm,
@ -284,7 +281,7 @@ namespace Ryujinx.Tests.Cpu
opcode |= ((sd & 0x10) << 18); opcode |= ((sd & 0x10) << 18);
opcode |= ((sd & 0xf) << 12); opcode |= ((sd & 0xf) << 12);
} }
opcode |= (uint)imm & 0xff; opcode |= imm & 0xff;
(V128 vec1, V128 vec2, _, _) = GenerateTestVectors(); (V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
@ -308,7 +305,7 @@ namespace Ryujinx.Tests.Cpu
int floatLength = length >> 2; int floatLength = length >> 2;
float[] data = new float[floatLength]; float[] data = new float[floatLength];
for (int i=0; i<floatLength; i++) for (int i = 0; i < floatLength; i++)
{ {
data[i] = i + (i / 9f); data[i] = i + (i / 9f);
} }

View file

@ -22,17 +22,17 @@ namespace Ryujinx.Tests.Cpu
{ {
uint[] variants = uint[] variants =
{ {
//I32 // I32
0b0000_0, 0b0000_0,
0b0010_0, 0b0010_0,
0b0100_0, 0b0100_0,
0b0110_0, 0b0110_0,
//I16 // I16
0b1000_0, 0b1000_0,
0b1010_0, 0b1010_0,
//dt // DT
0b1100_0, 0b1100_0,
0b1101_0, 0b1101_0,
0b1110_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)); SingleOpcode(opcode, r0: valueRn, r1: valueRn, r2: valueRn, r3: valueRn, v0: new V128(valueVn1, valueVn2), v1: new V128(valueVn2, valueVn1));
CompareAgainstUnicorn(); CompareAgainstUnicorn();
@ -191,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
[Random(RndCntImm)] ulong valueVn2, [Random(RndCntImm)] ulong valueVn2,
[Values] bool op) [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 & 1) << 5;
opcode |= (vm & 0x1e) >> 1; opcode |= (vm & 0x1e) >> 1;
opcode |= (rt & 0xf) << 12; opcode |= (rt & 0xf) << 12;
@ -216,7 +215,7 @@ namespace Ryujinx.Tests.Cpu
uint opcode = 0xf3b20080u; // VTRN.8 D0, D0 uint opcode = 0xf3b20080u; // VTRN.8 D0, D0
if (vm == vd) if (vm == vd)
{ {
return; //undefined return; // Undefined.
} }
if (q) if (q)
@ -246,10 +245,10 @@ namespace Ryujinx.Tests.Cpu
[Values(0u, 1u, 2u)] uint size, [Values(0u, 1u, 2u)] uint size,
[Values] bool q) [Values] bool q)
{ {
uint opcode = 0xf3b20180u; // VZIP.8 d0, d0 uint opcode = 0xf3b20180u; // VZIP.8 D0, D0
if (vm == vd || (size == 2 && !q)) if (vm == vd || (size == 2 && !q))
{ {
return; //undefined return; // Undefined.
} }
if (q) if (q)
@ -282,7 +281,7 @@ namespace Ryujinx.Tests.Cpu
uint opcode = 0xf3b20100u; // VUZP.8 d0, d0 uint opcode = 0xf3b20100u; // VUZP.8 d0, d0
if (vm == vd || (size == 2 && !q)) if (vm == vd || (size == 2 && !q))
{ {
return; //undefined return; // Undefined.
} }
if (q) if (q)
@ -307,16 +306,16 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Combinatorial, Description("VTBL.8 <Dd>, {list}, <Dm>")] [Test, Combinatorial, Description("VTBL.8 <Dd>, {list}, <Dm>")]
public void Vtbl([Range(0u, 6u)] uint vm, //indices, include potentially invalid public void Vtbl([Range(0u, 6u)] uint vm, // Indices, include potentially invalid.
[Range(4u, 12u)] uint vn, //selection [Range(4u, 12u)] uint vn, // Selection.
[Values(0u, 1u)] uint vd, //destinations [Values(0u, 1u)] uint vd, // Destinations.
[Range(0u, 3u)] uint length, [Range(0u, 3u)] uint length,
[Values] bool x) [Values] bool x)
{ {
uint opcode = 0xf3b00800u; // VTBL.8 D0, {D0}, D0 uint opcode = 0xf3b00800u; // VTBL.8 D0, {D0}, D0
if (vn + length > 31) if (vn + length > 31)
{ {
return; //undefined return; // Undefined.
} }
if (x) if (x)
@ -371,7 +370,7 @@ namespace Ryujinx.Tests.Cpu
} }
else if (imm4 > 7) else if (imm4 > 7)
{ {
return; //undefined return; // Undefined.
} }
opcode |= (vm & 0x10) << 1; opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf); opcode |= (vm & 0xf);
@ -412,8 +411,8 @@ namespace Ryujinx.Tests.Cpu
opcode |= (vd & 0xf) << 16; opcode |= (vd & 0xf) << 16;
opcode |= (rt & 0xf) << 12; opcode |= (rt & 0xf) << 12;
opcode |= (size & 1) << 5; // e opcode |= (size & 1) << 5; // E
opcode |= (size & 2) << 21; // b opcode |= (size & 2) << 21; // B
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong()); 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 NoInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool NoNaNs = false;
[Explicit]
[Test, Pairwise, Description("VADD.f32 V0, V0, V0")] [Test, Pairwise, Description("VADD.f32 V0, V0, V0")]
public void Vadd_f32([Values(0u)] uint rd, public void Vadd_f32([Values(0u)] uint rd,
[Values(0u, 1u)] uint rn, [Values(0u, 1u)] uint rn,