From 2876344ccac873dbd173f1e18058130543e0a8ad Mon Sep 17 00:00:00 2001 From: merry Date: Thu, 10 Feb 2022 21:31:17 +0000 Subject: [PATCH] T16: Implement ADD, CMP, MOV (high reg) --- ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs | 22 +++++++++++ ARMeilleure/Decoders/OpCodeTable.cs | 3 ++ Ryujinx.Tests/Cpu/CpuTestThumb.cs | 44 +++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs diff --git a/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs b/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs new file mode 100644 index 000000000..e4765641a --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs @@ -0,0 +1,22 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluRegHigh : OpCodeT16, IOpCode32AluReg + { + public int Rm { get; } + public int Rd { get; } + public int Rn { get; } + + public bool SetFlags { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode, bool inITBlock) => new OpCodeT16AluRegHigh(inst, address, opCode, inITBlock); + + public OpCodeT16AluRegHigh(InstDescriptor inst, ulong address, int opCode, bool inITBlock) : base(inst, address, opCode, inITBlock) + { + Rd = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8); + Rn = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8); + Rm = (opCode >> 3) & 0xf; + + SetFlags = false; + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index e4454c37b..a0b58eb3b 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -999,6 +999,9 @@ namespace ARMeilleure.Decoders SetT16("0100001101xxxxxx", InstName.Mul, InstEmit32.Mul, OpCodeT16AluRegLow.Create); SetT16("0100001110xxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT16AluRegLow.Create); SetT16("0100001111xxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT16AluRegLow.Create); + SetT16("01000100xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluRegHigh.Create); + SetT16("01000101xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegHigh.Create); + SetT16("01000110xxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluRegHigh.Create); SetT16("010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create); #endregion diff --git a/Ryujinx.Tests/Cpu/CpuTestThumb.cs b/Ryujinx.Tests/Cpu/CpuTestThumb.cs index f3fb03409..709d8290e 100644 --- a/Ryujinx.Tests/Cpu/CpuTestThumb.cs +++ b/Ryujinx.Tests/Cpu/CpuTestThumb.cs @@ -207,5 +207,49 @@ namespace Ryujinx.Tests.Cpu break; } } + + [Test, Pairwise] + public void AluRegHigh([Range(0u, 2u)] uint op, [Range(0u, 13u)] uint rd, [Range(0u, 13u)] uint rm, [Random(RndCnt)] uint w1, [Random(RndCnt)] uint w2) + { + if (rd == rm) + { + return; + } + + uint opcode = 0x4400; // ADDS , + + opcode |= ((rd & 7) << 0) | ((rm & 0xf) << 3) | ((rd & 8) << 4) | ((op & 3) << 8); + + ThumbOpcode((ushort)opcode); + ThumbOpcode(0x4770); // BX LR + + GetContext().SetX((int)rd, w1); + GetContext().SetX((int)rm, w2); + GetContext().SetPstateFlag(PState.TFlag, true); + + ExecuteOpcodes(runUnicorn: false); + + switch (op) + { + case 0: + Assert.That(GetContext().GetX((int)rd), Is.EqualTo(w1 + w2)); + break; + case 1: + Assert.That(GetContext().GetX((int)rd), Is.EqualTo(w1)); + Assert.That(GetContext().GetX((int)rm), Is.EqualTo(w2)); + { + uint result = w1 - w2; + uint overflow = (result ^ w1) & (w1 ^ w2); + Assert.That(GetContext().GetPstateFlag(PState.NFlag), Is.EqualTo((result >> 31) != 0)); + Assert.That(GetContext().GetPstateFlag(PState.ZFlag), Is.EqualTo(result == 0)); + Assert.That(GetContext().GetPstateFlag(PState.CFlag), Is.EqualTo(w1 >= w2)); + Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); + } + break; + case 2: + Assert.That(GetContext().GetX((int)rd), Is.EqualTo(w2)); + break; + } + } } }