AInstEmitSimdArithmetic.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. using ChocolArm64.Decoder;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. using static ChocolArm64.Instruction.AInstEmitSimdHelper;
  8. namespace ChocolArm64.Instruction
  9. {
  10. static partial class AInstEmit
  11. {
  12. public static void Abs_S(AILEmitterCtx Context)
  13. {
  14. EmitScalarUnaryOpSx(Context, () => EmitAbs(Context));
  15. }
  16. public static void Abs_V(AILEmitterCtx Context)
  17. {
  18. EmitVectorUnaryOpSx(Context, () => EmitAbs(Context));
  19. }
  20. private static void EmitAbs(AILEmitterCtx Context)
  21. {
  22. AILLabel LblTrue = new AILLabel();
  23. Context.Emit(OpCodes.Dup);
  24. Context.Emit(OpCodes.Ldc_I4_0);
  25. Context.Emit(OpCodes.Bge_S, LblTrue);
  26. Context.Emit(OpCodes.Neg);
  27. Context.MarkLabel(LblTrue);
  28. }
  29. public static void Add_S(AILEmitterCtx Context)
  30. {
  31. EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
  32. }
  33. public static void Add_V(AILEmitterCtx Context)
  34. {
  35. EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
  36. }
  37. public static void Addp_S(AILEmitterCtx Context)
  38. {
  39. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  40. EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
  41. EmitVectorExtractZx(Context, Op.Rn, 1, Op.Size);
  42. Context.Emit(OpCodes.Add);
  43. EmitScalarSet(Context, Op.Rd, Op.Size);
  44. }
  45. public static void Addp_V(AILEmitterCtx Context)
  46. {
  47. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  48. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  49. int Elems = Bytes >> Op.Size;
  50. int Half = Elems >> 1;
  51. for (int Index = 0; Index < Elems; Index++)
  52. {
  53. int Elem = (Index & (Half - 1)) << 1;
  54. EmitVectorExtractZx(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 0, Op.Size);
  55. EmitVectorExtractZx(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 1, Op.Size);
  56. Context.Emit(OpCodes.Add);
  57. EmitVectorInsertTmp(Context, Index, Op.Size);
  58. }
  59. Context.EmitLdvectmp();
  60. Context.EmitStvec(Op.Rd);
  61. if (Op.RegisterSize == ARegisterSize.SIMD64)
  62. {
  63. EmitVectorZeroUpper(Context, Op.Rd);
  64. }
  65. }
  66. public static void Addv_V(AILEmitterCtx Context)
  67. {
  68. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  69. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  70. EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
  71. for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
  72. {
  73. EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
  74. Context.Emit(OpCodes.Add);
  75. }
  76. EmitScalarSet(Context, Op.Rd, Op.Size);
  77. }
  78. public static void Cnt_V(AILEmitterCtx Context)
  79. {
  80. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  81. int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
  82. for (int Index = 0; Index < Elems; Index++)
  83. {
  84. EmitVectorExtractZx(Context, Op.Rn, Index, 0);
  85. Context.Emit(OpCodes.Conv_U1);
  86. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountSetBits8));
  87. Context.Emit(OpCodes.Conv_U8);
  88. EmitVectorInsert(Context, Op.Rd, Index, 0);
  89. }
  90. if (Op.RegisterSize == ARegisterSize.SIMD64)
  91. {
  92. EmitVectorZeroUpper(Context, Op.Rd);
  93. }
  94. }
  95. public static void Fabd_S(AILEmitterCtx Context)
  96. {
  97. EmitScalarBinaryOpF(Context, () =>
  98. {
  99. Context.Emit(OpCodes.Sub);
  100. EmitUnaryMathCall(Context, nameof(Math.Abs));
  101. });
  102. }
  103. public static void Fabs_S(AILEmitterCtx Context)
  104. {
  105. EmitScalarUnaryOpF(Context, () =>
  106. {
  107. EmitUnaryMathCall(Context, nameof(Math.Abs));
  108. });
  109. }
  110. public static void Fadd_S(AILEmitterCtx Context)
  111. {
  112. EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Add));
  113. }
  114. public static void Fadd_V(AILEmitterCtx Context)
  115. {
  116. EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Add));
  117. }
  118. public static void Faddp_V(AILEmitterCtx Context)
  119. {
  120. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  121. int SizeF = Op.Size & 1;
  122. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  123. int Elems = Bytes >> SizeF + 2;
  124. int Half = Elems >> 1;
  125. for (int Index = 0; Index < Elems; Index++)
  126. {
  127. int Elem = (Index & (Half - 1)) << 1;
  128. EmitVectorExtractF(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 0, SizeF);
  129. EmitVectorExtractF(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 1, SizeF);
  130. Context.Emit(OpCodes.Add);
  131. EmitVectorInsertTmpF(Context, Index, SizeF);
  132. }
  133. Context.EmitLdvectmp();
  134. Context.EmitStvec(Op.Rd);
  135. if (Op.RegisterSize == ARegisterSize.SIMD64)
  136. {
  137. EmitVectorZeroUpper(Context, Op.Rd);
  138. }
  139. }
  140. public static void Fdiv_S(AILEmitterCtx Context)
  141. {
  142. EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Div));
  143. }
  144. public static void Fdiv_V(AILEmitterCtx Context)
  145. {
  146. EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Div));
  147. }
  148. public static void Fmadd_S(AILEmitterCtx Context)
  149. {
  150. EmitScalarTernaryRaOpF(Context, () =>
  151. {
  152. Context.Emit(OpCodes.Mul);
  153. Context.Emit(OpCodes.Add);
  154. });
  155. }
  156. public static void Fmax_S(AILEmitterCtx Context)
  157. {
  158. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  159. EmitScalarBinaryOpF(Context, () =>
  160. {
  161. if (Op.Size == 0)
  162. {
  163. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MaxF));
  164. }
  165. else if (Op.Size == 1)
  166. {
  167. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Max));
  168. }
  169. else
  170. {
  171. throw new InvalidOperationException();
  172. }
  173. });
  174. }
  175. public static void Fmax_V(AILEmitterCtx Context)
  176. {
  177. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  178. EmitVectorBinaryOpF(Context, () =>
  179. {
  180. if (Op.Size == 0)
  181. {
  182. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MaxF));
  183. }
  184. else if (Op.Size == 1)
  185. {
  186. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Max));
  187. }
  188. else
  189. {
  190. throw new InvalidOperationException();
  191. }
  192. });
  193. }
  194. public static void Fmin_S(AILEmitterCtx Context)
  195. {
  196. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  197. EmitScalarBinaryOpF(Context, () =>
  198. {
  199. if (Op.Size == 0)
  200. {
  201. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MinF));
  202. }
  203. else if (Op.Size == 1)
  204. {
  205. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Min));
  206. }
  207. else
  208. {
  209. throw new InvalidOperationException();
  210. }
  211. });
  212. }
  213. public static void Fmin_V(AILEmitterCtx Context)
  214. {
  215. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  216. int SizeF = Op.Size & 1;
  217. EmitVectorBinaryOpF(Context, () =>
  218. {
  219. if (SizeF == 0)
  220. {
  221. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MinF));
  222. }
  223. else if (SizeF == 1)
  224. {
  225. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Min));
  226. }
  227. else
  228. {
  229. throw new InvalidOperationException();
  230. }
  231. });
  232. }
  233. public static void Fmaxnm_S(AILEmitterCtx Context)
  234. {
  235. Fmax_S(Context);
  236. }
  237. public static void Fminnm_S(AILEmitterCtx Context)
  238. {
  239. Fmin_S(Context);
  240. }
  241. public static void Fmla_V(AILEmitterCtx Context)
  242. {
  243. EmitVectorTernaryOpF(Context, () =>
  244. {
  245. Context.Emit(OpCodes.Mul);
  246. Context.Emit(OpCodes.Add);
  247. });
  248. }
  249. public static void Fmla_Ve(AILEmitterCtx Context)
  250. {
  251. EmitVectorTernaryOpByElemF(Context, () =>
  252. {
  253. Context.Emit(OpCodes.Mul);
  254. Context.Emit(OpCodes.Add);
  255. });
  256. }
  257. public static void Fmls_V(AILEmitterCtx Context)
  258. {
  259. EmitVectorTernaryOpF(Context, () =>
  260. {
  261. Context.Emit(OpCodes.Mul);
  262. Context.Emit(OpCodes.Sub);
  263. });
  264. }
  265. public static void Fmls_Ve(AILEmitterCtx Context)
  266. {
  267. EmitVectorTernaryOpByElemF(Context, () =>
  268. {
  269. Context.Emit(OpCodes.Mul);
  270. Context.Emit(OpCodes.Sub);
  271. });
  272. }
  273. public static void Fmsub_S(AILEmitterCtx Context)
  274. {
  275. EmitScalarTernaryRaOpF(Context, () =>
  276. {
  277. Context.Emit(OpCodes.Mul);
  278. Context.Emit(OpCodes.Sub);
  279. });
  280. }
  281. public static void Fmul_S(AILEmitterCtx Context)
  282. {
  283. EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Mul));
  284. }
  285. public static void Fmul_Se(AILEmitterCtx Context)
  286. {
  287. EmitScalarBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
  288. }
  289. public static void Fmul_V(AILEmitterCtx Context)
  290. {
  291. EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Mul));
  292. }
  293. public static void Fmul_Ve(AILEmitterCtx Context)
  294. {
  295. EmitVectorBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
  296. }
  297. public static void Fneg_S(AILEmitterCtx Context)
  298. {
  299. EmitScalarUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
  300. }
  301. public static void Fneg_V(AILEmitterCtx Context)
  302. {
  303. EmitVectorUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
  304. }
  305. public static void Fnmadd_S(AILEmitterCtx Context)
  306. {
  307. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  308. int SizeF = Op.Size & 1;
  309. EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
  310. Context.Emit(OpCodes.Neg);
  311. EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
  312. Context.Emit(OpCodes.Mul);
  313. EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
  314. Context.Emit(OpCodes.Sub);
  315. EmitScalarSetF(Context, Op.Rd, SizeF);
  316. }
  317. public static void Fnmsub_S(AILEmitterCtx Context)
  318. {
  319. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  320. int SizeF = Op.Size & 1;
  321. EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
  322. EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
  323. Context.Emit(OpCodes.Mul);
  324. EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
  325. Context.Emit(OpCodes.Sub);
  326. EmitScalarSetF(Context, Op.Rd, SizeF);
  327. }
  328. public static void Fnmul_S(AILEmitterCtx Context)
  329. {
  330. EmitScalarBinaryOpF(Context, () =>
  331. {
  332. Context.Emit(OpCodes.Mul);
  333. Context.Emit(OpCodes.Neg);
  334. });
  335. }
  336. public static void Frecpe_S(AILEmitterCtx Context)
  337. {
  338. EmitFrecpe(Context, 0, Scalar: true);
  339. }
  340. public static void Frecpe_V(AILEmitterCtx Context)
  341. {
  342. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  343. int SizeF = Op.Size & 1;
  344. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  345. for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
  346. {
  347. EmitFrecpe(Context, Index, Scalar: false);
  348. }
  349. if (Op.RegisterSize == ARegisterSize.SIMD64)
  350. {
  351. EmitVectorZeroUpper(Context, Op.Rd);
  352. }
  353. }
  354. private static void EmitFrecpe(AILEmitterCtx Context, int Index, bool Scalar)
  355. {
  356. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  357. int SizeF = Op.Size & 1;
  358. if (SizeF == 0)
  359. {
  360. Context.EmitLdc_R4(1);
  361. }
  362. else /* if (SizeF == 1) */
  363. {
  364. Context.EmitLdc_R8(1);
  365. }
  366. EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
  367. Context.Emit(OpCodes.Div);
  368. if (Scalar)
  369. {
  370. EmitVectorZeroAll(Context, Op.Rd);
  371. }
  372. EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
  373. }
  374. public static void Frecps_S(AILEmitterCtx Context)
  375. {
  376. EmitFrecps(Context, 0, Scalar: true);
  377. }
  378. public static void Frecps_V(AILEmitterCtx Context)
  379. {
  380. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  381. int SizeF = Op.Size & 1;
  382. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  383. for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
  384. {
  385. EmitFrecps(Context, Index, Scalar: false);
  386. }
  387. if (Op.RegisterSize == ARegisterSize.SIMD64)
  388. {
  389. EmitVectorZeroUpper(Context, Op.Rd);
  390. }
  391. }
  392. private static void EmitFrecps(AILEmitterCtx Context, int Index, bool Scalar)
  393. {
  394. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  395. int SizeF = Op.Size & 1;
  396. if (SizeF == 0)
  397. {
  398. Context.EmitLdc_R4(2);
  399. }
  400. else /* if (SizeF == 1) */
  401. {
  402. Context.EmitLdc_R8(2);
  403. }
  404. EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
  405. EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
  406. Context.Emit(OpCodes.Mul);
  407. Context.Emit(OpCodes.Sub);
  408. if (Scalar)
  409. {
  410. EmitVectorZeroAll(Context, Op.Rd);
  411. }
  412. EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
  413. }
  414. public static void Frinta_S(AILEmitterCtx Context)
  415. {
  416. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  417. EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
  418. EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
  419. EmitScalarSetF(Context, Op.Rd, Op.Size);
  420. }
  421. public static void Frinta_V(AILEmitterCtx Context)
  422. {
  423. EmitVectorUnaryOpF(Context, () =>
  424. {
  425. EmitRoundMathCall(Context, MidpointRounding.AwayFromZero);
  426. });
  427. }
  428. public static void Frinti_S(AILEmitterCtx Context)
  429. {
  430. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  431. EmitScalarUnaryOpF(Context, () =>
  432. {
  433. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  434. Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
  435. if (Op.Size == 0)
  436. {
  437. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
  438. }
  439. else if (Op.Size == 1)
  440. {
  441. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
  442. }
  443. else
  444. {
  445. throw new InvalidOperationException();
  446. }
  447. });
  448. }
  449. public static void Frinti_V(AILEmitterCtx Context)
  450. {
  451. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  452. int SizeF = Op.Size & 1;
  453. EmitVectorUnaryOpF(Context, () =>
  454. {
  455. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  456. Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
  457. if (SizeF == 0)
  458. {
  459. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
  460. }
  461. else if (SizeF == 1)
  462. {
  463. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
  464. }
  465. else
  466. {
  467. throw new InvalidOperationException();
  468. }
  469. });
  470. }
  471. public static void Frintm_S(AILEmitterCtx Context)
  472. {
  473. EmitScalarUnaryOpF(Context, () =>
  474. {
  475. EmitUnaryMathCall(Context, nameof(Math.Floor));
  476. });
  477. }
  478. public static void Frintm_V(AILEmitterCtx Context)
  479. {
  480. EmitVectorUnaryOpF(Context, () =>
  481. {
  482. EmitUnaryMathCall(Context, nameof(Math.Floor));
  483. });
  484. }
  485. public static void Frintn_S(AILEmitterCtx Context)
  486. {
  487. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  488. EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
  489. EmitRoundMathCall(Context, MidpointRounding.ToEven);
  490. EmitScalarSetF(Context, Op.Rd, Op.Size);
  491. }
  492. public static void Frintn_V(AILEmitterCtx Context)
  493. {
  494. EmitVectorUnaryOpF(Context, () =>
  495. {
  496. EmitRoundMathCall(Context, MidpointRounding.ToEven);
  497. });
  498. }
  499. public static void Frintp_S(AILEmitterCtx Context)
  500. {
  501. EmitScalarUnaryOpF(Context, () =>
  502. {
  503. EmitUnaryMathCall(Context, nameof(Math.Ceiling));
  504. });
  505. }
  506. public static void Frintp_V(AILEmitterCtx Context)
  507. {
  508. EmitVectorUnaryOpF(Context, () =>
  509. {
  510. EmitUnaryMathCall(Context, nameof(Math.Ceiling));
  511. });
  512. }
  513. public static void Frintx_S(AILEmitterCtx Context)
  514. {
  515. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  516. EmitScalarUnaryOpF(Context, () =>
  517. {
  518. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  519. Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
  520. if (Op.Size == 0)
  521. {
  522. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
  523. }
  524. else if (Op.Size == 1)
  525. {
  526. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
  527. }
  528. else
  529. {
  530. throw new InvalidOperationException();
  531. }
  532. });
  533. }
  534. public static void Frintx_V(AILEmitterCtx Context)
  535. {
  536. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  537. EmitVectorUnaryOpF(Context, () =>
  538. {
  539. Context.EmitLdarg(ATranslatedSub.StateArgIdx);
  540. Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
  541. if (Op.Size == 0)
  542. {
  543. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
  544. }
  545. else if (Op.Size == 1)
  546. {
  547. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
  548. }
  549. else
  550. {
  551. throw new InvalidOperationException();
  552. }
  553. });
  554. }
  555. public static void Frsqrte_S(AILEmitterCtx Context)
  556. {
  557. EmitScalarUnaryOpF(Context, () =>
  558. {
  559. EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
  560. });
  561. }
  562. public static void Frsqrte_V(AILEmitterCtx Context)
  563. {
  564. EmitVectorUnaryOpF(Context, () =>
  565. {
  566. EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.InvSqrtEstimate));
  567. });
  568. }
  569. public static void Frsqrts_S(AILEmitterCtx Context)
  570. {
  571. EmitFrsqrts(Context, 0, Scalar: true);
  572. }
  573. public static void Frsqrts_V(AILEmitterCtx Context)
  574. {
  575. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  576. int SizeF = Op.Size & 1;
  577. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  578. for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
  579. {
  580. EmitFrsqrts(Context, Index, Scalar: false);
  581. }
  582. if (Op.RegisterSize == ARegisterSize.SIMD64)
  583. {
  584. EmitVectorZeroUpper(Context, Op.Rd);
  585. }
  586. }
  587. private static void EmitFrsqrts(AILEmitterCtx Context, int Index, bool Scalar)
  588. {
  589. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  590. int SizeF = Op.Size & 1;
  591. if (SizeF == 0)
  592. {
  593. Context.EmitLdc_R4(3);
  594. }
  595. else /* if (SizeF == 1) */
  596. {
  597. Context.EmitLdc_R8(3);
  598. }
  599. EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
  600. EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
  601. Context.Emit(OpCodes.Mul);
  602. Context.Emit(OpCodes.Sub);
  603. if (SizeF == 0)
  604. {
  605. Context.EmitLdc_R4(0.5f);
  606. }
  607. else /* if (SizeF == 1) */
  608. {
  609. Context.EmitLdc_R8(0.5);
  610. }
  611. Context.Emit(OpCodes.Mul);
  612. if (Scalar)
  613. {
  614. EmitVectorZeroAll(Context, Op.Rd);
  615. }
  616. EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
  617. }
  618. public static void Fsqrt_S(AILEmitterCtx Context)
  619. {
  620. EmitScalarUnaryOpF(Context, () =>
  621. {
  622. EmitUnaryMathCall(Context, nameof(Math.Sqrt));
  623. });
  624. }
  625. public static void Fsub_S(AILEmitterCtx Context)
  626. {
  627. EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Sub));
  628. }
  629. public static void Fsub_V(AILEmitterCtx Context)
  630. {
  631. EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Sub));
  632. }
  633. public static void Mla_V(AILEmitterCtx Context)
  634. {
  635. EmitVectorTernaryOpZx(Context, () =>
  636. {
  637. Context.Emit(OpCodes.Mul);
  638. Context.Emit(OpCodes.Add);
  639. });
  640. }
  641. public static void Mla_Ve(AILEmitterCtx Context)
  642. {
  643. EmitVectorTernaryOpByElemZx(Context, () =>
  644. {
  645. Context.Emit(OpCodes.Mul);
  646. Context.Emit(OpCodes.Add);
  647. });
  648. }
  649. public static void Mls_V(AILEmitterCtx Context)
  650. {
  651. EmitVectorTernaryOpZx(Context, () =>
  652. {
  653. Context.Emit(OpCodes.Mul);
  654. Context.Emit(OpCodes.Sub);
  655. });
  656. }
  657. public static void Mul_V(AILEmitterCtx Context)
  658. {
  659. EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
  660. }
  661. public static void Mul_Ve(AILEmitterCtx Context)
  662. {
  663. EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul));
  664. }
  665. public static void Neg_S(AILEmitterCtx Context)
  666. {
  667. EmitScalarUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
  668. }
  669. public static void Neg_V(AILEmitterCtx Context)
  670. {
  671. EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
  672. }
  673. public static void Saddw_V(AILEmitterCtx Context)
  674. {
  675. EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
  676. }
  677. public static void Smax_V(AILEmitterCtx Context)
  678. {
  679. Type[] Types = new Type[] { typeof(long), typeof(long) };
  680. MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
  681. EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
  682. }
  683. public static void Smin_V(AILEmitterCtx Context)
  684. {
  685. Type[] Types = new Type[] { typeof(long), typeof(long) };
  686. MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
  687. EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
  688. }
  689. public static void Smlal_V(AILEmitterCtx Context)
  690. {
  691. EmitVectorWidenRnRmTernaryOpSx(Context, () =>
  692. {
  693. Context.Emit(OpCodes.Mul);
  694. Context.Emit(OpCodes.Add);
  695. });
  696. }
  697. public static void Smull_V(AILEmitterCtx Context)
  698. {
  699. EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
  700. }
  701. public static void Sub_S(AILEmitterCtx Context)
  702. {
  703. EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
  704. }
  705. public static void Sub_V(AILEmitterCtx Context)
  706. {
  707. EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
  708. }
  709. public static void Uabd_V(AILEmitterCtx Context)
  710. {
  711. EmitVectorBinaryOpZx(Context, () => EmitAbd(Context));
  712. }
  713. public static void Uabdl_V(AILEmitterCtx Context)
  714. {
  715. EmitVectorWidenRnRmBinaryOpZx(Context, () => EmitAbd(Context));
  716. }
  717. private static void EmitAbd(AILEmitterCtx Context)
  718. {
  719. Context.Emit(OpCodes.Sub);
  720. Type[] Types = new Type[] { typeof(long) };
  721. Context.EmitCall(typeof(Math).GetMethod(nameof(Math.Abs), Types));
  722. }
  723. public static void Uaddl_V(AILEmitterCtx Context)
  724. {
  725. EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
  726. }
  727. public static void Uaddlv_V(AILEmitterCtx Context)
  728. {
  729. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  730. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  731. EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
  732. for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
  733. {
  734. EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
  735. Context.Emit(OpCodes.Add);
  736. }
  737. EmitScalarSet(Context, Op.Rd, Op.Size + 1);
  738. }
  739. public static void Uaddw_V(AILEmitterCtx Context)
  740. {
  741. EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
  742. }
  743. public static void Uhadd_V(AILEmitterCtx Context)
  744. {
  745. EmitVectorBinaryOpZx(Context, () =>
  746. {
  747. Context.Emit(OpCodes.Add);
  748. Context.EmitLdc_I4(1);
  749. Context.Emit(OpCodes.Shr_Un);
  750. });
  751. }
  752. public static void Umull_V(AILEmitterCtx Context)
  753. {
  754. EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
  755. }
  756. }
  757. }