/ src / Ryujinx.Tests / Cpu / CpuTestAlu32.cs
CpuTestAlu32.cs
  1  #define Alu32
  2  
  3  using NUnit.Framework;
  4  
  5  namespace Ryujinx.Tests.Cpu
  6  {
  7      [Category("Alu32")]
  8      public sealed class CpuTestAlu32 : CpuTest32
  9      {
 10  #if Alu32
 11  
 12          #region "ValueSource (Opcodes)"
 13          private static uint[] SuHAddSub8()
 14          {
 15              return new[]
 16              {
 17                  0xe6100f90u, // SADD8  R0, R0, R0
 18                  0xe6100ff0u, // SSUB8  R0, R0, R0
 19                  0xe6300f90u, // SHADD8 R0, R0, R0
 20                  0xe6300ff0u, // SHSUB8 R0, R0, R0
 21                  0xe6500f90u, // UADD8  R0, R0, R0
 22                  0xe6500ff0u, // USUB8  R0, R0, R0
 23                  0xe6700f90u, // UHADD8 R0, R0, R0
 24                  0xe6700ff0u, // UHSUB8 R0, R0, R0
 25              };
 26          }
 27  
 28          private static uint[] UQAddSub16()
 29          {
 30              return new[]
 31              {
 32                  0xe6200f10u, // QADD16  R0, R0, R0
 33                  0xe6600f10u, // UQADD16 R0, R0, R0
 34                  0xe6600f70u, // UQSUB16 R0, R0, R0
 35              };
 36          }
 37  
 38          private static uint[] UQAddSub8()
 39          {
 40              return new[]
 41              {
 42                  0xe6600f90u, // UQADD8 R0, R0, R0
 43                  0xe6600ff0u, // UQSUB8 R0, R0, R0
 44              };
 45          }
 46  
 47          private static uint[] SsatUsat()
 48          {
 49              return new[]
 50              {
 51                  0xe6a00010u, // SSAT R0, #1, R0, LSL #0
 52                  0xe6a00050u, // SSAT R0, #1, R0, ASR #32
 53                  0xe6e00010u, // USAT R0, #0, R0, LSL #0
 54                  0xe6e00050u, // USAT R0, #0, R0, ASR #32
 55              };
 56          }
 57  
 58          private static uint[] Ssat16Usat16()
 59          {
 60              return new[]
 61              {
 62                  0xe6a00f30u, // SSAT16 R0, #1, R0
 63                  0xe6e00f30u, // USAT16 R0, #0, R0
 64              };
 65          }
 66  
 67          private static uint[] LsrLslAsrRor()
 68          {
 69              return new[]
 70              {
 71                  0xe1b00030u, // LSRS R0, R0, R0
 72                  0xe1b00010u, // LSLS R0, R0, R0
 73                  0xe1b00050u, // ASRS R0, R0, R0
 74                  0xe1b00070u, // RORS R0, R0, R0
 75              };
 76          }
 77          #endregion
 78  
 79          private const int RndCnt = 2;
 80  
 81          [Test, Pairwise, Description("RBIT <Rd>, <Rn>")]
 82          public void Rbit_32bit([Values(0u, 0xdu)] uint rd,
 83                                 [Values(1u, 0xdu)] uint rm,
 84                                 [Values(0x00000000u, 0x7FFFFFFFu,
 85                                         0x80000000u, 0xFFFFFFFFu)] uint wn)
 86          {
 87              uint opcode = 0xe6ff0f30u; // RBIT R0, R0
 88              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12);
 89  
 90              uint w31 = TestContext.CurrentContext.Random.NextUInt();
 91  
 92              SingleOpcode(opcode, r1: wn, sp: w31);
 93  
 94              CompareAgainstUnicorn();
 95          }
 96  
 97          [Test, Pairwise]
 98          public void Lsr_Lsl_Asr_Ror([ValueSource(nameof(LsrLslAsrRor))] uint opcode,
 99                                      [Values(0x00000000u, 0x7FFFFFFFu,
100                                              0x80000000u, 0xFFFFFFFFu)] uint shiftValue,
101                                      [Range(0, 31)] int shiftAmount)
102          {
103              uint rd = 0;
104              uint rm = 1;
105              uint rs = 2;
106              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rs & 15) << 8);
107  
108              SingleOpcode(opcode, r1: shiftValue, r2: (uint)shiftAmount);
109  
110              CompareAgainstUnicorn();
111          }
112  
113          [Test, Pairwise]
114          public void Shadd8([Values(0u, 0xdu)] uint rd,
115                             [Values(1u)] uint rm,
116                             [Values(2u)] uint rn,
117                             [Random(RndCnt)] uint w0,
118                             [Random(RndCnt)] uint w1,
119                             [Random(RndCnt)] uint w2)
120          {
121              uint opcode = 0xE6300F90u; // SHADD8 R0, R0, R0
122  
123              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
124  
125              uint sp = TestContext.CurrentContext.Random.NextUInt();
126  
127              SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
128  
129              CompareAgainstUnicorn();
130          }
131  
132          [Test, Pairwise]
133          public void Shsub8([Values(0u, 0xdu)] uint rd,
134                             [Values(1u)] uint rm,
135                             [Values(2u)] uint rn,
136                             [Random(RndCnt)] uint w0,
137                             [Random(RndCnt)] uint w1,
138                             [Random(RndCnt)] uint w2)
139          {
140              uint opcode = 0xE6300FF0u; // SHSUB8 R0, R0, R0
141  
142              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
143  
144              uint sp = TestContext.CurrentContext.Random.NextUInt();
145  
146              SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
147  
148              CompareAgainstUnicorn();
149          }
150  
151          [Test, Pairwise]
152          public void Ssat_Usat([ValueSource(nameof(SsatUsat))] uint opcode,
153                                [Values(0u, 0xdu)] uint rd,
154                                [Values(1u, 0xdu)] uint rn,
155                                [Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
156                                [Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint shift,
157                                [Values(0x00000000u, 0x7FFFFFFFu,
158                                        0x80000000u, 0xFFFFFFFFu)] uint wn)
159          {
160              opcode |= ((rn & 15) << 0) | ((shift & 31) << 7) | ((rd & 15) << 12) | ((sat & 31) << 16);
161  
162              uint w31 = TestContext.CurrentContext.Random.NextUInt();
163  
164              SingleOpcode(opcode, r1: wn, sp: w31);
165  
166              CompareAgainstUnicorn();
167          }
168  
169          [Test, Pairwise]
170          public void Ssat16_Usat16([ValueSource(nameof(Ssat16Usat16))] uint opcode,
171                                    [Values(0u, 0xdu)] uint rd,
172                                    [Values(1u, 0xdu)] uint rn,
173                                    [Values(0u, 7u, 8u, 0xfu)] uint sat,
174                                    [Values(0x00000000u, 0x7FFFFFFFu,
175                                            0x80000000u, 0xFFFFFFFFu)] uint wn)
176          {
177              opcode |= ((rn & 15) << 0) | ((rd & 15) << 12) | ((sat & 15) << 16);
178  
179              uint w31 = TestContext.CurrentContext.Random.NextUInt();
180  
181              SingleOpcode(opcode, r1: wn, sp: w31);
182  
183              CompareAgainstUnicorn();
184          }
185  
186          [Test, Pairwise]
187          public void SU_H_AddSub_8([ValueSource(nameof(SuHAddSub8))] uint opcode,
188                                    [Values(0u, 0xdu)] uint rd,
189                                    [Values(1u)] uint rm,
190                                    [Values(2u)] uint rn,
191                                    [Random(RndCnt)] uint w0,
192                                    [Random(RndCnt)] uint w1,
193                                    [Random(RndCnt)] uint w2)
194          {
195              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
196  
197              uint sp = TestContext.CurrentContext.Random.NextUInt();
198  
199              SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
200  
201              CompareAgainstUnicorn();
202          }
203  
204          [Test, Pairwise]
205          public void U_Q_AddSub_16([ValueSource(nameof(UQAddSub16))] uint opcode,
206                                    [Values(0u, 0xdu)] uint rd,
207                                    [Values(1u)] uint rm,
208                                    [Values(2u)] uint rn,
209                                    [Random(RndCnt)] uint w0,
210                                    [Random(RndCnt)] uint w1,
211                                    [Random(RndCnt)] uint w2)
212          {
213              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
214  
215              uint sp = TestContext.CurrentContext.Random.NextUInt();
216  
217              SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
218  
219              CompareAgainstUnicorn();
220          }
221  
222          [Test, Pairwise]
223          public void U_Q_AddSub_8([ValueSource(nameof(UQAddSub8))] uint opcode,
224                                    [Values(0u, 0xdu)] uint rd,
225                                    [Values(1u)] uint rm,
226                                    [Values(2u)] uint rn,
227                                    [Random(RndCnt)] uint w0,
228                                    [Random(RndCnt)] uint w1,
229                                    [Random(RndCnt)] uint w2)
230          {
231              opcode |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
232  
233              uint sp = TestContext.CurrentContext.Random.NextUInt();
234  
235              SingleOpcode(opcode, r0: w0, r1: w1, r2: w2, sp: sp);
236  
237              CompareAgainstUnicorn();
238          }
239  
240          [Test, Pairwise]
241          public void Uadd8_Sel([Values(0u)] uint rd,
242                                [Values(1u)] uint rm,
243                                [Values(2u)] uint rn,
244                                [Random(RndCnt)] uint w0,
245                                [Random(RndCnt)] uint w1,
246                                [Random(RndCnt)] uint w2)
247          {
248              uint opUadd8 = 0xE6500F90; // UADD8 R0, R0, R0
249              uint opSel = 0xE6800FB0; // SEL R0, R0, R0
250  
251              opUadd8 |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
252              opSel |= ((rm & 15) << 0) | ((rd & 15) << 12) | ((rn & 15) << 16);
253  
254              SetContext(r0: w0, r1: w1, r2: w2);
255              Opcode(opUadd8);
256              Opcode(opSel);
257              Opcode(0xE12FFF1E); // BX LR
258              ExecuteOpcodes();
259  
260              CompareAgainstUnicorn();
261          }
262  #endif
263      }
264  }