From 284272854b535477e016363495888660f44b484d Mon Sep 17 00:00:00 2001 From: merry Date: Thu, 10 Feb 2022 20:32:15 +0000 Subject: [PATCH] T16: Implement MOVS, CMP, ADDS, SUBS (8-bit immediate) --- ARMeilleure/Decoders/OpCodeT16AluImm8.cs | 26 +++++++++++++++ ARMeilleure/Decoders/OpCodeTable.cs | 4 +++ Ryujinx.Tests/Cpu/CpuTestThumb.cs | 41 +++++++++++++++++++++++- 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 ARMeilleure/Decoders/OpCodeT16AluImm8.cs diff --git a/ARMeilleure/Decoders/OpCodeT16AluImm8.cs b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs new file mode 100644 index 000000000..082bcb851 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs @@ -0,0 +1,26 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluImm8 : OpCodeT16, IOpCode32AluImm + { + public int Rd { get; } + public int Rn { get; } + + public bool SetFlags { get; } + + public int Immediate { get; } + + public bool IsRotated { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode, bool inITBlock) => new OpCodeT16AluImm8(inst, address, opCode, inITBlock); + + public OpCodeT16AluImm8(InstDescriptor inst, ulong address, int opCode, bool inITBlock) : base(inst, address, opCode, inITBlock) + { + Rd = (opCode >> 8) & 0x7; + Rn = (opCode >> 8) & 0x7; + Immediate = (opCode >> 0) & 0xff; + IsRotated = false; + + SetFlags = !inITBlock; + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 797ab85c5..ab547d4dd 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -979,6 +979,10 @@ namespace ARMeilleure.Decoders SetT16("0001101xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubReg.Create); SetT16("0001110xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubImm3.Create); SetT16("0001111xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubImm3.Create); + SetT16("00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluImm8.Create); + SetT16("00101xxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluImm8.Create); + SetT16("00110xxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluImm8.Create); + SetT16("00111xxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AluImm8.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 285f3cb9a..492bb0dbe 100644 --- a/Ryujinx.Tests/Cpu/CpuTestThumb.cs +++ b/Ryujinx.Tests/Cpu/CpuTestThumb.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using ARMeilleure.State; +using NUnit.Framework; using System; namespace Ryujinx.Tests.Cpu @@ -77,5 +78,43 @@ namespace Ryujinx.Tests.Cpu break; } } + + [Test, Pairwise] + public void AluImm8([Range(0u, 3u)] uint op, [Random(RndCnt)] uint imm, [Random(RndCnt)] uint w1) + { + imm &= 0xff; + + uint opcode = 0x2000; // MOVS , # + + uint rdn = 1; + opcode |= ((imm & 0xff) << 0) | ((rdn & 7) << 8) | ((op & 3) << 11); + + SingleThumbOpcode((ushort)opcode, r1: w1, runUnicorn: false); + + switch (op) + { + case 0: + Assert.That(GetContext().GetX(1), Is.EqualTo(imm)); + break; + case 1: + Assert.That(GetContext().GetX(1), Is.EqualTo(w1)); + cmpFlags: + { + uint result = w1 - imm; + uint overflow = (result ^ w1) & (w1 ^ imm); + 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 >= imm)); + Assert.That(GetContext().GetPstateFlag(PState.VFlag), Is.EqualTo((overflow >> 31) != 0)); + } + break; + case 2: + Assert.That(GetContext().GetX(1), Is.EqualTo((w1 + imm) & 0xffffffffu)); + break; + case 3: + Assert.That(GetContext().GetX(1), Is.EqualTo((w1 - imm) & 0xffffffffu)); + goto cmpFlags; + } + } } }