AInstEmitScalar.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  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. namespace ChocolArm64.Instruction
  8. {
  9. static partial class AInstEmit
  10. {
  11. public static void Addp_S(AILEmitterCtx Context)
  12. {
  13. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  14. Context.EmitLdvec(Op.Rn);
  15. Context.EmitLdc_I4(Op.Size);
  16. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Addp_S));
  17. Context.EmitStvec(Op.Rd);
  18. }
  19. public static void Dup_S(AILEmitterCtx Context)
  20. {
  21. AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
  22. Context.EmitLdvec(Op.Rn);
  23. Context.EmitLdc_I4(Op.DstIndex);
  24. Context.EmitLdc_I4(Op.Size);
  25. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Dup_S));
  26. Context.EmitStvec(Op.Rd);
  27. }
  28. public static void Fabs_S(AILEmitterCtx Context)
  29. {
  30. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  31. Context.EmitLdvecsf(Op.Rn);
  32. MethodInfo MthdInfo;
  33. if (Op.Size == 0)
  34. {
  35. MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Abs), new Type[] { typeof(float) });
  36. }
  37. else if (Op.Size == 1)
  38. {
  39. MthdInfo = typeof(Math).GetMethod(nameof(Math.Abs), new Type[] { typeof(double) });
  40. }
  41. else
  42. {
  43. throw new InvalidOperationException();
  44. }
  45. Context.EmitCall(MthdInfo);
  46. Context.EmitStvecsf(Op.Rd);
  47. }
  48. public static void Fadd_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Add);
  49. public static void Fccmp_S(AILEmitterCtx Context)
  50. {
  51. AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
  52. AILLabel LblTrue = new AILLabel();
  53. AILLabel LblEnd = new AILLabel();
  54. Context.EmitCondBranch(LblTrue, Op.Cond);
  55. //TODO: Share this logic with Ccmp.
  56. Context.EmitLdc_I4((Op.NZCV >> 0) & 1);
  57. Context.EmitStflg((int)APState.VBit);
  58. Context.EmitLdc_I4((Op.NZCV >> 1) & 1);
  59. Context.EmitStflg((int)APState.CBit);
  60. Context.EmitLdc_I4((Op.NZCV >> 2) & 1);
  61. Context.EmitStflg((int)APState.ZBit);
  62. Context.EmitLdc_I4((Op.NZCV >> 3) & 1);
  63. Context.EmitStflg((int)APState.NBit);
  64. Context.Emit(OpCodes.Br_S, LblEnd);
  65. Context.MarkLabel(LblTrue);
  66. Fcmp_S(Context);
  67. Context.MarkLabel(LblEnd);
  68. }
  69. public static void Fcmp_S(AILEmitterCtx Context)
  70. {
  71. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  72. bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
  73. //todo
  74. //Context.TryMarkCondWithoutCmp();
  75. void EmitLoadOpers()
  76. {
  77. Context.EmitLdvecsf(Op.Rn);
  78. if (CmpWithZero)
  79. {
  80. EmitLdcImmF(Context, 0, Op.Size);
  81. }
  82. else
  83. {
  84. Context.EmitLdvecsf(Op.Rm);
  85. }
  86. }
  87. //Z = Rn == Rm
  88. EmitLoadOpers();
  89. Context.Emit(OpCodes.Ceq);
  90. Context.Emit(OpCodes.Dup);
  91. Context.EmitStflg((int)APState.ZBit);
  92. //C = Rn >= Rm
  93. EmitLoadOpers();
  94. Context.Emit(OpCodes.Cgt);
  95. Context.Emit(OpCodes.Or);
  96. Context.EmitStflg((int)APState.CBit);
  97. //N = Rn < Rm
  98. EmitLoadOpers();
  99. Context.Emit(OpCodes.Clt);
  100. Context.EmitStflg((int)APState.NBit);
  101. //Handle NaN case. If any number is NaN, then NZCV = 0011.
  102. AILLabel LblNotNaN = new AILLabel();
  103. if (CmpWithZero)
  104. {
  105. EmitNaNCheck(Context, Op.Rn);
  106. }
  107. else
  108. {
  109. EmitNaNCheck(Context, Op.Rn);
  110. EmitNaNCheck(Context, Op.Rm);
  111. Context.Emit(OpCodes.Or);
  112. }
  113. Context.Emit(OpCodes.Brfalse_S, LblNotNaN);
  114. Context.EmitLdc_I4(1);
  115. Context.EmitLdc_I4(1);
  116. Context.EmitStflg((int)APState.CBit);
  117. Context.EmitStflg((int)APState.VBit);
  118. Context.MarkLabel(LblNotNaN);
  119. }
  120. public static void Fcmpe_S(AILEmitterCtx Context)
  121. {
  122. //TODO: Raise exception if value is NaN, how to handle exceptions?
  123. Fcmp_S(Context);
  124. }
  125. public static void Fcsel_S(AILEmitterCtx Context)
  126. {
  127. AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;
  128. AILLabel LblTrue = new AILLabel();
  129. AILLabel LblEnd = new AILLabel();
  130. Context.EmitCondBranch(LblTrue, Op.Cond);
  131. Context.EmitLdvecsf(Op.Rm);
  132. Context.EmitStvecsf(Op.Rd);
  133. Context.Emit(OpCodes.Br_S, LblEnd);
  134. Context.MarkLabel(LblTrue);
  135. Context.EmitLdvecsf(Op.Rn);
  136. Context.EmitStvecsf(Op.Rd);
  137. Context.MarkLabel(LblEnd);
  138. }
  139. public static void Fcvt_S(AILEmitterCtx Context)
  140. {
  141. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  142. Context.EmitLdvecsf(Op.Rn);
  143. EmitFloatCast(Context, Op.Opc);
  144. Context.EmitStvecsf(Op.Rd);
  145. }
  146. public static void Fcvtms_S(AILEmitterCtx Context) => EmitMathOpCvtToInt(Context, nameof(Math.Floor));
  147. public static void Fcvtps_S(AILEmitterCtx Context) => EmitMathOpCvtToInt(Context, nameof(Math.Ceiling));
  148. public static void Fcvtzs_S(AILEmitterCtx Context) => EmitFcvtz_(Context, true);
  149. public static void Fcvtzu_S(AILEmitterCtx Context) => EmitFcvtz_(Context, false);
  150. private static void EmitFcvtz_(AILEmitterCtx Context, bool Signed)
  151. {
  152. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  153. Context.EmitLdvecsf(Op.Rn);
  154. if (Signed)
  155. {
  156. EmitCvtToInt(Context, Op.Size);
  157. }
  158. else
  159. {
  160. EmitCvtToUInt(Context, Op.Size);
  161. }
  162. Context.EmitStintzr(Op.Rd);
  163. }
  164. public static void Fcvtzs_Fix(AILEmitterCtx Context) => EmitFcvtz__Fix(Context, true);
  165. public static void Fcvtzu_Fix(AILEmitterCtx Context) => EmitFcvtz__Fix(Context, false);
  166. private static void EmitFcvtz__Fix(AILEmitterCtx Context, bool Signed)
  167. {
  168. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  169. Context.EmitLdvecsf(Op.Rn);
  170. EmitLdcImmF(Context, 1L << Op.FBits, Op.Size);
  171. Context.Emit(OpCodes.Mul);
  172. if (Signed)
  173. {
  174. EmitCvtToInt(Context, Op.Size);
  175. }
  176. else
  177. {
  178. EmitCvtToUInt(Context, Op.Size);
  179. }
  180. Context.EmitStintzr(Op.Rd);
  181. }
  182. public static void Fdiv_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Div);
  183. public static void Fmadd_S(AILEmitterCtx Context)
  184. {
  185. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  186. Context.EmitLdvecsf(Op.Ra);
  187. Context.EmitLdvecsf(Op.Rn);
  188. Context.EmitLdvecsf(Op.Rm);
  189. Context.Emit(OpCodes.Mul);
  190. Context.Emit(OpCodes.Add);
  191. Context.EmitStvecsf(Op.Rd);
  192. }
  193. public static void Fmax_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Max));
  194. public static void Fmin_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Min));
  195. public static void Fmaxnm_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Max));
  196. public static void Fminnm_S(AILEmitterCtx Context) => EmitMathOp3(Context, nameof(Math.Min));
  197. public static void Fmov_S(AILEmitterCtx Context)
  198. {
  199. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  200. Context.EmitLdvecsf(Op.Rn);
  201. Context.EmitStvecsf(Op.Rd);
  202. }
  203. public static void Fmov_Si(AILEmitterCtx Context)
  204. {
  205. AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;
  206. Context.EmitLdc_I8(Op.Imm);
  207. Context.EmitLdc_I4(0);
  208. Context.EmitLdc_I4(Op.Size + 2);
  209. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S));
  210. Context.EmitStvec(Op.Rd);
  211. }
  212. public static void Fmov_Ftoi(AILEmitterCtx Context)
  213. {
  214. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  215. Context.EmitLdvecsi(Op.Rn);
  216. Context.EmitStintzr(Op.Rd);
  217. }
  218. public static void Fmov_Itof(AILEmitterCtx Context)
  219. {
  220. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  221. Context.EmitLdintzr(Op.Rn);
  222. Context.EmitStvecsi(Op.Rd);
  223. }
  224. public static void Fmov_Ftoi1(AILEmitterCtx Context)
  225. {
  226. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  227. Context.EmitLdvec(Op.Rn);
  228. Context.EmitLdc_I4(1);
  229. Context.EmitLdc_I4(3);
  230. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
  231. Context.EmitStintzr(Op.Rd);
  232. }
  233. public static void Fmov_Itof1(AILEmitterCtx Context)
  234. {
  235. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  236. Context.EmitLdintzr(Op.Rn);
  237. Context.EmitLdc_I4(1);
  238. Context.EmitLdc_I4(3);
  239. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S));
  240. Context.EmitStvec(Op.Rd);
  241. }
  242. public static void Fmsub_S(AILEmitterCtx Context)
  243. {
  244. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  245. Context.EmitLdvecsf(Op.Ra);
  246. Context.EmitLdvecsf(Op.Rn);
  247. Context.Emit(OpCodes.Neg);
  248. Context.EmitLdvecsf(Op.Rm);
  249. Context.Emit(OpCodes.Mul);
  250. Context.Emit(OpCodes.Sub);
  251. Context.EmitStvecsf(Op.Rd);
  252. }
  253. public static void Fmul_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Mul);
  254. public static void Fneg_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Neg);
  255. public static void Fnmul_S(AILEmitterCtx Context)
  256. {
  257. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  258. Context.EmitLdvecsf(Op.Rn);
  259. Context.EmitLdvecsf(Op.Rm);
  260. Context.Emit(OpCodes.Mul);
  261. Context.Emit(OpCodes.Neg);
  262. Context.EmitStvecsf(Op.Rd);
  263. }
  264. public static void Frinta_S(AILEmitterCtx Context)
  265. {
  266. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  267. Context.EmitLdvecsf(Op.Rn);
  268. Context.EmitLdc_I4((int)MidpointRounding.AwayFromZero);
  269. MethodInfo MthdInfo;
  270. if (Op.Size == 0)
  271. {
  272. Type[] Types = new Type[] { typeof(float), typeof(MidpointRounding) };
  273. MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
  274. }
  275. else if (Op.Size == 1)
  276. {
  277. Type[] Types = new Type[] { typeof(double), typeof(MidpointRounding) };
  278. MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
  279. }
  280. else
  281. {
  282. throw new InvalidOperationException();
  283. }
  284. Context.EmitCall(MthdInfo);
  285. Context.EmitStvecsf(Op.Rd);
  286. }
  287. public static void Frintm_S(AILEmitterCtx Context)
  288. {
  289. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  290. Context.EmitLdvecsf(Op.Rn);
  291. MethodInfo MthdInfo;
  292. if (Op.Size == 0)
  293. {
  294. MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Floor), new Type[] { typeof(float) });
  295. }
  296. else if (Op.Size == 1)
  297. {
  298. MthdInfo = typeof(Math).GetMethod(nameof(Math.Floor), new Type[] { typeof(double) });
  299. }
  300. else
  301. {
  302. throw new InvalidOperationException();
  303. }
  304. Context.EmitCall(MthdInfo);
  305. Context.EmitStvecsf(Op.Rd);
  306. }
  307. public static void Fsqrt_S(AILEmitterCtx Context) => EmitMathOp2(Context, nameof(Math.Sqrt));
  308. public static void Fsub_S(AILEmitterCtx Context) => EmitScalarOp(Context, OpCodes.Sub);
  309. public static void Scvtf_Gp(AILEmitterCtx Context)
  310. {
  311. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  312. Context.EmitLdintzr(Op.Rn);
  313. EmitFloatCast(Context, Op.Size);
  314. Context.EmitStvecsf(Op.Rd);
  315. }
  316. public static void Scvtf_S(AILEmitterCtx Context)
  317. {
  318. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  319. Context.EmitLdvecsi(Op.Rn);
  320. EmitFloatCast(Context, Op.Size);
  321. Context.EmitStvecsf(Op.Rd);
  322. }
  323. public static void Shl_S(AILEmitterCtx Context)
  324. {
  325. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  326. Context.EmitLdvecsi(Op.Rn);
  327. Context.EmitLdc_I4(Op.Imm - (8 << Op.Size));
  328. Context.Emit(OpCodes.Shl);
  329. Context.EmitStvecsi(Op.Rd);
  330. }
  331. public static void Sshr_S(AILEmitterCtx Context)
  332. {
  333. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  334. Context.EmitLdvecsi(Op.Rn);
  335. Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
  336. Context.Emit(OpCodes.Shr);
  337. Context.EmitStvecsi(Op.Rd);
  338. }
  339. public static void Sub_S(AILEmitterCtx Context)
  340. {
  341. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  342. Context.EmitLdvecsi(Op.Rn);
  343. Context.EmitLdvecsi(Op.Rm);
  344. Context.Emit(OpCodes.Sub);
  345. Context.EmitStvecsi(Op.Rd);
  346. }
  347. public static void Ucvtf_Gp(AILEmitterCtx Context)
  348. {
  349. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  350. Context.EmitLdintzr(Op.Rn);
  351. Context.Emit(OpCodes.Conv_R_Un);
  352. EmitFloatCast(Context, Op.Size);
  353. Context.EmitStvecsf(Op.Rd);
  354. }
  355. private static void EmitScalarOp(AILEmitterCtx Context, OpCode ILOp)
  356. {
  357. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  358. Context.EmitLdvecsf(Op.Rn);
  359. //Negate and Not are the only unary operations supported on IL.
  360. //"Not" doesn't work with floats, so we don't need to compare it.
  361. if (ILOp != OpCodes.Neg)
  362. {
  363. Context.EmitLdvecsf(Op.Rm);
  364. }
  365. Context.Emit(ILOp);
  366. Context.EmitStvecsf(Op.Rd);
  367. }
  368. private static void EmitMathOp2(AILEmitterCtx Context, string Name)
  369. {
  370. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  371. Context.EmitLdvecsf(Op.Rn);
  372. EmitMathOpCall(Context, Name);
  373. Context.EmitStvecsf(Op.Rd);
  374. }
  375. private static void EmitMathOp3(AILEmitterCtx Context, string Name)
  376. {
  377. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  378. Context.EmitLdvecsf(Op.Rn);
  379. Context.EmitLdvecsf(Op.Rm);
  380. MethodInfo MthdInfo;
  381. if (Op.Size == 0)
  382. {
  383. MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float), typeof(float) });
  384. }
  385. else if (Op.Size == 1)
  386. {
  387. MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double), typeof(double) });
  388. }
  389. else
  390. {
  391. throw new InvalidOperationException();
  392. }
  393. Context.EmitCall(MthdInfo);
  394. Context.EmitStvecsf(Op.Rd);
  395. }
  396. public static void EmitMathOpCvtToInt(AILEmitterCtx Context, string Name)
  397. {
  398. AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;
  399. Context.EmitLdvecsf(Op.Rn);
  400. EmitMathOpCall(Context, Name);
  401. EmitCvtToInt(Context, Op.Size);
  402. Context.EmitStintzr(Op.Rd);
  403. }
  404. private static void EmitMathOpCall(AILEmitterCtx Context, string Name)
  405. {
  406. IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
  407. MethodInfo MthdInfo;
  408. if (Op.Size == 0)
  409. {
  410. MthdInfo = typeof(MathF).GetMethod(Name);
  411. }
  412. else if (Op.Size == 1)
  413. {
  414. MthdInfo = typeof(Math).GetMethod(Name);
  415. }
  416. else
  417. {
  418. throw new InvalidOperationException();
  419. }
  420. Context.EmitCall(MthdInfo);
  421. }
  422. private static void EmitCvtToInt(AILEmitterCtx Context, int Size)
  423. {
  424. if (Size < 0 || Size > 1)
  425. {
  426. throw new ArgumentOutOfRangeException(nameof(Size));
  427. }
  428. Context.EmitLdc_I4(0);
  429. if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
  430. {
  431. if (Size == 0)
  432. {
  433. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToInt32));
  434. }
  435. else /* if (Size == 1) */
  436. {
  437. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToInt32));
  438. }
  439. }
  440. else
  441. {
  442. if (Size == 0)
  443. {
  444. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToInt64));
  445. }
  446. else /* if (Size == 1) */
  447. {
  448. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToInt64));
  449. }
  450. }
  451. }
  452. private static void EmitCvtToUInt(AILEmitterCtx Context, int Size)
  453. {
  454. if (Size < 0 || Size > 1)
  455. {
  456. throw new ArgumentOutOfRangeException(nameof(Size));
  457. }
  458. Context.EmitLdc_I4(0);
  459. if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
  460. {
  461. if (Size == 0)
  462. {
  463. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt32));
  464. }
  465. else /* if (Size == 1) */
  466. {
  467. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt32));
  468. }
  469. }
  470. else
  471. {
  472. if (Size == 0)
  473. {
  474. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt64));
  475. }
  476. else /* if (Size == 1) */
  477. {
  478. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt64));
  479. }
  480. }
  481. }
  482. private static void EmitFloatCast(AILEmitterCtx Context, int Size)
  483. {
  484. if (Size == 0)
  485. {
  486. Context.Emit(OpCodes.Conv_R4);
  487. }
  488. else if (Size == 1)
  489. {
  490. Context.Emit(OpCodes.Conv_R8);
  491. }
  492. else
  493. {
  494. throw new ArgumentOutOfRangeException(nameof(Size));
  495. }
  496. }
  497. private static void EmitLdcImmF(AILEmitterCtx Context, double ImmF, int Size)
  498. {
  499. if (Size == 0)
  500. {
  501. Context.EmitLdc_R4((float)ImmF);
  502. }
  503. else if (Size == 1)
  504. {
  505. Context.EmitLdc_R8(ImmF);
  506. }
  507. else
  508. {
  509. throw new ArgumentOutOfRangeException(nameof(Size));
  510. }
  511. }
  512. private static void EmitNaNCheck(AILEmitterCtx Context, int Index)
  513. {
  514. IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
  515. Context.EmitLdvecsf(Index);
  516. if (Op.Size == 0)
  517. {
  518. Context.EmitCall(typeof(float), nameof(float.IsNaN));
  519. }
  520. else if (Op.Size == 1)
  521. {
  522. Context.EmitCall(typeof(double), nameof(double.IsNaN));
  523. }
  524. else
  525. {
  526. throw new InvalidOperationException();
  527. }
  528. }
  529. }
  530. }