CpuTestAluRx.cs 60 KB

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