Pseudocode.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // https://github.com/LDj3SNuD/ARM_v8-A_AArch64_Instructions_Tester/blob/master/Tester/Pseudocode.cs
  2. // https://meriac.github.io/archex/A64_v83A_ISA/shared_pseudocode.xml
  3. // https://alastairreid.github.io/asl-lexical-syntax/
  4. // | ------------------------|----------------------------------- |
  5. // | ASL | C# |
  6. // | ------------------------|----------------------------------- |
  7. // | bit, bits(1); boolean | bool |
  8. // | bits | Bits |
  9. // | integer | BigInteger, int |
  10. // | real | decimal |
  11. // | ------------------------|----------------------------------- |
  12. // | '0'; FALSE | false |
  13. // | '1'; TRUE | true |
  14. // | '010' | "010" |
  15. // | bitsX IN {bitsY, bitsZ} | (bitsX == bitsY || bitsX == bitsZ) |
  16. // | DIV | / |
  17. // | MOD | % |
  18. // | ------------------------|----------------------------------- |
  19. using System;
  20. using System.Numerics;
  21. namespace Ryujinx.Tests.Cpu.Tester
  22. {
  23. using Types;
  24. using static Shared;
  25. internal static class AArch64
  26. {
  27. #region "exceptions/exceptions/"
  28. /* #AArch64.ResetControlRegisters.1 */
  29. public static void ResetControlRegisters(bool cold_reset)
  30. {
  31. PSTATE.N = cold_reset;
  32. PSTATE.Z = cold_reset;
  33. PSTATE.C = cold_reset;
  34. PSTATE.V = cold_reset;
  35. }
  36. /* */
  37. public static void TakeReset(bool cold_reset)
  38. {
  39. /* assert !HighestELUsingAArch32(); */
  40. // Enter the highest implemented Exception level in AArch64 state
  41. if (HaveEL(EL3))
  42. {
  43. PSTATE.EL = EL3;
  44. }
  45. else if (HaveEL(EL2))
  46. {
  47. PSTATE.EL = EL2;
  48. }
  49. else
  50. {
  51. PSTATE.EL = EL1;
  52. }
  53. // Reset the system registers and other system components
  54. AArch64.ResetControlRegisters(cold_reset);
  55. // Reset all other PSTATE fields
  56. PSTATE.SP = true; // Select stack pointer
  57. // All registers, bits and fields not reset by the above pseudocode or by the BranchTo() call
  58. // below are UNKNOWN bitstrings after reset. In particular, the return information registers
  59. // ELR_ELx and SPSR_ELx have UNKNOWN values, so that it
  60. // is impossible to return from a reset in an architecturally defined way.
  61. AArch64.ResetGeneralRegisters();
  62. AArch64.ResetSpecialRegisters();
  63. }
  64. #endregion
  65. #region "functions/registers/"
  66. /* #AArch64.ResetGeneralRegisters.0 */
  67. public static void ResetGeneralRegisters()
  68. {
  69. for (int i = 0; i <= 30; i++)
  70. {
  71. /* X[i] = bits(64) UNKNOWN; */
  72. _R[i].SetAll(false);
  73. }
  74. }
  75. /* #AArch64.ResetSpecialRegisters.0 */
  76. public static void ResetSpecialRegisters()
  77. {
  78. // AArch64 special registers
  79. /* SP_EL0 = bits(64) UNKNOWN; */
  80. SP_EL0.SetAll(false);
  81. /* SP_EL1 = bits(64) UNKNOWN; */
  82. SP_EL1.SetAll(false);
  83. }
  84. // #impl-aarch64.SP.write.0
  85. public static void SP(Bits value)
  86. {
  87. /* int width = value.Count; */
  88. /* assert width IN {32,64}; */
  89. if (!PSTATE.SP)
  90. {
  91. SP_EL0 = ZeroExtend(64, value);
  92. }
  93. else
  94. {
  95. switch (PSTATE.EL)
  96. {
  97. case Bits bits when bits == EL0:
  98. SP_EL0 = ZeroExtend(64, value);
  99. break;
  100. default:
  101. case Bits bits when bits == EL1:
  102. SP_EL1 = ZeroExtend(64, value);
  103. break;
  104. /*case Bits bits when bits == EL2:
  105. SP_EL2 = ZeroExtend(64, value);
  106. break;
  107. case Bits bits when bits == EL3:
  108. SP_EL3 = ZeroExtend(64, value);
  109. break;*/
  110. }
  111. }
  112. }
  113. // #impl-aarch64.SP.read.0
  114. public static Bits SP(int width)
  115. {
  116. /* assert width IN {8,16,32,64}; */
  117. if (!PSTATE.SP)
  118. {
  119. return SP_EL0[width - 1, 0];
  120. }
  121. else
  122. {
  123. switch (PSTATE.EL)
  124. {
  125. case Bits bits when bits == EL0:
  126. return SP_EL0[width - 1, 0];
  127. default:
  128. case Bits bits when bits == EL1:
  129. return SP_EL1[width - 1, 0];
  130. /*case Bits bits when bits == EL2:
  131. return SP_EL2[width - 1, 0];
  132. case Bits bits when bits == EL3:
  133. return SP_EL3[width - 1, 0];*/
  134. }
  135. }
  136. }
  137. // #impl-aarch64.X.write.1
  138. public static void X(int n, Bits value)
  139. {
  140. /* int width = value.Count; */
  141. /* assert n >= 0 && n <= 31; */
  142. /* assert width IN {32,64}; */
  143. if (n != 31)
  144. {
  145. _R[n] = ZeroExtend(64, value);
  146. }
  147. }
  148. /* #impl-aarch64.X.read.1 */
  149. public static Bits X(int width, int n)
  150. {
  151. /* assert n >= 0 && n <= 31; */
  152. /* assert width IN {8,16,32,64}; */
  153. if (n != 31)
  154. {
  155. return _R[n][width - 1, 0];
  156. }
  157. else
  158. {
  159. return Zeros(width);
  160. }
  161. }
  162. #endregion
  163. #region "instrs/extendreg/"
  164. /* #impl-aarch64.DecodeRegExtend.1 */
  165. public static ExtendType DecodeRegExtend(Bits op)
  166. {
  167. switch (op)
  168. {
  169. default:
  170. case Bits bits when bits == "000":
  171. return ExtendType.ExtendType_UXTB;
  172. case Bits bits when bits == "001":
  173. return ExtendType.ExtendType_UXTH;
  174. case Bits bits when bits == "010":
  175. return ExtendType.ExtendType_UXTW;
  176. case Bits bits when bits == "011":
  177. return ExtendType.ExtendType_UXTX;
  178. case Bits bits when bits == "100":
  179. return ExtendType.ExtendType_SXTB;
  180. case Bits bits when bits == "101":
  181. return ExtendType.ExtendType_SXTH;
  182. case Bits bits when bits == "110":
  183. return ExtendType.ExtendType_SXTW;
  184. case Bits bits when bits == "111":
  185. return ExtendType.ExtendType_SXTX;
  186. }
  187. }
  188. /* #impl-aarch64.ExtendReg.3 */
  189. public static Bits ExtendReg(int N, int reg, ExtendType type, int shift)
  190. {
  191. /* assert shift >= 0 && shift <= 4; */
  192. Bits val = X(N, reg);
  193. bool unsigned;
  194. int len;
  195. switch (type)
  196. {
  197. default:
  198. case ExtendType.ExtendType_SXTB:
  199. unsigned = false; len = 8;
  200. break;
  201. case ExtendType.ExtendType_SXTH:
  202. unsigned = false; len = 16;
  203. break;
  204. case ExtendType.ExtendType_SXTW:
  205. unsigned = false; len = 32;
  206. break;
  207. case ExtendType.ExtendType_SXTX:
  208. unsigned = false; len = 64;
  209. break;
  210. case ExtendType.ExtendType_UXTB:
  211. unsigned = true; len = 8;
  212. break;
  213. case ExtendType.ExtendType_UXTH:
  214. unsigned = true; len = 16;
  215. break;
  216. case ExtendType.ExtendType_UXTW:
  217. unsigned = true; len = 32;
  218. break;
  219. case ExtendType.ExtendType_UXTX:
  220. unsigned = true; len = 64;
  221. break;
  222. }
  223. // Note the extended width of the intermediate value and
  224. // that sign extension occurs from bit <len+shift-1>, not
  225. // from bit <len-1>. This is equivalent to the instruction
  226. // [SU]BFIZ Rtmp, Rreg, #shift, #len
  227. // It may also be seen as a sign/zero extend followed by a shift:
  228. // LSL(Extend(val<len-1:0>, N, unsigned), shift);
  229. len = Min(len, N - shift);
  230. return Extend(Bits.Concat(val[len - 1, 0], Zeros(shift)), N, unsigned);
  231. }
  232. // #ExtendType
  233. public enum ExtendType {ExtendType_SXTB, ExtendType_SXTH, ExtendType_SXTW, ExtendType_SXTX,
  234. ExtendType_UXTB, ExtendType_UXTH, ExtendType_UXTW, ExtendType_UXTX};
  235. #endregion
  236. #region "instrs/integer/bitmasks/"
  237. /* #impl-aarch64.DecodeBitMasks.4 */
  238. public static (Bits, Bits) DecodeBitMasks(int M, bool immN, Bits imms, Bits immr, bool immediate)
  239. {
  240. Bits tmask, wmask;
  241. Bits tmask_and, wmask_and;
  242. Bits tmask_or, wmask_or;
  243. Bits levels;
  244. // Compute log2 of element size
  245. // 2^len must be in range [2, M]
  246. int len = HighestSetBit(Bits.Concat(immN, NOT(imms)));
  247. /* if len < 1 then ReservedValue(); */
  248. /* assert M >= (1 << len); */
  249. // Determine S, R and S - R parameters
  250. levels = ZeroExtend(Ones(len), 6);
  251. // For logical immediates an all-ones value of S is reserved
  252. // since it would generate a useless all-ones result (many times)
  253. /* if immediate && (imms AND levels) == levels then ReservedValue(); */
  254. BigInteger S = UInt(AND(imms, levels));
  255. BigInteger R = UInt(AND(immr, levels));
  256. BigInteger diff = S - R; // 6-bit subtract with borrow
  257. // Compute "top mask"
  258. tmask_and = OR(diff.SubBigInteger(5, 0), NOT(levels));
  259. tmask_or = AND(diff.SubBigInteger(5, 0), levels);
  260. tmask = Ones(64);
  261. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[0], 1), Ones( 1)), 32)), Replicate(Bits.Concat(Zeros( 1), Replicate(tmask_or[0], 1)), 32));
  262. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[1], 2), Ones( 2)), 16)), Replicate(Bits.Concat(Zeros( 2), Replicate(tmask_or[1], 2)), 16));
  263. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[2], 4), Ones( 4)), 8)), Replicate(Bits.Concat(Zeros( 4), Replicate(tmask_or[2], 4)), 8));
  264. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[3], 8), Ones( 8)), 4)), Replicate(Bits.Concat(Zeros( 8), Replicate(tmask_or[3], 8)), 4));
  265. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[4], 16), Ones(16)), 2)), Replicate(Bits.Concat(Zeros(16), Replicate(tmask_or[4], 16)), 2));
  266. tmask = OR(AND(tmask, Replicate(Bits.Concat(Replicate(tmask_and[5], 32), Ones(32)), 1)), Replicate(Bits.Concat(Zeros(32), Replicate(tmask_or[5], 32)), 1));
  267. // Compute "wraparound mask"
  268. wmask_and = OR(immr, NOT(levels));
  269. wmask_or = AND(immr, levels);
  270. wmask = Zeros(64);
  271. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones( 1), Replicate(wmask_and[0], 1)), 32)), Replicate(Bits.Concat(Replicate(wmask_or[0], 1), Zeros( 1)), 32));
  272. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones( 2), Replicate(wmask_and[1], 2)), 16)), Replicate(Bits.Concat(Replicate(wmask_or[1], 2), Zeros( 2)), 16));
  273. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones( 4), Replicate(wmask_and[2], 4)), 8)), Replicate(Bits.Concat(Replicate(wmask_or[2], 4), Zeros( 4)), 8));
  274. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones( 8), Replicate(wmask_and[3], 8)), 4)), Replicate(Bits.Concat(Replicate(wmask_or[3], 8), Zeros( 8)), 4));
  275. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones(16), Replicate(wmask_and[4], 16)), 2)), Replicate(Bits.Concat(Replicate(wmask_or[4], 16), Zeros(16)), 2));
  276. wmask = OR(AND(wmask, Replicate(Bits.Concat(Ones(32), Replicate(wmask_and[5], 32)), 1)), Replicate(Bits.Concat(Replicate(wmask_or[5], 32), Zeros(32)), 1));
  277. if (diff.SubBigInteger(6)) // borrow from S - R
  278. {
  279. wmask = AND(wmask, tmask);
  280. }
  281. else
  282. {
  283. wmask = OR(wmask, tmask);
  284. }
  285. return (wmask[M - 1, 0], tmask[M - 1, 0]);
  286. }
  287. #endregion
  288. #region "instrs/integer/shiftreg/"
  289. /* #impl-aarch64.DecodeShift.1 */
  290. public static ShiftType DecodeShift(Bits op)
  291. {
  292. switch (op)
  293. {
  294. default:
  295. case Bits bits when bits == "00":
  296. return ShiftType.ShiftType_LSL;
  297. case Bits bits when bits == "01":
  298. return ShiftType.ShiftType_LSR;
  299. case Bits bits when bits == "10":
  300. return ShiftType.ShiftType_ASR;
  301. case Bits bits when bits == "11":
  302. return ShiftType.ShiftType_ROR;
  303. }
  304. }
  305. /* #impl-aarch64.ShiftReg.3 */
  306. public static Bits ShiftReg(int N, int reg, ShiftType type, int amount)
  307. {
  308. Bits result = X(N, reg);
  309. switch (type)
  310. {
  311. default:
  312. case ShiftType.ShiftType_LSL:
  313. result = LSL(result, amount);
  314. break;
  315. case ShiftType.ShiftType_LSR:
  316. result = LSR(result, amount);
  317. break;
  318. case ShiftType.ShiftType_ASR:
  319. result = ASR(result, amount);
  320. break;
  321. case ShiftType.ShiftType_ROR:
  322. result = ROR(result, amount);
  323. break;
  324. }
  325. return result;
  326. }
  327. // #ShiftType
  328. public enum ShiftType {ShiftType_LSL, ShiftType_LSR, ShiftType_ASR, ShiftType_ROR};
  329. #endregion
  330. }
  331. internal static class Shared
  332. {
  333. static Shared()
  334. {
  335. _R = new Bits[31];
  336. for (int i = 0; i <= 30; i++)
  337. {
  338. _R[i] = new Bits(64, false);
  339. }
  340. SP_EL0 = new Bits(64, false);
  341. SP_EL1 = new Bits(64, false);
  342. PSTATE.N = false;
  343. PSTATE.Z = false;
  344. PSTATE.C = false;
  345. PSTATE.V = false;
  346. PSTATE.EL = EL1;
  347. PSTATE.SP = true;
  348. }
  349. #region "functions/common/"
  350. /* */
  351. public static Bits AND(Bits x, Bits y)
  352. {
  353. return x.And(y);
  354. }
  355. // #impl-shared.ASR.2
  356. public static Bits ASR(Bits x, int shift)
  357. {
  358. int N = x.Count;
  359. /* assert shift >= 0; */
  360. Bits result;
  361. if (shift == 0)
  362. {
  363. result = new Bits(x);
  364. }
  365. else
  366. {
  367. (result, _) = ASR_C(x, shift);
  368. }
  369. return result;
  370. }
  371. // #impl-shared.ASR_C.2
  372. public static (Bits, bool) ASR_C(Bits x, int shift)
  373. {
  374. int N = x.Count;
  375. /* assert shift > 0; */
  376. Bits extended_x = SignExtend(x, shift + N);
  377. Bits result = extended_x[shift + N - 1, shift];
  378. bool carry_out = extended_x[shift - 1];
  379. return (result, carry_out);
  380. }
  381. // #impl-shared.CountLeadingSignBits.1
  382. public static int CountLeadingSignBits(Bits x)
  383. {
  384. int N = x.Count;
  385. return CountLeadingZeroBits(EOR(x[N - 1, 1], x[N - 2, 0]));
  386. }
  387. // #impl-shared.CountLeadingZeroBits.1
  388. public static int CountLeadingZeroBits(Bits x)
  389. {
  390. int N = x.Count;
  391. return (N - 1 - HighestSetBit(x));
  392. }
  393. /* */
  394. public static Bits EOR(Bits x, Bits y)
  395. {
  396. return x.Xor(y);
  397. }
  398. // #impl-shared.Extend.3
  399. public static Bits Extend(Bits x, int N, bool unsigned)
  400. {
  401. if (unsigned)
  402. {
  403. return ZeroExtend(x, N);
  404. }
  405. else
  406. {
  407. return SignExtend(x, N);
  408. }
  409. }
  410. /* #impl-shared.Extend.2 */
  411. public static Bits Extend(int N, Bits x, bool unsigned)
  412. {
  413. return Extend(x, N, unsigned);
  414. }
  415. // #impl-shared.HighestSetBit.1
  416. public static int HighestSetBit(Bits x)
  417. {
  418. int N = x.Count;
  419. for (int i = N - 1; i >= 0; i--)
  420. {
  421. if (x[i])
  422. {
  423. return i;
  424. }
  425. }
  426. return -1;
  427. }
  428. // #impl-shared.Int.2
  429. public static BigInteger Int(Bits x, bool unsigned)
  430. {
  431. return (unsigned ? UInt(x) : SInt(x));
  432. }
  433. // #impl-shared.IsOnes.1
  434. public static bool IsOnes(Bits x)
  435. {
  436. int N = x.Count;
  437. return (x == Ones(N));
  438. }
  439. // #impl-shared.IsZero.1
  440. public static bool IsZero(Bits x)
  441. {
  442. int N = x.Count;
  443. return (x == Zeros(N));
  444. }
  445. // #impl-shared.IsZeroBit.1
  446. public static bool IsZeroBit(Bits x)
  447. {
  448. return IsZero(x);
  449. }
  450. // #impl-shared.LSL.2
  451. public static Bits LSL(Bits x, int shift)
  452. {
  453. int N = x.Count;
  454. /* assert shift >= 0; */
  455. Bits result;
  456. if (shift == 0)
  457. {
  458. result = new Bits(x);
  459. }
  460. else
  461. {
  462. (result, _) = LSL_C(x, shift);
  463. }
  464. return result;
  465. }
  466. // #impl-shared.LSL_C.2
  467. public static (Bits, bool) LSL_C(Bits x, int shift)
  468. {
  469. int N = x.Count;
  470. /* assert shift > 0; */
  471. Bits extended_x = Bits.Concat(x, Zeros(shift));
  472. Bits result = extended_x[N - 1, 0];
  473. bool carry_out = extended_x[N];
  474. return (result, carry_out);
  475. }
  476. // #impl-shared.LSR.2
  477. public static Bits LSR(Bits x, int shift)
  478. {
  479. int N = x.Count;
  480. /* assert shift >= 0; */
  481. Bits result;
  482. if (shift == 0)
  483. {
  484. result = new Bits(x);
  485. }
  486. else
  487. {
  488. (result, _) = LSR_C(x, shift);
  489. }
  490. return result;
  491. }
  492. // #impl-shared.LSR_C.2
  493. public static (Bits, bool) LSR_C(Bits x, int shift)
  494. {
  495. int N = x.Count;
  496. /* assert shift > 0; */
  497. Bits extended_x = ZeroExtend(x, shift + N);
  498. Bits result = extended_x[shift + N - 1, shift];
  499. bool carry_out = extended_x[shift - 1];
  500. return (result, carry_out);
  501. }
  502. // #impl-shared.Min.2
  503. public static int Min(int a, int b)
  504. {
  505. if (a <= b)
  506. {
  507. return a;
  508. }
  509. else
  510. {
  511. return b;
  512. }
  513. }
  514. /* #impl-shared.NOT.1 */
  515. public static Bits NOT(Bits x)
  516. {
  517. return x.Not();
  518. }
  519. // #impl-shared.Ones.1
  520. public static Bits Ones(int N)
  521. {
  522. return Replicate(true, N);
  523. }
  524. /* */
  525. public static Bits OR(Bits x, Bits y)
  526. {
  527. return x.Or(y);
  528. }
  529. /* */
  530. public static decimal Real(BigInteger value)
  531. {
  532. return (decimal)value;
  533. }
  534. // #impl-shared.ROR.2
  535. public static Bits ROR(Bits x, int shift)
  536. {
  537. /* assert shift >= 0; */
  538. Bits result;
  539. if (shift == 0)
  540. {
  541. result = new Bits(x);
  542. }
  543. else
  544. {
  545. (result, _) = ROR_C(x, shift);
  546. }
  547. return result;
  548. }
  549. // #impl-shared.ROR_C.2
  550. public static (Bits, bool) ROR_C(Bits x, int shift)
  551. {
  552. int N = x.Count;
  553. /* assert shift != 0; */
  554. int m = shift % N;
  555. Bits result = OR(LSR(x, m), LSL(x, N - m));
  556. bool carry_out = result[N - 1];
  557. return (result, carry_out);
  558. }
  559. /* #impl-shared.Replicate.1 */
  560. public static Bits Replicate(int N, Bits x)
  561. {
  562. int M = x.Count;
  563. /* assert N MOD M == 0; */
  564. return Replicate(x, N / M);
  565. }
  566. /* #impl-shared.Replicate.2 */
  567. public static Bits Replicate(Bits x, int N)
  568. {
  569. int M = x.Count;
  570. bool[] dst = new bool[M * N];
  571. for (int i = 0; i < N; i++)
  572. {
  573. x.CopyTo(dst, i * M);
  574. }
  575. return new Bits(dst);
  576. }
  577. /* #impl-shared.RoundDown.1 */
  578. public static BigInteger RoundDown(decimal x)
  579. {
  580. return (BigInteger)Decimal.Floor(x);
  581. }
  582. // #impl-shared.RoundTowardsZero.1
  583. public static BigInteger RoundTowardsZero(decimal x)
  584. {
  585. if (x == 0.0m)
  586. {
  587. return (BigInteger)0m;
  588. }
  589. else if (x >= 0.0m)
  590. {
  591. return RoundDown(x);
  592. }
  593. else
  594. {
  595. return RoundUp(x);
  596. }
  597. }
  598. /* #impl-shared.RoundUp.1 */
  599. public static BigInteger RoundUp(decimal x)
  600. {
  601. return (BigInteger)Decimal.Ceiling(x);
  602. }
  603. // #impl-shared.SInt.1
  604. public static BigInteger SInt(Bits x)
  605. {
  606. int N = x.Count;
  607. BigInteger result = 0;
  608. for (int i = 0; i <= N - 1; i++)
  609. {
  610. if (x[i])
  611. {
  612. result = result + BigInteger.Pow(2, i);
  613. }
  614. }
  615. if (x[N - 1])
  616. {
  617. result = result - BigInteger.Pow(2, N);
  618. }
  619. return result;
  620. }
  621. // #impl-shared.SignExtend.2
  622. public static Bits SignExtend(Bits x, int N)
  623. {
  624. int M = x.Count;
  625. /* assert N >= M; */
  626. return Bits.Concat(Replicate(x[M - 1], N - M), x);
  627. }
  628. /* #impl-shared.SignExtend.1 */
  629. public static Bits SignExtend(int N, Bits x)
  630. {
  631. return SignExtend(x, N);
  632. }
  633. // #impl-shared.UInt.1
  634. public static BigInteger UInt(Bits x)
  635. {
  636. int N = x.Count;
  637. BigInteger result = 0;
  638. for (int i = 0; i <= N - 1; i++)
  639. {
  640. if (x[i])
  641. {
  642. result = result + BigInteger.Pow(2, i);
  643. }
  644. }
  645. return result;
  646. }
  647. // #impl-shared.ZeroExtend.2
  648. public static Bits ZeroExtend(Bits x, int N)
  649. {
  650. int M = x.Count;
  651. /* assert N >= M; */
  652. return Bits.Concat(Zeros(N - M), x);
  653. }
  654. /* #impl-shared.ZeroExtend.1 */
  655. public static Bits ZeroExtend(int N, Bits x)
  656. {
  657. return ZeroExtend(x, N);
  658. }
  659. // #impl-shared.Zeros.1
  660. /* #impl-shared.Zeros.0 */
  661. public static Bits Zeros(int N)
  662. {
  663. return Replicate(false, N);
  664. }
  665. #endregion
  666. #region "functions/crc/"
  667. // #impl-shared.BitReverse.1
  668. public static Bits BitReverse(Bits data)
  669. {
  670. int N = data.Count;
  671. Bits result = new Bits(N);
  672. for (int i = 0; i <= N - 1; i++)
  673. {
  674. result[N - i - 1] = data[i];
  675. }
  676. return result;
  677. }
  678. // #impl-shared.Poly32Mod2.2
  679. public static Bits Poly32Mod2(Bits _data, Bits poly)
  680. {
  681. int N = _data.Count;
  682. /* assert N > 32; */
  683. Bits data = new Bits(_data);
  684. for (int i = N - 1; i >= 32; i--)
  685. {
  686. if (data[i])
  687. {
  688. data[i - 1, 0] = EOR(data[i - 1, 0], Bits.Concat(poly, Zeros(i - 32)));
  689. }
  690. }
  691. return data[31, 0];
  692. }
  693. #endregion
  694. #region "functions/integer/"
  695. /* #impl-shared.AddWithCarry.3 */
  696. public static (Bits, Bits) AddWithCarry(int N, Bits x, Bits y, bool carry_in)
  697. {
  698. BigInteger unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
  699. BigInteger signed_sum = SInt(x) + SInt(y) + UInt(carry_in);
  700. Bits result = unsigned_sum.SubBigInteger(N - 1, 0); // same value as signed_sum<N-1:0>
  701. bool n = result[N - 1];
  702. bool z = IsZero(result);
  703. bool c = !(UInt(result) == unsigned_sum);
  704. bool v = !(SInt(result) == signed_sum);
  705. return (result, Bits.Concat(n, z, c, v));
  706. }
  707. #endregion
  708. #region "functions/registers/"
  709. public static readonly Bits[] _R;
  710. public static Bits SP_EL0;
  711. public static Bits SP_EL1;
  712. #endregion
  713. #region "functions/system/"
  714. // #impl-shared.ConditionHolds.1
  715. public static bool ConditionHolds(Bits cond)
  716. {
  717. bool result;
  718. // Evaluate base condition.
  719. switch (cond[3, 1])
  720. {
  721. case Bits bits when bits == "000":
  722. result = (PSTATE.Z == true); // EQ or NE
  723. break;
  724. case Bits bits when bits == "001":
  725. result = (PSTATE.C == true); // CS or CC
  726. break;
  727. case Bits bits when bits == "010":
  728. result = (PSTATE.N == true); // MI or PL
  729. break;
  730. case Bits bits when bits == "011":
  731. result = (PSTATE.V == true); // VS or VC
  732. break;
  733. case Bits bits when bits == "100":
  734. result = (PSTATE.C == true && PSTATE.Z == false); // HI or LS
  735. break;
  736. case Bits bits when bits == "101":
  737. result = (PSTATE.N == PSTATE.V); // GE or LT
  738. break;
  739. case Bits bits when bits == "110":
  740. result = (PSTATE.N == PSTATE.V && PSTATE.Z == false); // GT or LE
  741. break;
  742. default:
  743. case Bits bits when bits == "111":
  744. result = true; // AL
  745. break;
  746. }
  747. // Condition flag values in the set '111x' indicate always true
  748. // Otherwise, invert condition if necessary.
  749. if (cond[0] == true && cond != "1111")
  750. {
  751. result = !result;
  752. }
  753. return result;
  754. }
  755. // #EL3
  756. public static readonly Bits EL3 = "11";
  757. // #EL2
  758. public static readonly Bits EL2 = "10";
  759. // #EL1
  760. public static readonly Bits EL1 = "01";
  761. // #EL0
  762. public static readonly Bits EL0 = "00";
  763. /* #impl-shared.HaveEL.1 */
  764. public static bool HaveEL(Bits el)
  765. {
  766. if (el == EL1 || el == EL0)
  767. {
  768. return true; // EL1 and EL0 must exist
  769. }
  770. return false;
  771. }
  772. public static ProcState PSTATE;
  773. /* #ProcState */
  774. internal struct ProcState
  775. {
  776. public void NZCV(Bits nzcv) // ASL: ".<,,,>".
  777. {
  778. N = nzcv[3];
  779. Z = nzcv[2];
  780. C = nzcv[1];
  781. V = nzcv[0];
  782. }
  783. public void NZCV(bool n, bool z, bool c, bool v) // ASL: ".<,,,>".
  784. {
  785. N = n;
  786. Z = z;
  787. C = c;
  788. V = v;
  789. }
  790. public bool N; // Negative condition flag
  791. public bool Z; // Zero condition flag
  792. public bool C; // Carry condition flag
  793. public bool V; // oVerflow condition flag
  794. public Bits EL; // Exception Level
  795. public bool SP; // Stack pointer select: 0=SP0, 1=SPx [AArch64 only]
  796. }
  797. #endregion
  798. }
  799. }