From 8e119a1e9694416289c4c4c7ed38c408c096f9a2 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 13 Sep 2022 19:51:40 -0300 Subject: [PATCH] Implement PLD and SUB (imm16) on T32, plus UADD8, SADD8, USUB8 and SSUB8 on both A32 and T32 (#3693) --- ARMeilleure/Decoders/OpCodeTable.cs | 52 ++++++++++---- ARMeilleure/Instructions/InstEmitAlu32.cs | 88 ++++++++++++++++++++--- ARMeilleure/Instructions/InstName.cs | 5 ++ ARMeilleure/State/PState.cs | 4 ++ Ryujinx.Tests/Cpu/CpuTest32.cs | 4 ++ Ryujinx.Tests/Cpu/CpuTestAlu32.cs | 56 ++++++++++----- 6 files changed, 168 insertions(+), 41 deletions(-) diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 6484eaf5..faeb9b5a 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -727,11 +727,13 @@ namespace ARMeilleure.Decoders SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluImm.Create); SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsImm.Create); SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsReg.Create); + SetA32("<<<<01100001xxxxxxxx11111001xxxx", InstName.Sadd8, InstEmit32.Sadd8, OpCode32AluReg.Create); SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluImm.Create); SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsImm.Create); SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create); SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create); SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create); + SetA32("<<<<01101000xxxxxxxx11111011xxxx", InstName.Sel, InstEmit32.Sel, OpCode32AluReg.Create); SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create); SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create); SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create); @@ -745,6 +747,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCode32AluMla.Create); SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, OpCode32Sat.Create); SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, OpCode32Sat16.Create); + SetA32("<<<<01100001xxxxxxxx11111111xxxx", InstName.Ssub8, InstEmit32.Ssub8, OpCode32AluReg.Create); SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, OpCode32MemStEx.Create); SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, OpCode32MemStEx.Create); SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, OpCode32MemStEx.Create); @@ -779,6 +782,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluImm.Create); SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsImm.Create); SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create); + SetA32("<<<<01100101xxxxxxxx11111001xxxx", InstName.Uadd8, InstEmit32.Uadd8, OpCode32AluReg.Create); SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create); SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create); SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create); @@ -788,6 +792,7 @@ namespace ARMeilleure.Decoders SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create); SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create); SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create); + SetA32("<<<<01100101xxxxxxxx11111111xxxx", InstName.Usub8, InstEmit32.Usub8, OpCode32AluReg.Create); SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCode32AluUx.Create); SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCode32AluUx.Create); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create); @@ -1128,26 +1133,26 @@ namespace ARMeilleure.Decoders SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create); SetT32("111110000101<<<xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create); - SetT32("111110001100xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create); + SetT32("111110000100<<<xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create); - SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create); + SetT32("111110000000<<<xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create); - SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create); + SetT32("111110000010<<< { + Assert.That(_context.GetPstateFlag(PState.GE0Flag), Is.EqualTo((_unicornEmu.CPSR & (1u << 16)) != 0), "GE0Flag"); + Assert.That(_context.GetPstateFlag(PState.GE1Flag), Is.EqualTo((_unicornEmu.CPSR & (1u << 17)) != 0), "GE1Flag"); + Assert.That(_context.GetPstateFlag(PState.GE2Flag), Is.EqualTo((_unicornEmu.CPSR & (1u << 18)) != 0), "GE2Flag"); + Assert.That(_context.GetPstateFlag(PState.GE3Flag), Is.EqualTo((_unicornEmu.CPSR & (1u << 19)) != 0), "GE3Flag"); Assert.That(_context.GetPstateFlag(PState.QFlag), Is.EqualTo(_unicornEmu.QFlag), "QFlag"); Assert.That(_context.GetPstateFlag(PState.VFlag), Is.EqualTo(_unicornEmu.OverflowFlag), "VFlag"); Assert.That(_context.GetPstateFlag(PState.CFlag), Is.EqualTo(_unicornEmu.CarryFlag), "CFlag"); diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs index f04aa22e..c7537cd9 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs @@ -10,6 +10,21 @@ namespace Ryujinx.Tests.Cpu #if Alu32 #region "ValueSource (Opcodes)" + private static uint[] _SU_H_AddSub_8_() + { + return new uint[] + { + 0xe6100f90u, // SADD8 R0, R0, R0 + 0xe6100ff0u, // SSUB8 R0, R0, R0 + 0xe6300f90u, // SHADD8 R0, R0, R0 + 0xe6300ff0u, // SHSUB8 R0, R0, R0 + 0xe6500f90u, // UADD8 R0, R0, R0 + 0xe6500ff0u, // USUB8 R0, R0, R0 + 0xe6700f90u, // UHADD8 R0, R0, R0 + 0xe6700ff0u // UHSUB8 R0, R0, R0 + }; + } + private static uint[] _Ssat_Usat_() { return new uint[] @@ -150,15 +165,14 @@ namespace Ryujinx.Tests.Cpu } [Test, Pairwise] - public void Uhadd8([Values(0u, 0xdu)] uint rd, - [Values(1u)] uint rm, - [Values(2u)] uint rn, - [Random(RndCnt)] uint w0, - [Random(RndCnt)] uint w1, - [Random(RndCnt)] uint w2) + public void SU_H_AddSub_8([ValueSource("_SU_H_AddSub_8_")] uint opcode, + [Values(0u, 0xdu)] uint rd, + [Values(1u)] uint rm, + [Values(2u)] uint rn, + [Random(RndCnt)] uint w0, + [Random(RndCnt)] uint w1, + [Random(RndCnt)] uint w2) { - uint opcode = 0xE6700F90u; // UHADD8 R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); uint sp = TestContext.CurrentContext.Random.NextUInt(); @@ -169,20 +183,24 @@ namespace Ryujinx.Tests.Cpu } [Test, Pairwise] - public void Uhsub8([Values(0u, 0xdu)] uint rd, - [Values(1u)] uint rm, - [Values(2u)] uint rn, - [Random(RndCnt)] uint w0, - [Random(RndCnt)] uint w1, - [Random(RndCnt)] uint w2) + public void Uadd8_Sel([Values(0u)] uint rd, + [Values(1u)] uint rm, + [Values(2u)] uint rn, + [Random(RndCnt)] uint w0, + [Random(RndCnt)] uint w1, + [Random(RndCnt)] uint w2) { - uint opcode = 0xE6700FF0u; // UHSUB8 R0, R0, R0 + uint opUadd8 = 0xE6500F90; // UADD8 R0, R0, R0 + uint opSel = 0xE6800FB0; // SEL R0, R0, R0 - opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); + opUadd8 |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); + opSel |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16); - uint sp = TestContext.CurrentContext.Random.NextUInt(); - - SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp); + SetContext(r0: w0, r1: w1, r2: w2); + Opcode(opUadd8); + Opcode(opSel); + Opcode(0xE12FFF1E); // BX LR + ExecuteOpcodes(); CompareAgainstUnicorn(); }