CpuTestAluRx.cs 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. //#define AluRx
  2. using NUnit.Framework;
  3. namespace Ryujinx.Tests.Cpu
  4. {
  5. [Category("AluRx"), Ignore("Tested: first half of 2018.")]
  6. public sealed class CpuTestAluRx : CpuTest
  7. {
  8. #if AluRx
  9. [SetUp]
  10. public void SetupTester()
  11. {
  12. AArch64.TakeReset(false);
  13. }
  14. [Test, Description("ADD <Xd|SP>, <Xn|SP>, <X><m>{, <extend> {#<amount>}}")]
  15. public void Add_X_64bit([Values(0u, 31u)] uint Rd,
  16. [Values(1u, 31u)] uint Rn,
  17. [Values(2u, 31u)] uint Rm,
  18. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  19. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  20. [Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
  21. (ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(2)] ulong Xm,
  22. [Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
  23. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  24. {
  25. uint Opcode = 0x8B206000; // ADD X0, X0, X0, UXTX #0
  26. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  27. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  28. Bits Op = new Bits(Opcode);
  29. AThreadState ThreadState;
  30. if (Rn != 31)
  31. {
  32. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  33. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: _X31);
  34. AArch64.X((int)Rn, new Bits(Xn_SP));
  35. }
  36. else
  37. {
  38. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Xm);
  39. AArch64.SP(new Bits(Xn_SP));
  40. }
  41. AArch64.X((int)Rm, new Bits(Xm));
  42. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  43. if (Rd != 31)
  44. {
  45. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  46. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  47. }
  48. else
  49. {
  50. ulong SP = AArch64.SP(64).ToUInt64();
  51. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  52. }
  53. }
  54. [Test, Description("ADD <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  55. public void Add_W_64bit([Values(0u, 31u)] uint Rd,
  56. [Values(1u, 31u)] uint Rn,
  57. [Values(2u, 31u)] uint Rm,
  58. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  59. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  60. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  61. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  62. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  63. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  64. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  65. {
  66. uint Opcode = 0x8B200000; // ADD X0, X0, W0, UXTB #0
  67. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  68. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  69. Bits Op = new Bits(Opcode);
  70. AThreadState ThreadState;
  71. if (Rn != 31)
  72. {
  73. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  74. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  75. AArch64.X((int)Rn, new Bits(Xn_SP));
  76. }
  77. else
  78. {
  79. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  80. AArch64.SP(new Bits(Xn_SP));
  81. }
  82. AArch64.X((int)Rm, new Bits(Wm));
  83. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  84. if (Rd != 31)
  85. {
  86. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  87. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  88. }
  89. else
  90. {
  91. ulong SP = AArch64.SP(64).ToUInt64();
  92. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  93. }
  94. }
  95. [Test, Description("ADD <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  96. public void Add_H_64bit([Values(0u, 31u)] uint Rd,
  97. [Values(1u, 31u)] uint Rn,
  98. [Values(2u, 31u)] uint Rm,
  99. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  100. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  101. [Values((ushort)0x0000, (ushort)0x7FFF,
  102. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  103. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  104. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  105. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  106. {
  107. uint Opcode = 0x8B200000; // ADD X0, X0, W0, UXTB #0
  108. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  109. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  110. Bits Op = new Bits(Opcode);
  111. AThreadState ThreadState;
  112. if (Rn != 31)
  113. {
  114. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  115. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  116. AArch64.X((int)Rn, new Bits(Xn_SP));
  117. }
  118. else
  119. {
  120. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  121. AArch64.SP(new Bits(Xn_SP));
  122. }
  123. AArch64.X((int)Rm, new Bits(Wm));
  124. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  125. if (Rd != 31)
  126. {
  127. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  128. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  129. }
  130. else
  131. {
  132. ulong SP = AArch64.SP(64).ToUInt64();
  133. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  134. }
  135. }
  136. [Test, Description("ADD <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  137. public void Add_B_64bit([Values(0u, 31u)] uint Rd,
  138. [Values(1u, 31u)] uint Rn,
  139. [Values(2u, 31u)] uint Rm,
  140. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  141. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  142. [Values((byte)0x00, (byte)0x7F,
  143. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  144. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  145. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  146. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  147. {
  148. uint Opcode = 0x8B200000; // ADD X0, X0, W0, UXTB #0
  149. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  150. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  151. Bits Op = new Bits(Opcode);
  152. AThreadState ThreadState;
  153. if (Rn != 31)
  154. {
  155. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  156. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  157. AArch64.X((int)Rn, new Bits(Xn_SP));
  158. }
  159. else
  160. {
  161. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  162. AArch64.SP(new Bits(Xn_SP));
  163. }
  164. AArch64.X((int)Rm, new Bits(Wm));
  165. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  166. if (Rd != 31)
  167. {
  168. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  169. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  170. }
  171. else
  172. {
  173. ulong SP = AArch64.SP(64).ToUInt64();
  174. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  175. }
  176. }
  177. [Test, Description("ADD <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  178. public void Add_W_32bit([Values(0u, 31u)] uint Rd,
  179. [Values(1u, 31u)] uint Rn,
  180. [Values(2u, 31u)] uint Rm,
  181. [Values(0x00000000u, 0x7FFFFFFFu,
  182. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  183. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  184. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  185. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  186. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  187. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  188. {
  189. uint Opcode = 0x0B200000; // ADD W0, W0, W0, UXTB #0
  190. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  191. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  192. Bits Op = new Bits(Opcode);
  193. AThreadState ThreadState;
  194. if (Rn != 31)
  195. {
  196. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  197. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  198. AArch64.X((int)Rn, new Bits(Wn_WSP));
  199. }
  200. else
  201. {
  202. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  203. AArch64.SP(new Bits(Wn_WSP));
  204. }
  205. AArch64.X((int)Rm, new Bits(Wm));
  206. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  207. if (Rd != 31)
  208. {
  209. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  210. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  211. }
  212. else
  213. {
  214. uint WSP = AArch64.SP(32).ToUInt32();
  215. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  216. }
  217. }
  218. [Test, Description("ADD <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  219. public void Add_H_32bit([Values(0u, 31u)] uint Rd,
  220. [Values(1u, 31u)] uint Rn,
  221. [Values(2u, 31u)] uint Rm,
  222. [Values(0x00000000u, 0x7FFFFFFFu,
  223. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  224. [Values((ushort)0x0000, (ushort)0x7FFF,
  225. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  226. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  227. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  228. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  229. {
  230. uint Opcode = 0x0B200000; // ADD W0, W0, W0, UXTB #0
  231. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  232. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  233. Bits Op = new Bits(Opcode);
  234. AThreadState ThreadState;
  235. if (Rn != 31)
  236. {
  237. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  238. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  239. AArch64.X((int)Rn, new Bits(Wn_WSP));
  240. }
  241. else
  242. {
  243. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  244. AArch64.SP(new Bits(Wn_WSP));
  245. }
  246. AArch64.X((int)Rm, new Bits(Wm));
  247. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  248. if (Rd != 31)
  249. {
  250. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  251. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  252. }
  253. else
  254. {
  255. uint WSP = AArch64.SP(32).ToUInt32();
  256. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  257. }
  258. }
  259. [Test, Description("ADD <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  260. public void Add_B_32bit([Values(0u, 31u)] uint Rd,
  261. [Values(1u, 31u)] uint Rn,
  262. [Values(2u, 31u)] uint Rm,
  263. [Values(0x00000000u, 0x7FFFFFFFu,
  264. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  265. [Values((byte)0x00, (byte)0x7F,
  266. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  267. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  268. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  269. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  270. {
  271. uint Opcode = 0x0B200000; // ADD W0, W0, W0, UXTB #0
  272. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  273. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  274. Bits Op = new Bits(Opcode);
  275. AThreadState ThreadState;
  276. if (Rn != 31)
  277. {
  278. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  279. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  280. AArch64.X((int)Rn, new Bits(Wn_WSP));
  281. }
  282. else
  283. {
  284. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  285. AArch64.SP(new Bits(Wn_WSP));
  286. }
  287. AArch64.X((int)Rm, new Bits(Wm));
  288. Base.Add_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  289. if (Rd != 31)
  290. {
  291. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  292. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  293. }
  294. else
  295. {
  296. uint WSP = AArch64.SP(32).ToUInt32();
  297. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  298. }
  299. }
  300. [Test, Description("ADDS <Xd>, <Xn|SP>, <X><m>{, <extend> {#<amount>}}")]
  301. public void Adds_X_64bit([Values(0u, 31u)] uint Rd,
  302. [Values(1u, 31u)] uint Rn,
  303. [Values(2u, 31u)] uint Rm,
  304. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  305. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  306. [Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
  307. (ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(2)] ulong Xm,
  308. [Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
  309. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  310. {
  311. uint Opcode = 0xAB206000; // ADDS X0, X0, X0, UXTX #0
  312. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  313. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  314. Bits Op = new Bits(Opcode);
  315. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
  316. AArch64.X((int)Rn, new Bits(Xn_SP));
  317. AArch64.X((int)Rm, new Bits(Xm));
  318. AArch64.SP(new Bits(Xn_SP));
  319. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  320. if (Rd != 31)
  321. {
  322. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  323. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  324. }
  325. else
  326. {
  327. ulong _X31 = AArch64.SP(64).ToUInt64();
  328. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  329. }
  330. Assert.Multiple(() =>
  331. {
  332. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  333. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  334. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  335. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  336. });
  337. }
  338. [Test, Description("ADDS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  339. public void Adds_W_64bit([Values(0u, 31u)] uint Rd,
  340. [Values(1u, 31u)] uint Rn,
  341. [Values(2u, 31u)] uint Rm,
  342. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  343. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  344. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  345. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  346. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  347. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  348. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  349. {
  350. uint Opcode = 0xAB200000; // ADDS X0, X0, W0, UXTB #0
  351. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  352. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  353. Bits Op = new Bits(Opcode);
  354. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  355. AArch64.X((int)Rn, new Bits(Xn_SP));
  356. AArch64.X((int)Rm, new Bits(Wm));
  357. AArch64.SP(new Bits(Xn_SP));
  358. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  359. if (Rd != 31)
  360. {
  361. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  362. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  363. }
  364. else
  365. {
  366. ulong _X31 = AArch64.SP(64).ToUInt64();
  367. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  368. }
  369. Assert.Multiple(() =>
  370. {
  371. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  372. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  373. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  374. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  375. });
  376. }
  377. [Test, Description("ADDS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  378. public void Adds_H_64bit([Values(0u, 31u)] uint Rd,
  379. [Values(1u, 31u)] uint Rn,
  380. [Values(2u, 31u)] uint Rm,
  381. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  382. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  383. [Values((ushort)0x0000, (ushort)0x7FFF,
  384. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  385. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  386. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  387. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  388. {
  389. uint Opcode = 0xAB200000; // ADDS X0, X0, W0, UXTB #0
  390. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  391. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  392. Bits Op = new Bits(Opcode);
  393. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  394. AArch64.X((int)Rn, new Bits(Xn_SP));
  395. AArch64.X((int)Rm, new Bits(Wm));
  396. AArch64.SP(new Bits(Xn_SP));
  397. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  398. if (Rd != 31)
  399. {
  400. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  401. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  402. }
  403. else
  404. {
  405. ulong _X31 = AArch64.SP(64).ToUInt64();
  406. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  407. }
  408. Assert.Multiple(() =>
  409. {
  410. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  411. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  412. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  413. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  414. });
  415. }
  416. [Test, Description("ADDS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  417. public void Adds_B_64bit([Values(0u, 31u)] uint Rd,
  418. [Values(1u, 31u)] uint Rn,
  419. [Values(2u, 31u)] uint Rm,
  420. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  421. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  422. [Values((byte)0x00, (byte)0x7F,
  423. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  424. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  425. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  426. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  427. {
  428. uint Opcode = 0xAB200000; // ADDS X0, X0, W0, UXTB #0
  429. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  430. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  431. Bits Op = new Bits(Opcode);
  432. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  433. AArch64.X((int)Rn, new Bits(Xn_SP));
  434. AArch64.X((int)Rm, new Bits(Wm));
  435. AArch64.SP(new Bits(Xn_SP));
  436. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  437. if (Rd != 31)
  438. {
  439. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  440. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  441. }
  442. else
  443. {
  444. ulong _X31 = AArch64.SP(64).ToUInt64();
  445. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  446. }
  447. Assert.Multiple(() =>
  448. {
  449. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  450. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  451. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  452. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  453. });
  454. }
  455. [Test, Description("ADDS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  456. public void Adds_W_32bit([Values(0u, 31u)] uint Rd,
  457. [Values(1u, 31u)] uint Rn,
  458. [Values(2u, 31u)] uint Rm,
  459. [Values(0x00000000u, 0x7FFFFFFFu,
  460. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  461. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  462. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  463. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  464. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  465. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  466. {
  467. uint Opcode = 0x2B200000; // ADDS W0, W0, W0, UXTB #0
  468. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  469. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  470. Bits Op = new Bits(Opcode);
  471. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  472. AArch64.X((int)Rn, new Bits(Wn_WSP));
  473. AArch64.X((int)Rm, new Bits(Wm));
  474. AArch64.SP(new Bits(Wn_WSP));
  475. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  476. if (Rd != 31)
  477. {
  478. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  479. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  480. }
  481. else
  482. {
  483. uint _W31 = AArch64.SP(32).ToUInt32();
  484. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  485. }
  486. Assert.Multiple(() =>
  487. {
  488. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  489. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  490. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  491. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  492. });
  493. }
  494. [Test, Description("ADDS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  495. public void Adds_H_32bit([Values(0u, 31u)] uint Rd,
  496. [Values(1u, 31u)] uint Rn,
  497. [Values(2u, 31u)] uint Rm,
  498. [Values(0x00000000u, 0x7FFFFFFFu,
  499. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  500. [Values((ushort)0x0000, (ushort)0x7FFF,
  501. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  502. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  503. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  504. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  505. {
  506. uint Opcode = 0x2B200000; // ADDS W0, W0, W0, UXTB #0
  507. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  508. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  509. Bits Op = new Bits(Opcode);
  510. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  511. AArch64.X((int)Rn, new Bits(Wn_WSP));
  512. AArch64.X((int)Rm, new Bits(Wm));
  513. AArch64.SP(new Bits(Wn_WSP));
  514. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  515. if (Rd != 31)
  516. {
  517. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  518. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  519. }
  520. else
  521. {
  522. uint _W31 = AArch64.SP(32).ToUInt32();
  523. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  524. }
  525. Assert.Multiple(() =>
  526. {
  527. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  528. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  529. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  530. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  531. });
  532. }
  533. [Test, Description("ADDS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  534. public void Adds_B_32bit([Values(0u, 31u)] uint Rd,
  535. [Values(1u, 31u)] uint Rn,
  536. [Values(2u, 31u)] uint Rm,
  537. [Values(0x00000000u, 0x7FFFFFFFu,
  538. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  539. [Values((byte)0x00, (byte)0x7F,
  540. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  541. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  542. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  543. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  544. {
  545. uint Opcode = 0x2B200000; // ADDS W0, W0, W0, UXTB #0
  546. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  547. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  548. Bits Op = new Bits(Opcode);
  549. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  550. AArch64.X((int)Rn, new Bits(Wn_WSP));
  551. AArch64.X((int)Rm, new Bits(Wm));
  552. AArch64.SP(new Bits(Wn_WSP));
  553. Base.Adds_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  554. if (Rd != 31)
  555. {
  556. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  557. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  558. }
  559. else
  560. {
  561. uint _W31 = AArch64.SP(32).ToUInt32();
  562. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  563. }
  564. Assert.Multiple(() =>
  565. {
  566. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  567. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  568. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  569. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  570. });
  571. }
  572. [Test, Description("SUB <Xd|SP>, <Xn|SP>, <X><m>{, <extend> {#<amount>}}")]
  573. public void Sub_X_64bit([Values(0u, 31u)] uint Rd,
  574. [Values(1u, 31u)] uint Rn,
  575. [Values(2u, 31u)] uint Rm,
  576. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  577. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  578. [Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
  579. (ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(2)] ulong Xm,
  580. [Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
  581. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  582. {
  583. uint Opcode = 0xCB206000; // SUB X0, X0, X0, UXTX #0
  584. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  585. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  586. Bits Op = new Bits(Opcode);
  587. AThreadState ThreadState;
  588. if (Rn != 31)
  589. {
  590. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  591. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: _X31);
  592. AArch64.X((int)Rn, new Bits(Xn_SP));
  593. }
  594. else
  595. {
  596. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Xm);
  597. AArch64.SP(new Bits(Xn_SP));
  598. }
  599. AArch64.X((int)Rm, new Bits(Xm));
  600. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  601. if (Rd != 31)
  602. {
  603. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  604. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  605. }
  606. else
  607. {
  608. ulong SP = AArch64.SP(64).ToUInt64();
  609. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  610. }
  611. }
  612. [Test, Description("SUB <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  613. public void Sub_W_64bit([Values(0u, 31u)] uint Rd,
  614. [Values(1u, 31u)] uint Rn,
  615. [Values(2u, 31u)] uint Rm,
  616. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  617. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  618. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  619. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  620. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  621. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  622. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  623. {
  624. uint Opcode = 0xCB200000; // SUB X0, X0, W0, UXTB #0
  625. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  626. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  627. Bits Op = new Bits(Opcode);
  628. AThreadState ThreadState;
  629. if (Rn != 31)
  630. {
  631. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  632. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  633. AArch64.X((int)Rn, new Bits(Xn_SP));
  634. }
  635. else
  636. {
  637. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  638. AArch64.SP(new Bits(Xn_SP));
  639. }
  640. AArch64.X((int)Rm, new Bits(Wm));
  641. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  642. if (Rd != 31)
  643. {
  644. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  645. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  646. }
  647. else
  648. {
  649. ulong SP = AArch64.SP(64).ToUInt64();
  650. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  651. }
  652. }
  653. [Test, Description("SUB <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  654. public void Sub_H_64bit([Values(0u, 31u)] uint Rd,
  655. [Values(1u, 31u)] uint Rn,
  656. [Values(2u, 31u)] uint Rm,
  657. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  658. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  659. [Values((ushort)0x0000, (ushort)0x7FFF,
  660. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  661. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  662. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  663. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  664. {
  665. uint Opcode = 0xCB200000; // SUB X0, X0, W0, UXTB #0
  666. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  667. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  668. Bits Op = new Bits(Opcode);
  669. AThreadState ThreadState;
  670. if (Rn != 31)
  671. {
  672. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  673. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  674. AArch64.X((int)Rn, new Bits(Xn_SP));
  675. }
  676. else
  677. {
  678. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  679. AArch64.SP(new Bits(Xn_SP));
  680. }
  681. AArch64.X((int)Rm, new Bits(Wm));
  682. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  683. if (Rd != 31)
  684. {
  685. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  686. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  687. }
  688. else
  689. {
  690. ulong SP = AArch64.SP(64).ToUInt64();
  691. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  692. }
  693. }
  694. [Test, Description("SUB <Xd|SP>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  695. public void Sub_B_64bit([Values(0u, 31u)] uint Rd,
  696. [Values(1u, 31u)] uint Rn,
  697. [Values(2u, 31u)] uint Rm,
  698. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  699. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  700. [Values((byte)0x00, (byte)0x7F,
  701. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  702. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  703. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  704. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  705. {
  706. uint Opcode = 0xCB200000; // SUB X0, X0, W0, UXTB #0
  707. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  708. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  709. Bits Op = new Bits(Opcode);
  710. AThreadState ThreadState;
  711. if (Rn != 31)
  712. {
  713. ulong _X31 = TestContext.CurrentContext.Random.NextULong();
  714. ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: _X31);
  715. AArch64.X((int)Rn, new Bits(Xn_SP));
  716. }
  717. else
  718. {
  719. ThreadState = SingleOpcode(Opcode, X31: Xn_SP, X2: Wm);
  720. AArch64.SP(new Bits(Xn_SP));
  721. }
  722. AArch64.X((int)Rm, new Bits(Wm));
  723. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  724. if (Rd != 31)
  725. {
  726. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  727. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  728. }
  729. else
  730. {
  731. ulong SP = AArch64.SP(64).ToUInt64();
  732. Assert.That((ulong)ThreadState.X31, Is.EqualTo(SP));
  733. }
  734. }
  735. [Test, Description("SUB <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  736. public void Sub_W_32bit([Values(0u, 31u)] uint Rd,
  737. [Values(1u, 31u)] uint Rn,
  738. [Values(2u, 31u)] uint Rm,
  739. [Values(0x00000000u, 0x7FFFFFFFu,
  740. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  741. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  742. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  743. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  744. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  745. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  746. {
  747. uint Opcode = 0x4B200000; // SUB W0, W0, W0, UXTB #0
  748. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  749. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  750. Bits Op = new Bits(Opcode);
  751. AThreadState ThreadState;
  752. if (Rn != 31)
  753. {
  754. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  755. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  756. AArch64.X((int)Rn, new Bits(Wn_WSP));
  757. }
  758. else
  759. {
  760. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  761. AArch64.SP(new Bits(Wn_WSP));
  762. }
  763. AArch64.X((int)Rm, new Bits(Wm));
  764. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  765. if (Rd != 31)
  766. {
  767. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  768. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  769. }
  770. else
  771. {
  772. uint WSP = AArch64.SP(32).ToUInt32();
  773. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  774. }
  775. }
  776. [Test, Description("SUB <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  777. public void Sub_H_32bit([Values(0u, 31u)] uint Rd,
  778. [Values(1u, 31u)] uint Rn,
  779. [Values(2u, 31u)] uint Rm,
  780. [Values(0x00000000u, 0x7FFFFFFFu,
  781. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  782. [Values((ushort)0x0000, (ushort)0x7FFF,
  783. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  784. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  785. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  786. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  787. {
  788. uint Opcode = 0x4B200000; // SUB W0, W0, W0, UXTB #0
  789. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  790. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  791. Bits Op = new Bits(Opcode);
  792. AThreadState ThreadState;
  793. if (Rn != 31)
  794. {
  795. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  796. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  797. AArch64.X((int)Rn, new Bits(Wn_WSP));
  798. }
  799. else
  800. {
  801. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  802. AArch64.SP(new Bits(Wn_WSP));
  803. }
  804. AArch64.X((int)Rm, new Bits(Wm));
  805. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  806. if (Rd != 31)
  807. {
  808. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  809. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  810. }
  811. else
  812. {
  813. uint WSP = AArch64.SP(32).ToUInt32();
  814. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  815. }
  816. }
  817. [Test, Description("SUB <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  818. public void Sub_B_32bit([Values(0u, 31u)] uint Rd,
  819. [Values(1u, 31u)] uint Rn,
  820. [Values(2u, 31u)] uint Rm,
  821. [Values(0x00000000u, 0x7FFFFFFFu,
  822. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  823. [Values((byte)0x00, (byte)0x7F,
  824. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  825. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  826. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  827. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  828. {
  829. uint Opcode = 0x4B200000; // SUB W0, W0, W0, UXTB #0
  830. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  831. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  832. Bits Op = new Bits(Opcode);
  833. AThreadState ThreadState;
  834. if (Rn != 31)
  835. {
  836. uint _W31 = TestContext.CurrentContext.Random.NextUInt();
  837. ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: _W31);
  838. AArch64.X((int)Rn, new Bits(Wn_WSP));
  839. }
  840. else
  841. {
  842. ThreadState = SingleOpcode(Opcode, X31: Wn_WSP, X2: Wm);
  843. AArch64.SP(new Bits(Wn_WSP));
  844. }
  845. AArch64.X((int)Rm, new Bits(Wm));
  846. Base.Sub_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  847. if (Rd != 31)
  848. {
  849. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  850. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  851. }
  852. else
  853. {
  854. uint WSP = AArch64.SP(32).ToUInt32();
  855. Assert.That((uint)ThreadState.X31, Is.EqualTo(WSP));
  856. }
  857. }
  858. [Test, Description("SUBS <Xd>, <Xn|SP>, <X><m>{, <extend> {#<amount>}}")]
  859. public void Subs_X_64bit([Values(0u, 31u)] uint Rd,
  860. [Values(1u, 31u)] uint Rn,
  861. [Values(2u, 31u)] uint Rm,
  862. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  863. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  864. [Values((ulong)0x0000000000000000, (ulong)0x7FFFFFFFFFFFFFFF,
  865. (ulong)0x8000000000000000, (ulong)0xFFFFFFFFFFFFFFFF)] [Random(2)] ulong Xm,
  866. [Values(0b011u, 0b111u)] uint extend, // <LSL|UXTX, SXTX>
  867. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  868. {
  869. uint Opcode = 0xEB206000; // SUBS X0, X0, X0, UXTX #0
  870. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  871. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  872. Bits Op = new Bits(Opcode);
  873. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Xm, X31: Xn_SP);
  874. AArch64.X((int)Rn, new Bits(Xn_SP));
  875. AArch64.X((int)Rm, new Bits(Xm));
  876. AArch64.SP(new Bits(Xn_SP));
  877. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  878. if (Rd != 31)
  879. {
  880. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  881. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  882. }
  883. else
  884. {
  885. ulong _X31 = AArch64.SP(64).ToUInt64();
  886. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  887. }
  888. Assert.Multiple(() =>
  889. {
  890. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  891. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  892. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  893. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  894. });
  895. }
  896. [Test, Description("SUBS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  897. public void Subs_W_64bit([Values(0u, 31u)] uint Rd,
  898. [Values(1u, 31u)] uint Rn,
  899. [Values(2u, 31u)] uint Rm,
  900. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  901. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  902. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  903. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  904. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  905. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  906. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  907. {
  908. uint Opcode = 0xEB200000; // SUBS X0, X0, W0, UXTB #0
  909. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  910. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  911. Bits Op = new Bits(Opcode);
  912. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  913. AArch64.X((int)Rn, new Bits(Xn_SP));
  914. AArch64.X((int)Rm, new Bits(Wm));
  915. AArch64.SP(new Bits(Xn_SP));
  916. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  917. if (Rd != 31)
  918. {
  919. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  920. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  921. }
  922. else
  923. {
  924. ulong _X31 = AArch64.SP(64).ToUInt64();
  925. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  926. }
  927. Assert.Multiple(() =>
  928. {
  929. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  930. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  931. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  932. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  933. });
  934. }
  935. [Test, Description("SUBS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  936. public void Subs_H_64bit([Values(0u, 31u)] uint Rd,
  937. [Values(1u, 31u)] uint Rn,
  938. [Values(2u, 31u)] uint Rm,
  939. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  940. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  941. [Values((ushort)0x0000, (ushort)0x7FFF,
  942. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  943. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  944. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  945. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  946. {
  947. uint Opcode = 0xEB200000; // SUBS X0, X0, W0, UXTB #0
  948. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  949. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  950. Bits Op = new Bits(Opcode);
  951. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  952. AArch64.X((int)Rn, new Bits(Xn_SP));
  953. AArch64.X((int)Rm, new Bits(Wm));
  954. AArch64.SP(new Bits(Xn_SP));
  955. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  956. if (Rd != 31)
  957. {
  958. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  959. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  960. }
  961. else
  962. {
  963. ulong _X31 = AArch64.SP(64).ToUInt64();
  964. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  965. }
  966. Assert.Multiple(() =>
  967. {
  968. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  969. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  970. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  971. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  972. });
  973. }
  974. [Test, Description("SUBS <Xd>, <Xn|SP>, <W><m>{, <extend> {#<amount>}}")]
  975. public void Subs_B_64bit([Values(0u, 31u)] uint Rd,
  976. [Values(1u, 31u)] uint Rn,
  977. [Values(2u, 31u)] uint Rm,
  978. [Values(0x0000000000000000ul, 0x7FFFFFFFFFFFFFFFul,
  979. 0x8000000000000000ul, 0xFFFFFFFFFFFFFFFFul)] [Random(1)] ulong Xn_SP,
  980. [Values((byte)0x00, (byte)0x7F,
  981. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  982. [Values(0b000u, 0b001u, 0b010u, // <UXTB, UXTH, UXTW,
  983. 0b100u, 0b101u, 0b110u)] uint extend, // SXTB, SXTH, SXTW>
  984. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  985. {
  986. uint Opcode = 0xEB200000; // SUBS X0, X0, W0, UXTB #0
  987. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  988. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  989. Bits Op = new Bits(Opcode);
  990. AThreadState ThreadState = SingleOpcode(Opcode, X1: Xn_SP, X2: Wm, X31: Xn_SP);
  991. AArch64.X((int)Rn, new Bits(Xn_SP));
  992. AArch64.X((int)Rm, new Bits(Wm));
  993. AArch64.SP(new Bits(Xn_SP));
  994. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  995. if (Rd != 31)
  996. {
  997. ulong Xd = AArch64.X(64, (int)Rd).ToUInt64();
  998. Assert.That((ulong)ThreadState.X0, Is.EqualTo(Xd));
  999. }
  1000. else
  1001. {
  1002. ulong _X31 = AArch64.SP(64).ToUInt64();
  1003. Assert.That((ulong)ThreadState.X31, Is.EqualTo(_X31));
  1004. }
  1005. Assert.Multiple(() =>
  1006. {
  1007. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  1008. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  1009. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  1010. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  1011. });
  1012. }
  1013. [Test, Description("SUBS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  1014. public void Subs_W_32bit([Values(0u, 31u)] uint Rd,
  1015. [Values(1u, 31u)] uint Rn,
  1016. [Values(2u, 31u)] uint Rm,
  1017. [Values(0x00000000u, 0x7FFFFFFFu,
  1018. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  1019. [Values((uint)0x00000000, (uint)0x7FFFFFFF,
  1020. (uint)0x80000000, (uint)0xFFFFFFFF)] [Random(2)] uint Wm,
  1021. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  1022. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  1023. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  1024. {
  1025. uint Opcode = 0x6B200000; // SUBS W0, W0, W0, UXTB #0
  1026. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  1027. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  1028. Bits Op = new Bits(Opcode);
  1029. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  1030. AArch64.X((int)Rn, new Bits(Wn_WSP));
  1031. AArch64.X((int)Rm, new Bits(Wm));
  1032. AArch64.SP(new Bits(Wn_WSP));
  1033. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  1034. if (Rd != 31)
  1035. {
  1036. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  1037. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  1038. }
  1039. else
  1040. {
  1041. uint _W31 = AArch64.SP(32).ToUInt32();
  1042. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  1043. }
  1044. Assert.Multiple(() =>
  1045. {
  1046. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  1047. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  1048. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  1049. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  1050. });
  1051. }
  1052. [Test, Description("SUBS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  1053. public void Subs_H_32bit([Values(0u, 31u)] uint Rd,
  1054. [Values(1u, 31u)] uint Rn,
  1055. [Values(2u, 31u)] uint Rm,
  1056. [Values(0x00000000u, 0x7FFFFFFFu,
  1057. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  1058. [Values((ushort)0x0000, (ushort)0x7FFF,
  1059. (ushort)0x8000, (ushort)0xFFFF)] [Random(2)] ushort Wm,
  1060. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  1061. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  1062. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  1063. {
  1064. uint Opcode = 0x6B200000; // SUBS W0, W0, W0, UXTB #0
  1065. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  1066. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  1067. Bits Op = new Bits(Opcode);
  1068. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  1069. AArch64.X((int)Rn, new Bits(Wn_WSP));
  1070. AArch64.X((int)Rm, new Bits(Wm));
  1071. AArch64.SP(new Bits(Wn_WSP));
  1072. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  1073. if (Rd != 31)
  1074. {
  1075. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  1076. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  1077. }
  1078. else
  1079. {
  1080. uint _W31 = AArch64.SP(32).ToUInt32();
  1081. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  1082. }
  1083. Assert.Multiple(() =>
  1084. {
  1085. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  1086. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  1087. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  1088. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  1089. });
  1090. }
  1091. [Test, Description("SUBS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}")]
  1092. public void Subs_B_32bit([Values(0u, 31u)] uint Rd,
  1093. [Values(1u, 31u)] uint Rn,
  1094. [Values(2u, 31u)] uint Rm,
  1095. [Values(0x00000000u, 0x7FFFFFFFu,
  1096. 0x80000000u, 0xFFFFFFFFu)] [Random(1)] uint Wn_WSP,
  1097. [Values((byte)0x00, (byte)0x7F,
  1098. (byte)0x80, (byte)0xFF)] [Random(2)] byte Wm,
  1099. [Values(0b000u, 0b001u, 0b010u, 0b011u, // <UXTB, UXTH, LSL|UXTW, UXTX,
  1100. 0b100u, 0b101u, 0b110u, 0b111u)] uint extend, // SXTB, SXTH, SXTW, SXTX>
  1101. [Values(0u, 1u, 2u, 3u, 4u)] uint amount)
  1102. {
  1103. uint Opcode = 0x6B200000; // SUBS W0, W0, W0, UXTB #0
  1104. Opcode |= ((Rm & 31) << 16) | ((Rn & 31) << 5) | ((Rd & 31) << 0);
  1105. Opcode |= ((extend & 7) << 13) | ((amount & 7) << 10);
  1106. Bits Op = new Bits(Opcode);
  1107. AThreadState ThreadState = SingleOpcode(Opcode, X1: Wn_WSP, X2: Wm, X31: Wn_WSP);
  1108. AArch64.X((int)Rn, new Bits(Wn_WSP));
  1109. AArch64.X((int)Rm, new Bits(Wm));
  1110. AArch64.SP(new Bits(Wn_WSP));
  1111. Base.Subs_Rx(Op[31], Op[20, 16], Op[15, 13], Op[12, 10], Op[9, 5], Op[4, 0]);
  1112. if (Rd != 31)
  1113. {
  1114. uint Wd = AArch64.X(32, (int)Rd).ToUInt32();
  1115. Assert.That((uint)ThreadState.X0, Is.EqualTo(Wd));
  1116. }
  1117. else
  1118. {
  1119. uint _W31 = AArch64.SP(32).ToUInt32();
  1120. Assert.That((uint)ThreadState.X31, Is.EqualTo(_W31));
  1121. }
  1122. Assert.Multiple(() =>
  1123. {
  1124. Assert.That(ThreadState.Negative, Is.EqualTo(Shared.PSTATE.N));
  1125. Assert.That(ThreadState.Zero, Is.EqualTo(Shared.PSTATE.Z));
  1126. Assert.That(ThreadState.Carry, Is.EqualTo(Shared.PSTATE.C));
  1127. Assert.That(ThreadState.Overflow, Is.EqualTo(Shared.PSTATE.V));
  1128. });
  1129. }
  1130. #endif
  1131. }
  1132. }