CpuTestSimdReg.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #define SimdReg
  2. using ChocolArm64.State;
  3. using NUnit.Framework;
  4. namespace Ryujinx.Tests.Cpu
  5. {
  6. using Tester;
  7. using Tester.Types;
  8. [Category("SimdReg")]
  9. public sealed class CpuTestSimdReg : CpuTest
  10. {
  11. #if SimdReg
  12. [SetUp]
  13. public void SetupTester()
  14. {
  15. AArch64.TakeReset(false);
  16. }
  17. #region "ValueSource"
  18. private static ulong[] _1D_()
  19. {
  20. return new ulong[] { 0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  21. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  22. }
  23. private static ulong[] _8B4H2S_()
  24. {
  25. return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
  26. 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
  27. 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
  28. 0x8000000080000000ul, 0xFFFFFFFFFFFFFFFFul };
  29. }
  30. private static ulong[] _8B4H2S1D_()
  31. {
  32. return new ulong[] { 0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
  33. 0x8080808080808080ul, 0x7FFF7FFF7FFF7FFFul,
  34. 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
  35. 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
  36. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  37. }
  38. private static ulong[] _4H2S1D_()
  39. {
  40. return new ulong[] { 0x0000000000000000ul, 0x7FFF7FFF7FFF7FFFul,
  41. 0x8000800080008000ul, 0x7FFFFFFF7FFFFFFFul,
  42. 0x8000000080000000ul, 0x7FFFFFFFFFFFFFFFul,
  43. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul };
  44. }
  45. #endregion
  46. [Test, Description("ADD <V><d>, <V><n>, <V><m>")]
  47. public void Add_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
  48. [ValueSource("_1D_")] [Random(1)] ulong B)
  49. {
  50. uint Opcode = 0x5EE28420; // ADD D0, D1, D2
  51. Bits Op = new Bits(Opcode);
  52. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  53. AVec V1 = new AVec { X0 = A };
  54. AVec V2 = new AVec { X0 = B };
  55. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  56. AArch64.V(1, new Bits(A));
  57. AArch64.V(2, new Bits(B));
  58. SimdFp.Add_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  59. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  60. Assert.That(ThreadState.V0.X1, Is.Zero);
  61. }
  62. [Test, Description("ADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  63. public void Add_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
  64. [ValueSource("_8B4H2S_")] [Random(1)] ulong B,
  65. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
  66. {
  67. uint Opcode = 0x0E228420; // ADD V0.8B, V1.8B, V2.8B
  68. Opcode |= ((size & 3) << 22);
  69. Bits Op = new Bits(Opcode);
  70. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  71. AVec V1 = new AVec { X0 = A };
  72. AVec V2 = new AVec { X0 = B };
  73. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  74. AArch64.V(1, new Bits(A));
  75. AArch64.V(2, new Bits(B));
  76. SimdFp.Add_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  77. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  78. Assert.That(ThreadState.V0.X1, Is.Zero);
  79. }
  80. [Test, Pairwise, Description("ADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  81. public void Add_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
  82. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
  83. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
  84. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
  85. [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
  86. {
  87. uint Opcode = 0x4E228420; // ADD V0.16B, V1.16B, V2.16B
  88. Opcode |= ((size & 3) << 22);
  89. Bits Op = new Bits(Opcode);
  90. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  91. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  92. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
  93. AArch64.Vpart(1, 0, new Bits(A0));
  94. AArch64.Vpart(1, 1, new Bits(A1));
  95. AArch64.Vpart(2, 0, new Bits(B0));
  96. AArch64.Vpart(2, 1, new Bits(B1));
  97. SimdFp.Add_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  98. Assert.Multiple(() =>
  99. {
  100. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
  101. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  102. });
  103. }
  104. [Test, Pairwise, Description("ADDHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  105. public void Addhn_V_8H8B_4S4H_2D2S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  106. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  107. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  108. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  109. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H8B, 4S4H, 2D2S>
  110. {
  111. uint Opcode = 0x0E224020; // ADDHN V0.8B, V1.8H, V2.8H
  112. Opcode |= ((size & 3) << 22);
  113. Bits Op = new Bits(Opcode);
  114. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  115. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  116. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  117. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  118. AArch64.Vpart(1, 0, new Bits(A0));
  119. AArch64.Vpart(1, 1, new Bits(A1));
  120. AArch64.Vpart(2, 0, new Bits(B0));
  121. AArch64.Vpart(2, 1, new Bits(B1));
  122. SimdFp.Addhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  123. Assert.Multiple(() =>
  124. {
  125. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  126. Assert.That(ThreadState.V0.X1, Is.Zero);
  127. });
  128. }
  129. [Test, Pairwise, Description("ADDHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  130. public void Addhn_V_8H16B_4S8H_2D4S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  131. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  132. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  133. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  134. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H16B, 4S8H, 2D4S>
  135. {
  136. uint Opcode = 0x4E224020; // ADDHN2 V0.16B, V1.8H, V2.8H
  137. Opcode |= ((size & 3) << 22);
  138. Bits Op = new Bits(Opcode);
  139. ulong _X0 = TestContext.CurrentContext.Random.NextULong();
  140. AVec V0 = new AVec { X0 = _X0 };
  141. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  142. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  143. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  144. AArch64.Vpart(1, 0, new Bits(A0));
  145. AArch64.Vpart(1, 1, new Bits(A1));
  146. AArch64.Vpart(2, 0, new Bits(B0));
  147. AArch64.Vpart(2, 1, new Bits(B1));
  148. SimdFp.Addhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  149. Assert.Multiple(() =>
  150. {
  151. Assert.That(ThreadState.V0.X0, Is.EqualTo(_X0));
  152. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  153. });
  154. }
  155. [Test, Description("ADDP <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  156. public void Addp_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
  157. [ValueSource("_8B4H2S_")] [Random(1)] ulong B,
  158. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
  159. {
  160. uint Opcode = 0x0E22BC20; // ADDP V0.8B, V1.8B, V2.8B
  161. Opcode |= ((size & 3) << 22);
  162. Bits Op = new Bits(Opcode);
  163. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  164. AVec V1 = new AVec { X0 = A };
  165. AVec V2 = new AVec { X0 = B };
  166. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  167. AArch64.V(1, new Bits(A));
  168. AArch64.V(2, new Bits(B));
  169. SimdFp.Addp_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  170. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  171. Assert.That(ThreadState.V0.X1, Is.Zero);
  172. }
  173. [Test, Pairwise, Description("ADDP <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  174. public void Addp_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
  175. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
  176. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
  177. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
  178. [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
  179. {
  180. uint Opcode = 0x4E22BC20; // ADDP V0.16B, V1.16B, V2.16B
  181. Opcode |= ((size & 3) << 22);
  182. Bits Op = new Bits(Opcode);
  183. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  184. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  185. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
  186. AArch64.Vpart(1, 0, new Bits(A0));
  187. AArch64.Vpart(1, 1, new Bits(A1));
  188. AArch64.Vpart(2, 0, new Bits(B0));
  189. AArch64.Vpart(2, 1, new Bits(B1));
  190. SimdFp.Addp_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  191. Assert.Multiple(() =>
  192. {
  193. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
  194. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  195. });
  196. }
  197. [Test, Pairwise, Description("RADDHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  198. public void Raddhn_V_8H8B_4S4H_2D2S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  199. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  200. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  201. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  202. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H8B, 4S4H, 2D2S>
  203. {
  204. uint Opcode = 0x2E224020; // RADDHN V0.8B, V1.8H, V2.8H
  205. Opcode |= ((size & 3) << 22);
  206. Bits Op = new Bits(Opcode);
  207. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  208. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  209. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  210. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  211. AArch64.Vpart(1, 0, new Bits(A0));
  212. AArch64.Vpart(1, 1, new Bits(A1));
  213. AArch64.Vpart(2, 0, new Bits(B0));
  214. AArch64.Vpart(2, 1, new Bits(B1));
  215. SimdFp.Raddhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  216. Assert.Multiple(() =>
  217. {
  218. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  219. Assert.That(ThreadState.V0.X1, Is.Zero);
  220. });
  221. }
  222. [Test, Pairwise, Description("RADDHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  223. public void Raddhn_V_8H16B_4S8H_2D4S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  224. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  225. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  226. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  227. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H16B, 4S8H, 2D4S>
  228. {
  229. uint Opcode = 0x6E224020; // RADDHN2 V0.16B, V1.8H, V2.8H
  230. Opcode |= ((size & 3) << 22);
  231. Bits Op = new Bits(Opcode);
  232. ulong _X0 = TestContext.CurrentContext.Random.NextULong();
  233. AVec V0 = new AVec { X0 = _X0 };
  234. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  235. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  236. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  237. AArch64.Vpart(1, 0, new Bits(A0));
  238. AArch64.Vpart(1, 1, new Bits(A1));
  239. AArch64.Vpart(2, 0, new Bits(B0));
  240. AArch64.Vpart(2, 1, new Bits(B1));
  241. SimdFp.Raddhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  242. Assert.Multiple(() =>
  243. {
  244. Assert.That(ThreadState.V0.X0, Is.EqualTo(_X0));
  245. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  246. });
  247. }
  248. [Test, Pairwise, Description("RSUBHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  249. public void Rsubhn_V_8H8B_4S4H_2D2S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  250. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  251. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  252. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  253. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H8B, 4S4H, 2D2S>
  254. {
  255. uint Opcode = 0x2E226020; // RSUBHN V0.8B, V1.8H, V2.8H
  256. Opcode |= ((size & 3) << 22);
  257. Bits Op = new Bits(Opcode);
  258. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  259. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  260. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  261. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  262. AArch64.Vpart(1, 0, new Bits(A0));
  263. AArch64.Vpart(1, 1, new Bits(A1));
  264. AArch64.Vpart(2, 0, new Bits(B0));
  265. AArch64.Vpart(2, 1, new Bits(B1));
  266. SimdFp.Rsubhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  267. Assert.Multiple(() =>
  268. {
  269. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  270. Assert.That(ThreadState.V0.X1, Is.Zero);
  271. });
  272. }
  273. [Test, Pairwise, Description("RSUBHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  274. public void Rsubhn_V_8H16B_4S8H_2D4S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  275. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  276. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  277. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  278. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H16B, 4S8H, 2D4S>
  279. {
  280. uint Opcode = 0x6E226020; // RSUBHN2 V0.16B, V1.8H, V2.8H
  281. Opcode |= ((size & 3) << 22);
  282. Bits Op = new Bits(Opcode);
  283. ulong _X0 = TestContext.CurrentContext.Random.NextULong();
  284. AVec V0 = new AVec { X0 = _X0 };
  285. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  286. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  287. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  288. AArch64.Vpart(1, 0, new Bits(A0));
  289. AArch64.Vpart(1, 1, new Bits(A1));
  290. AArch64.Vpart(2, 0, new Bits(B0));
  291. AArch64.Vpart(2, 1, new Bits(B1));
  292. SimdFp.Rsubhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  293. Assert.Multiple(() =>
  294. {
  295. Assert.That(ThreadState.V0.X0, Is.EqualTo(_X0));
  296. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  297. });
  298. }
  299. [Test, Description("SUB <V><d>, <V><n>, <V><m>")]
  300. public void Sub_S_D([ValueSource("_1D_")] [Random(1)] ulong A,
  301. [ValueSource("_1D_")] [Random(1)] ulong B)
  302. {
  303. uint Opcode = 0x7EE28420; // SUB D0, D1, D2
  304. Bits Op = new Bits(Opcode);
  305. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  306. AVec V1 = new AVec { X0 = A };
  307. AVec V2 = new AVec { X0 = B };
  308. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  309. AArch64.V(1, new Bits(A));
  310. AArch64.V(2, new Bits(B));
  311. SimdFp.Sub_S(Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  312. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  313. Assert.That(ThreadState.V0.X1, Is.Zero);
  314. }
  315. [Test, Description("SUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  316. public void Sub_V_8B_4H_2S([ValueSource("_8B4H2S_")] [Random(1)] ulong A,
  317. [ValueSource("_8B4H2S_")] [Random(1)] ulong B,
  318. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8B, 4H, 2S>
  319. {
  320. uint Opcode = 0x2E228420; // SUB V0.8B, V1.8B, V2.8B
  321. Opcode |= ((size & 3) << 22);
  322. Bits Op = new Bits(Opcode);
  323. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  324. AVec V1 = new AVec { X0 = A };
  325. AVec V2 = new AVec { X0 = B };
  326. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  327. AArch64.V(1, new Bits(A));
  328. AArch64.V(2, new Bits(B));
  329. SimdFp.Sub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  330. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  331. Assert.That(ThreadState.V0.X1, Is.Zero);
  332. }
  333. [Test, Pairwise, Description("SUB <Vd>.<T>, <Vn>.<T>, <Vm>.<T>")]
  334. public void Sub_V_16B_8H_4S_2D([ValueSource("_8B4H2S1D_")] [Random(1)] ulong A0,
  335. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong A1,
  336. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B0,
  337. [ValueSource("_8B4H2S1D_")] [Random(1)] ulong B1,
  338. [Values(0b00u, 0b01u, 0b10u, 0b11u)] uint size) // <16B, 8H, 4S, 2D>
  339. {
  340. uint Opcode = 0x6E228420; // SUB V0.16B, V1.16B, V2.16B
  341. Opcode |= ((size & 3) << 22);
  342. Bits Op = new Bits(Opcode);
  343. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  344. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  345. AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
  346. AArch64.Vpart(1, 0, new Bits(A0));
  347. AArch64.Vpart(1, 1, new Bits(A1));
  348. AArch64.Vpart(2, 0, new Bits(B0));
  349. AArch64.Vpart(2, 1, new Bits(B1));
  350. SimdFp.Sub_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  351. Assert.Multiple(() =>
  352. {
  353. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.Vpart(64, 0, 0).ToUInt64()));
  354. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  355. });
  356. }
  357. [Test, Pairwise, Description("SUBHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  358. public void Subhn_V_8H8B_4S4H_2D2S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  359. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  360. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  361. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  362. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H8B, 4S4H, 2D2S>
  363. {
  364. uint Opcode = 0x0E226020; // SUBHN V0.8B, V1.8H, V2.8H
  365. Opcode |= ((size & 3) << 22);
  366. Bits Op = new Bits(Opcode);
  367. AVec V0 = new AVec { X1 = TestContext.CurrentContext.Random.NextULong() };
  368. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  369. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  370. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  371. AArch64.Vpart(1, 0, new Bits(A0));
  372. AArch64.Vpart(1, 1, new Bits(A1));
  373. AArch64.Vpart(2, 0, new Bits(B0));
  374. AArch64.Vpart(2, 1, new Bits(B1));
  375. SimdFp.Subhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  376. Assert.Multiple(() =>
  377. {
  378. Assert.That(ThreadState.V0.X0, Is.EqualTo(AArch64.V(64, 0).ToUInt64()));
  379. Assert.That(ThreadState.V0.X1, Is.Zero);
  380. });
  381. }
  382. [Test, Pairwise, Description("SUBHN{2} <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>")]
  383. public void Subhn_V_8H16B_4S8H_2D4S([ValueSource("_4H2S1D_")] [Random(1)] ulong A0,
  384. [ValueSource("_4H2S1D_")] [Random(1)] ulong A1,
  385. [ValueSource("_4H2S1D_")] [Random(1)] ulong B0,
  386. [ValueSource("_4H2S1D_")] [Random(1)] ulong B1,
  387. [Values(0b00u, 0b01u, 0b10u)] uint size) // <8H16B, 4S8H, 2D4S>
  388. {
  389. uint Opcode = 0x4E226020; // SUBHN2 V0.16B, V1.8H, V2.8H
  390. Opcode |= ((size & 3) << 22);
  391. Bits Op = new Bits(Opcode);
  392. ulong _X0 = TestContext.CurrentContext.Random.NextULong();
  393. AVec V0 = new AVec { X0 = _X0 };
  394. AVec V1 = new AVec { X0 = A0, X1 = A1 };
  395. AVec V2 = new AVec { X0 = B0, X1 = B1 };
  396. AThreadState ThreadState = SingleOpcode(Opcode, V0: V0, V1: V1, V2: V2);
  397. AArch64.Vpart(1, 0, new Bits(A0));
  398. AArch64.Vpart(1, 1, new Bits(A1));
  399. AArch64.Vpart(2, 0, new Bits(B0));
  400. AArch64.Vpart(2, 1, new Bits(B1));
  401. SimdFp.Subhn_V(Op[30], Op[23, 22], Op[20, 16], Op[9, 5], Op[4, 0]);
  402. Assert.Multiple(() =>
  403. {
  404. Assert.That(ThreadState.V0.X0, Is.EqualTo(_X0));
  405. Assert.That(ThreadState.V0.X1, Is.EqualTo(AArch64.Vpart(64, 0, 1).ToUInt64()));
  406. });
  407. }
  408. #endif
  409. }
  410. }