From d4fe1ee5a80b7cd232c1fa3ec45e91b6e044fdc3 Mon Sep 17 00:00:00 2001 From: merry Date: Thu, 10 Feb 2022 17:15:31 +0000 Subject: [PATCH] Tests: Prepare for thumb tests --- Ryujinx.Tests.Unicorn/UnicornAArch32.cs | 14 +++++++-- Ryujinx.Tests/Cpu/CpuTest32.cs | 41 ++++++++++++++++++++++++- Ryujinx.Tests/Cpu/CpuTestThumb.cs | 11 +++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 Ryujinx.Tests/Cpu/CpuTestThumb.cs diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs index 45d2da7a4..e1efb52fe 100644 --- a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs +++ b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs @@ -41,8 +41,8 @@ namespace Ryujinx.Tests.Unicorn public uint PC { - get => GetRegister(Arm32Register.PC); - set => SetRegister(Arm32Register.PC, value); + get => GetRegister(Arm32Register.PC) & 0xfffffffeu; + set => SetRegister(Arm32Register.PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u)); } public uint CPSR @@ -87,6 +87,16 @@ namespace Ryujinx.Tests.Unicorn set => CPSR = (CPSR & ~0x80000000u) | (value ? 0x80000000u : 0u); } + public bool ThumbFlag + { + get => (CPSR & 0x00000020u) != 0; + set + { + CPSR = (CPSR & ~0x00000020u) | (value ? 0x00000020u : 0u); + SetRegister(Arm32Register.PC, (GetRegister(Arm32Register.PC) & 0xfffffffeu) | (value ? 1u : 0u)); + } + } + public UnicornAArch32() { Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc)); diff --git a/Ryujinx.Tests/Cpu/CpuTest32.cs b/Ryujinx.Tests/Cpu/CpuTest32.cs index 5d24af39c..7fa9ba09a 100644 --- a/Ryujinx.Tests/Cpu/CpuTest32.cs +++ b/Ryujinx.Tests/Cpu/CpuTest32.cs @@ -106,6 +106,18 @@ namespace Ryujinx.Tests.Cpu _currAddress += 4; } + protected void ThumbOpcode(ushort opcode) + { + _memory.Write(_currAddress, opcode); + + if (_unicornAvailable) + { + _unicornEmu.MemoryWrite16(_currAddress, opcode); + } + + _currAddress += 2; + } + protected ExecutionContext GetContext() => _context; protected void SetContext(uint r0 = 0, @@ -126,7 +138,8 @@ namespace Ryujinx.Tests.Cpu bool carry = false, bool zero = false, bool negative = false, - int fpscr = 0) + int fpscr = 0, + bool thumb = false) { _context.SetX(0, r0); _context.SetX(1, r1); @@ -151,6 +164,8 @@ namespace Ryujinx.Tests.Cpu SetFpscr((uint)fpscr); + _context.SetPstateFlag(PState.TFlag, thumb); + if (_unicornAvailable) { _unicornEmu.R[0] = r0; @@ -175,6 +190,8 @@ namespace Ryujinx.Tests.Cpu _unicornEmu.NegativeFlag = negative; _unicornEmu.Fpscr = fpscr; + + _unicornEmu.ThumbFlag = thumb; } } @@ -218,6 +235,28 @@ namespace Ryujinx.Tests.Cpu return GetContext(); } + protected ExecutionContext SingleThumbOpcode(ushort opcode, + uint r0 = 0, + uint r1 = 0, + uint r2 = 0, + uint r3 = 0, + uint sp = 0, + bool saturation = false, + bool overflow = false, + bool carry = false, + bool zero = false, + bool negative = false, + int fpscr = 0, + bool runUnicorn = true) + { + ThumbOpcode(opcode); + ThumbOpcode(0x4770); // BX LR + SetContext(r0, r1, r2, r3, sp, default, default, default, default, default, default, default, default, saturation, overflow, carry, zero, negative, fpscr, thumb: true); + ExecuteOpcodes(runUnicorn); + + return GetContext(); + } + protected void SetWorkingMemory(uint offset, byte[] data) { _memory.Write(DataBaseAddress + offset, data); diff --git a/Ryujinx.Tests/Cpu/CpuTestThumb.cs b/Ryujinx.Tests/Cpu/CpuTestThumb.cs new file mode 100644 index 000000000..058bcc50e --- /dev/null +++ b/Ryujinx.Tests/Cpu/CpuTestThumb.cs @@ -0,0 +1,11 @@ +using NUnit.Framework; +using System; + +namespace Ryujinx.Tests.Cpu +{ + [Category("Thumb")] + public sealed class CpuTestThumb : CpuTest32 + { + private const int RndCnt = 2; + } +}