AInstEmitSimd.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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.AInstEmitMemoryHelper;
  8. namespace ChocolArm64.Instruction
  9. {
  10. static partial class AInstEmit
  11. {
  12. public static void Add_V(AILEmitterCtx Context)
  13. {
  14. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.Add));
  15. }
  16. public static void Addp_V(AILEmitterCtx Context)
  17. {
  18. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  19. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  20. int Elems = Bytes >> Op.Size;
  21. int Half = Elems >> 1;
  22. for (int Index = 0; Index < Elems; Index++)
  23. {
  24. int Elem = (Index & (Half - 1)) << 1;
  25. EmitVectorExtractZx(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 0, Op.Size);
  26. EmitVectorExtractZx(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 1, Op.Size);
  27. Context.Emit(OpCodes.Add);
  28. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  29. }
  30. if (Op.RegisterSize == ARegisterSize.SIMD64)
  31. {
  32. EmitVectorZeroUpper(Context, Op.Rd);
  33. }
  34. }
  35. public static void Addv_V(AILEmitterCtx Context)
  36. {
  37. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  38. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  39. int Results = 0;
  40. for (int Size = Op.Size; Size < 4; Size++)
  41. {
  42. for (int Index = 0; Index < (Bytes >> Size); Index += 2)
  43. {
  44. EmitVectorExtractZx(Context, Op.Rn, Index + 0, Size);
  45. EmitVectorExtractZx(Context, Op.Rn, Index + 1, Size);
  46. Context.Emit(OpCodes.Add);
  47. Results++;
  48. }
  49. }
  50. while (--Results > 0)
  51. {
  52. Context.Emit(OpCodes.Add);
  53. }
  54. EmitVectorZeroLower(Context, Op.Rd);
  55. EmitVectorZeroUpper(Context, Op.Rd);
  56. EmitVectorInsert(Context, Op.Rd, 0, Op.Size);
  57. }
  58. public static void And_V(AILEmitterCtx Context)
  59. {
  60. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.And));
  61. }
  62. public static void Bic_V(AILEmitterCtx Context)
  63. {
  64. EmitVectorBinaryZx(Context, () =>
  65. {
  66. Context.Emit(OpCodes.Not);
  67. Context.Emit(OpCodes.And);
  68. });
  69. }
  70. public static void Bic_Vi(AILEmitterCtx Context)
  71. {
  72. EmitVectorImmBinary(Context, () =>
  73. {
  74. Context.Emit(OpCodes.Not);
  75. Context.Emit(OpCodes.And);
  76. });
  77. }
  78. public static void Bsl_V(AILEmitterCtx Context)
  79. {
  80. EmitVectorTernaryZx(Context, () =>
  81. {
  82. Context.EmitSttmp();
  83. Context.EmitLdtmp();
  84. Context.Emit(OpCodes.Xor);
  85. Context.Emit(OpCodes.And);
  86. Context.EmitLdtmp();
  87. Context.Emit(OpCodes.Xor);
  88. });
  89. }
  90. public static void Cmeq_V(AILEmitterCtx Context)
  91. {
  92. EmitVectorCmp(Context, OpCodes.Beq_S);
  93. }
  94. public static void Cmge_V(AILEmitterCtx Context)
  95. {
  96. EmitVectorCmp(Context, OpCodes.Bge_S);
  97. }
  98. public static void Cmgt_V(AILEmitterCtx Context)
  99. {
  100. EmitVectorCmp(Context, OpCodes.Bgt_S);
  101. }
  102. public static void Cmhi_V(AILEmitterCtx Context)
  103. {
  104. EmitVectorCmp(Context, OpCodes.Bgt_Un_S);
  105. }
  106. public static void Cmhs_V(AILEmitterCtx Context)
  107. {
  108. EmitVectorCmp(Context, OpCodes.Bge_Un_S);
  109. }
  110. public static void Cmle_V(AILEmitterCtx Context)
  111. {
  112. EmitVectorCmp(Context, OpCodes.Ble_S);
  113. }
  114. public static void Cmlt_V(AILEmitterCtx Context)
  115. {
  116. EmitVectorCmp(Context, OpCodes.Blt_S);
  117. }
  118. public static void Cnt_V(AILEmitterCtx Context)
  119. {
  120. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  121. int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
  122. for (int Index = 0; Index < Elems; Index++)
  123. {
  124. EmitVectorExtractZx(Context, Op.Rn, Index, 0);
  125. Context.Emit(OpCodes.Conv_U1);
  126. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountSetBits8));
  127. Context.Emit(OpCodes.Conv_U8);
  128. EmitVectorInsert(Context, Op.Rd, Index, 0);
  129. }
  130. }
  131. public static void Dup_Gp(AILEmitterCtx Context)
  132. {
  133. AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
  134. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  135. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  136. {
  137. Context.EmitLdintzr(Op.Rn);
  138. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  139. }
  140. if (Op.RegisterSize == ARegisterSize.SIMD64)
  141. {
  142. EmitVectorZeroUpper(Context, Op.Rd);
  143. }
  144. }
  145. public static void Dup_V(AILEmitterCtx Context)
  146. {
  147. AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
  148. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  149. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  150. {
  151. EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
  152. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  153. }
  154. if (Op.RegisterSize == ARegisterSize.SIMD64)
  155. {
  156. EmitVectorZeroUpper(Context, Op.Rd);
  157. }
  158. }
  159. public static void Eor_V(AILEmitterCtx Context)
  160. {
  161. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.Xor));
  162. }
  163. public static void Fadd_V(AILEmitterCtx Context)
  164. {
  165. EmitVectorBinaryF(Context, () => Context.Emit(OpCodes.Add));
  166. }
  167. public static void Fcvtzs_V(AILEmitterCtx Context)
  168. {
  169. EmitVectorFcvt(Context, Signed: true);
  170. }
  171. public static void Fcvtzu_V(AILEmitterCtx Context)
  172. {
  173. EmitVectorFcvt(Context, Signed: false);
  174. }
  175. public static void Fmla_V(AILEmitterCtx Context)
  176. {
  177. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  178. EmitVectorTernaryF(Context, () =>
  179. {
  180. Context.Emit(OpCodes.Mul);
  181. Context.Emit(OpCodes.Add);
  182. });
  183. }
  184. public static void Fmla_Ve(AILEmitterCtx Context)
  185. {
  186. EmitVectorTernaryByElemF(Context, () =>
  187. {
  188. Context.Emit(OpCodes.Mul);
  189. Context.Emit(OpCodes.Add);
  190. });
  191. }
  192. public static void Fmov_V(AILEmitterCtx Context)
  193. {
  194. AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
  195. Context.EmitLdc_I8(Op.Imm);
  196. Context.EmitLdc_I4(Op.Size + 2);
  197. ASoftFallback.EmitCall(Context,
  198. nameof(ASoftFallback.Dup_Gp64),
  199. nameof(ASoftFallback.Dup_Gp128));
  200. Context.EmitStvec(Op.Rd);
  201. }
  202. public static void Fmul_V(AILEmitterCtx Context)
  203. {
  204. EmitVectorBinaryF(Context, () => Context.Emit(OpCodes.Mul));
  205. }
  206. public static void Fmul_Ve(AILEmitterCtx Context)
  207. {
  208. EmitVectorBinaryByElemF(Context, () => Context.Emit(OpCodes.Mul));
  209. }
  210. public static void Fsub_V(AILEmitterCtx Context)
  211. {
  212. EmitVectorBinaryF(Context, () => Context.Emit(OpCodes.Sub));
  213. }
  214. public static void Ins_Gp(AILEmitterCtx Context)
  215. {
  216. AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
  217. Context.EmitLdintzr(Op.Rn);
  218. EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
  219. }
  220. public static void Ins_V(AILEmitterCtx Context)
  221. {
  222. AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
  223. EmitVectorExtractZx(Context, Op.Rn, Op.SrcIndex, Op.Size);
  224. EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size);
  225. }
  226. public static void Ld__Vms(AILEmitterCtx Context)
  227. {
  228. EmitSimdMemMs(Context, IsLoad: true);
  229. }
  230. public static void Ld__Vss(AILEmitterCtx Context)
  231. {
  232. EmitSimdMemSs(Context, IsLoad: true);
  233. }
  234. public static void Mla_V(AILEmitterCtx Context)
  235. {
  236. EmitVectorTernaryZx(Context, () =>
  237. {
  238. Context.Emit(OpCodes.Mul);
  239. Context.Emit(OpCodes.Add);
  240. });
  241. }
  242. public static void Movi_V(AILEmitterCtx Context)
  243. {
  244. EmitVectorImmUnary(Context, () => { });
  245. }
  246. public static void Mul_V(AILEmitterCtx Context)
  247. {
  248. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.Mul));
  249. }
  250. public static void Mvni_V(AILEmitterCtx Context)
  251. {
  252. EmitVectorImmUnary(Context, () => Context.Emit(OpCodes.Not));
  253. }
  254. public static void Neg_V(AILEmitterCtx Context)
  255. {
  256. EmitVectorUnarySx(Context, () => Context.Emit(OpCodes.Neg));
  257. }
  258. public static void Not_V(AILEmitterCtx Context)
  259. {
  260. EmitVectorUnaryZx(Context, () => Context.Emit(OpCodes.Not));
  261. }
  262. public static void Orr_V(AILEmitterCtx Context)
  263. {
  264. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.Or));
  265. }
  266. public static void Orr_Vi(AILEmitterCtx Context)
  267. {
  268. EmitVectorImmBinary(Context, () => Context.Emit(OpCodes.Or));
  269. }
  270. public static void Saddw_V(AILEmitterCtx Context)
  271. {
  272. EmitVectorWidenBinarySx(Context, () => Context.Emit(OpCodes.Add));
  273. }
  274. public static void Scvtf_V(AILEmitterCtx Context)
  275. {
  276. EmitVectorCvtf(Context, Signed: true);
  277. }
  278. public static void Shl_V(AILEmitterCtx Context)
  279. {
  280. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  281. int Shift = Op.Imm - (8 << Op.Size);
  282. EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
  283. }
  284. public static void Shrn_V(AILEmitterCtx Context)
  285. {
  286. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  287. int Shift = (8 << (Op.Size + 1)) - Op.Imm;
  288. EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), Shift);
  289. }
  290. public static void Smax_V(AILEmitterCtx Context)
  291. {
  292. Type[] Types = new Type[] { typeof(long), typeof(long) };
  293. MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Max), Types);
  294. EmitVectorBinarySx(Context, () => Context.EmitCall(MthdInfo));
  295. }
  296. public static void Smin_V(AILEmitterCtx Context)
  297. {
  298. Type[] Types = new Type[] { typeof(long), typeof(long) };
  299. MethodInfo MthdInfo = typeof(Math).GetMethod(nameof(Math.Min), Types);
  300. EmitVectorBinarySx(Context, () => Context.EmitCall(MthdInfo));
  301. }
  302. public static void Sshl_V(AILEmitterCtx Context)
  303. {
  304. EmitVectorShl(Context, Signed: true);
  305. }
  306. public static void Sshll_V(AILEmitterCtx Context)
  307. {
  308. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  309. int Shift = Op.Imm - (8 << Op.Size);
  310. EmitVectorShImmWidenBinarySx(Context, () => Context.Emit(OpCodes.Shl), Shift);
  311. }
  312. public static void Sshr_V(AILEmitterCtx Context)
  313. {
  314. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  315. int Shift = (8 << (Op.Size + 1)) - Op.Imm;
  316. EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
  317. }
  318. public static void St__Vms(AILEmitterCtx Context)
  319. {
  320. EmitSimdMemMs(Context, IsLoad: false);
  321. }
  322. public static void St__Vss(AILEmitterCtx Context)
  323. {
  324. EmitSimdMemSs(Context, IsLoad: false);
  325. }
  326. public static void Sub_V(AILEmitterCtx Context)
  327. {
  328. EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.Sub));
  329. }
  330. public static void Tbl_V(AILEmitterCtx Context)
  331. {
  332. AOpCodeSimdTbl Op = (AOpCodeSimdTbl)Context.CurrOp;
  333. Context.EmitLdvec(Op.Rm);
  334. for (int Index = 0; Index < Op.Size; Index++)
  335. {
  336. Context.EmitLdvec((Op.Rn + Index) & 0x1f);
  337. }
  338. switch (Op.Size)
  339. {
  340. case 1: ASoftFallback.EmitCall(Context,
  341. nameof(ASoftFallback.Tbl1_V64),
  342. nameof(ASoftFallback.Tbl1_V128)); break;
  343. case 2: ASoftFallback.EmitCall(Context,
  344. nameof(ASoftFallback.Tbl2_V64),
  345. nameof(ASoftFallback.Tbl2_V128)); break;
  346. case 3: ASoftFallback.EmitCall(Context,
  347. nameof(ASoftFallback.Tbl3_V64),
  348. nameof(ASoftFallback.Tbl3_V128)); break;
  349. case 4: ASoftFallback.EmitCall(Context,
  350. nameof(ASoftFallback.Tbl4_V64),
  351. nameof(ASoftFallback.Tbl4_V128)); break;
  352. default: throw new InvalidOperationException();
  353. }
  354. Context.EmitStvec(Op.Rd);
  355. }
  356. public static void Uaddlv_V(AILEmitterCtx Context)
  357. {
  358. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  359. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  360. EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
  361. for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
  362. {
  363. EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
  364. Context.Emit(OpCodes.Add);
  365. }
  366. EmitVectorZeroLower(Context, Op.Rd);
  367. EmitVectorZeroUpper(Context, Op.Rd);
  368. EmitVectorInsert(Context, Op.Rd, 0, Op.Size);
  369. }
  370. public static void Uaddw_V(AILEmitterCtx Context)
  371. {
  372. EmitVectorWidenBinaryZx(Context, () => Context.Emit(OpCodes.Add));
  373. }
  374. public static void Ucvtf_V(AILEmitterCtx Context)
  375. {
  376. EmitVectorCvtf(Context, Signed: false);
  377. }
  378. public static void Ushl_V(AILEmitterCtx Context)
  379. {
  380. EmitVectorShl(Context, Signed: false);
  381. }
  382. public static void Ushll_V(AILEmitterCtx Context)
  383. {
  384. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  385. int Shift = Op.Imm - (8 << Op.Size);
  386. EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
  387. }
  388. public static void Ushr_V(AILEmitterCtx Context)
  389. {
  390. EmitVectorShr(Context, ShrFlags.None);
  391. }
  392. public static void Usra_V(AILEmitterCtx Context)
  393. {
  394. EmitVectorShr(Context, ShrFlags.Accumulate);
  395. }
  396. [Flags]
  397. private enum ShrFlags
  398. {
  399. None = 0,
  400. Signed = 1 << 0,
  401. Rounding = 1 << 1,
  402. Accumulate = 1 << 2
  403. }
  404. private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags)
  405. {
  406. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  407. int Shift = (8 << (Op.Size + 1)) - Op.Imm;
  408. if (Flags.HasFlag(ShrFlags.Accumulate))
  409. {
  410. Action Emit = () =>
  411. {
  412. Context.EmitLdc_I4(Shift);
  413. Context.Emit(OpCodes.Shr_Un);
  414. Context.Emit(OpCodes.Add);
  415. };
  416. EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
  417. }
  418. else
  419. {
  420. EmitVectorUnaryZx(Context, () =>
  421. {
  422. Context.EmitLdc_I4(Shift);
  423. Context.Emit(OpCodes.Shr_Un);
  424. });
  425. }
  426. }
  427. public static void Uzp1_V(AILEmitterCtx Context)
  428. {
  429. EmitVectorUnzip(Context, Part: 0);
  430. }
  431. public static void Uzp2_V(AILEmitterCtx Context)
  432. {
  433. EmitVectorUnzip(Context, Part: 1);
  434. }
  435. private static void EmitVectorUnzip(AILEmitterCtx Context, int Part)
  436. {
  437. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  438. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  439. int Elems = Bytes >> Op.Size;
  440. int Half = Elems >> 1;
  441. for (int Index = 0; Index < Elems; Index++)
  442. {
  443. int Elem = Part + ((Index & (Half - 1)) << 1);
  444. EmitVectorExtractZx(Context, Index < Half ? Op.Rn : Op.Rm, Elem, Op.Size);
  445. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  446. }
  447. if (Op.RegisterSize == ARegisterSize.SIMD64)
  448. {
  449. EmitVectorZeroUpper(Context, Op.Rd);
  450. }
  451. }
  452. public static void Xtn_V(AILEmitterCtx Context)
  453. {
  454. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  455. int Elems = 8 >> Op.Size;
  456. int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
  457. for (int Index = 0; Index < Elems; Index++)
  458. {
  459. EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1);
  460. EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size);
  461. }
  462. if (Part == 0)
  463. {
  464. EmitVectorZeroUpper(Context, Op.Rd);
  465. }
  466. }
  467. private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
  468. {
  469. AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp;
  470. int Offset = 0;
  471. for (int Rep = 0; Rep < Op.Reps; Rep++)
  472. for (int Elem = 0; Elem < Op.Elems; Elem++)
  473. for (int SElem = 0; SElem < Op.SElems; SElem++)
  474. {
  475. int Rtt = (Op.Rt + Rep + SElem) & 0x1f;
  476. if (IsLoad)
  477. {
  478. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  479. Context.EmitLdint(Op.Rn);
  480. Context.EmitLdc_I8(Offset);
  481. Context.Emit(OpCodes.Add);
  482. EmitReadZxCall(Context, Op.Size);
  483. EmitVectorInsert(Context, Rtt, Elem, Op.Size);
  484. if (Op.RegisterSize == ARegisterSize.SIMD64 && Elem == Op.Elems - 1)
  485. {
  486. EmitVectorZeroUpper(Context, Rtt);
  487. }
  488. }
  489. else
  490. {
  491. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  492. Context.EmitLdint(Op.Rn);
  493. Context.EmitLdc_I8(Offset);
  494. Context.Emit(OpCodes.Add);
  495. EmitVectorExtractZx(Context, Rtt, Elem, Op.Size);
  496. EmitWriteCall(Context, Op.Size);
  497. }
  498. Offset += 1 << Op.Size;
  499. }
  500. if (Op.WBack)
  501. {
  502. EmitSimdMemWBack(Context, Offset);
  503. }
  504. }
  505. private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
  506. {
  507. AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
  508. //TODO: Replicate mode.
  509. int Offset = 0;
  510. for (int SElem = 0; SElem < Op.SElems; SElem++)
  511. {
  512. int Rt = (Op.Rt + SElem) & 0x1f;
  513. if (IsLoad)
  514. {
  515. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  516. Context.EmitLdint(Op.Rn);
  517. Context.EmitLdc_I8(Offset);
  518. Context.Emit(OpCodes.Add);
  519. EmitReadZxCall(Context, Op.Size);
  520. EmitVectorInsert(Context, Rt, Op.Index, Op.Size);
  521. if (Op.RegisterSize == ARegisterSize.SIMD64)
  522. {
  523. EmitVectorZeroUpper(Context, Rt);
  524. }
  525. }
  526. else
  527. {
  528. Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
  529. Context.EmitLdint(Op.Rn);
  530. Context.EmitLdc_I8(Offset);
  531. Context.Emit(OpCodes.Add);
  532. EmitVectorExtractZx(Context, Rt, Op.Index, Op.Size);
  533. EmitWriteCall(Context, Op.Size);
  534. }
  535. Offset += 1 << Op.Size;
  536. }
  537. if (Op.WBack)
  538. {
  539. EmitSimdMemWBack(Context, Offset);
  540. }
  541. }
  542. private static void EmitSimdMemWBack(AILEmitterCtx Context, int Offset)
  543. {
  544. AOpCodeMemReg Op = (AOpCodeMemReg)Context.CurrOp;
  545. Context.EmitLdint(Op.Rn);
  546. if (Op.Rm != ARegisters.ZRIndex)
  547. {
  548. Context.EmitLdint(Op.Rm);
  549. }
  550. else
  551. {
  552. Context.EmitLdc_I8(Offset);
  553. }
  554. Context.Emit(OpCodes.Add);
  555. Context.EmitStint(Op.Rn);
  556. }
  557. private static void EmitVectorCmp(AILEmitterCtx Context, OpCode ILOp)
  558. {
  559. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  560. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  561. ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
  562. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  563. {
  564. EmitVectorExtractSx(Context, Op.Rn, Index, Op.Size);
  565. if (Op is AOpCodeSimdReg BinOp)
  566. {
  567. EmitVectorExtractSx(Context, BinOp.Rm, Index, Op.Size);
  568. }
  569. else
  570. {
  571. Context.EmitLdc_I8(0);
  572. }
  573. AILLabel LblTrue = new AILLabel();
  574. AILLabel LblEnd = new AILLabel();
  575. Context.Emit(ILOp, LblTrue);
  576. EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0);
  577. Context.Emit(OpCodes.Br_S, LblEnd);
  578. Context.MarkLabel(LblTrue);
  579. EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask);
  580. Context.MarkLabel(LblEnd);
  581. }
  582. if (Op.RegisterSize == ARegisterSize.SIMD64)
  583. {
  584. EmitVectorZeroUpper(Context, Op.Rd);
  585. }
  586. }
  587. private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
  588. {
  589. //This instruction shifts the value on vector A by the number of bits
  590. //specified on the signed, lower 8 bits of vector B. If the shift value
  591. //is greater or equal to the data size of each lane, then the result is zero.
  592. //Additionally, negative shifts produces right shifts by the negated shift value.
  593. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  594. int MaxShift = 8 << Op.Size;
  595. Action Emit = () =>
  596. {
  597. AILLabel LblShl = new AILLabel();
  598. AILLabel LblZero = new AILLabel();
  599. AILLabel LblEnd = new AILLabel();
  600. void EmitShift(OpCode ILOp)
  601. {
  602. Context.Emit(OpCodes.Dup);
  603. Context.EmitLdc_I4(MaxShift);
  604. Context.Emit(OpCodes.Bge_S, LblZero);
  605. Context.Emit(ILOp);
  606. Context.Emit(OpCodes.Br_S, LblEnd);
  607. }
  608. Context.Emit(OpCodes.Conv_I1);
  609. Context.Emit(OpCodes.Dup);
  610. Context.EmitLdc_I4(0);
  611. Context.Emit(OpCodes.Bge_S, LblShl);
  612. Context.Emit(OpCodes.Neg);
  613. EmitShift(Signed
  614. ? OpCodes.Shr
  615. : OpCodes.Shr_Un);
  616. Context.MarkLabel(LblShl);
  617. EmitShift(OpCodes.Shl);
  618. Context.MarkLabel(LblZero);
  619. Context.Emit(OpCodes.Pop);
  620. Context.Emit(OpCodes.Pop);
  621. Context.EmitLdc_I8(0);
  622. Context.MarkLabel(LblEnd);
  623. };
  624. if (Signed)
  625. {
  626. EmitVectorBinarySx(Context, Emit);
  627. }
  628. else
  629. {
  630. EmitVectorBinaryZx(Context, Emit);
  631. }
  632. }
  633. private static void EmitVectorFcvt(AILEmitterCtx Context, bool Signed)
  634. {
  635. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  636. int SizeF = Op.Size & 1;
  637. int SizeI = SizeF + 2;
  638. int FBits = GetFBits(Context);
  639. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  640. for (int Index = 0; Index < (Bytes >> SizeI); Index++)
  641. {
  642. EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
  643. Context.EmitLdc_I4(FBits);
  644. if (SizeF == 0)
  645. {
  646. ASoftFallback.EmitCall(Context, Signed
  647. ? nameof(ASoftFallback.SatSingleToInt32)
  648. : nameof(ASoftFallback.SatSingleToUInt32));
  649. }
  650. else if (SizeF == 1)
  651. {
  652. ASoftFallback.EmitCall(Context, Signed
  653. ? nameof(ASoftFallback.SatDoubleToInt64)
  654. : nameof(ASoftFallback.SatDoubleToUInt64));
  655. }
  656. EmitVectorInsert(Context, Op.Rd, Index, SizeI);
  657. }
  658. if (Op.RegisterSize == ARegisterSize.SIMD64)
  659. {
  660. EmitVectorZeroUpper(Context, Op.Rd);
  661. }
  662. }
  663. private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed)
  664. {
  665. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  666. int SizeF = Op.Size & 1;
  667. int SizeI = SizeF + 2;
  668. int FBits = GetFBits(Context);
  669. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  670. for (int Index = 0; Index < (Bytes >> SizeI); Index++)
  671. {
  672. EmitVectorExtract(Context, Op.Rn, Index, SizeI, Signed);
  673. Context.EmitLdc_I4(FBits);
  674. if (SizeF == 0)
  675. {
  676. Context.Emit(OpCodes.Conv_I4);
  677. ASoftFallback.EmitCall(Context, Signed
  678. ? nameof(ASoftFallback.Int32ToSingle)
  679. : nameof(ASoftFallback.UInt32ToSingle));
  680. }
  681. else if (SizeF == 1)
  682. {
  683. ASoftFallback.EmitCall(Context, Signed
  684. ? nameof(ASoftFallback.Int64ToDouble)
  685. : nameof(ASoftFallback.UInt64ToDouble));
  686. }
  687. EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
  688. }
  689. if (Op.RegisterSize == ARegisterSize.SIMD64)
  690. {
  691. EmitVectorZeroUpper(Context, Op.Rd);
  692. }
  693. }
  694. private static int GetFBits(AILEmitterCtx Context)
  695. {
  696. if (Context.CurrOp is AOpCodeSimdShImm Op)
  697. {
  698. return (8 << (Op.Size + 1)) - Op.Imm;
  699. }
  700. return 0;
  701. }
  702. [Flags]
  703. private enum OperFlags
  704. {
  705. Rd = 1 << 0,
  706. Rn = 1 << 1,
  707. Rm = 1 << 2,
  708. RnRm = Rn | Rm,
  709. RdRn = Rd | Rn,
  710. RdRnRm = Rd | Rn | Rm
  711. }
  712. private static void EmitVectorBinaryF(AILEmitterCtx Context, Action Emit)
  713. {
  714. EmitVectorFOp(Context, Emit, OperFlags.RnRm);
  715. }
  716. private static void EmitVectorTernaryF(AILEmitterCtx Context, Action Emit)
  717. {
  718. EmitVectorFOp(Context, Emit, OperFlags.RdRnRm);
  719. }
  720. private static void EmitVectorBinaryByElemF(AILEmitterCtx Context, Action Emit)
  721. {
  722. AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
  723. EmitVectorFOp(Context, Emit, OperFlags.RnRm, Op.Index);
  724. }
  725. private static void EmitVectorTernaryByElemF(AILEmitterCtx Context, Action Emit)
  726. {
  727. AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;
  728. EmitVectorFOp(Context, Emit, OperFlags.RdRnRm, Op.Index);
  729. }
  730. private static void EmitVectorFOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, int Elem = -1)
  731. {
  732. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  733. int SizeF = Op.Size & 1;
  734. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  735. for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
  736. {
  737. if (Opers.HasFlag(OperFlags.Rd))
  738. {
  739. EmitVectorExtractF(Context, Op.Rd, Index, SizeF);
  740. }
  741. if (Opers.HasFlag(OperFlags.Rn))
  742. {
  743. EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
  744. }
  745. if (Opers.HasFlag(OperFlags.Rm))
  746. {
  747. if (Elem != -1)
  748. {
  749. EmitVectorExtractF(Context, Op.Rm, Elem, SizeF);
  750. }
  751. else
  752. {
  753. EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
  754. }
  755. }
  756. Emit();
  757. EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
  758. }
  759. if (Op.RegisterSize == ARegisterSize.SIMD64)
  760. {
  761. EmitVectorZeroUpper(Context, Op.Rd);
  762. }
  763. }
  764. private static void EmitVectorUnarySx(AILEmitterCtx Context, Action Emit)
  765. {
  766. EmitVectorOp(Context, Emit, OperFlags.Rn, true);
  767. }
  768. private static void EmitVectorBinarySx(AILEmitterCtx Context, Action Emit)
  769. {
  770. EmitVectorOp(Context, Emit, OperFlags.RnRm, true);
  771. }
  772. private static void EmitVectorUnaryZx(AILEmitterCtx Context, Action Emit)
  773. {
  774. EmitVectorOp(Context, Emit, OperFlags.Rn, false);
  775. }
  776. private static void EmitVectorBinaryZx(AILEmitterCtx Context, Action Emit)
  777. {
  778. EmitVectorOp(Context, Emit, OperFlags.RnRm, false);
  779. }
  780. private static void EmitVectorTernaryZx(AILEmitterCtx Context, Action Emit)
  781. {
  782. EmitVectorOp(Context, Emit, OperFlags.RdRnRm, false);
  783. }
  784. private static void EmitVectorOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
  785. {
  786. AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
  787. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  788. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  789. {
  790. if (Opers.HasFlag(OperFlags.Rd))
  791. {
  792. EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
  793. }
  794. if (Opers.HasFlag(OperFlags.Rn))
  795. {
  796. EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
  797. }
  798. if (Opers.HasFlag(OperFlags.Rm))
  799. {
  800. EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);
  801. }
  802. Emit();
  803. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  804. }
  805. if (Op.RegisterSize == ARegisterSize.SIMD64)
  806. {
  807. EmitVectorZeroUpper(Context, Op.Rd);
  808. }
  809. }
  810. private static void EmitVectorImmUnary(AILEmitterCtx Context, Action Emit)
  811. {
  812. EmitVectorImmOp(Context, Emit, false);
  813. }
  814. private static void EmitVectorImmBinary(AILEmitterCtx Context, Action Emit)
  815. {
  816. EmitVectorImmOp(Context, Emit, true);
  817. }
  818. private static void EmitVectorImmOp(AILEmitterCtx Context, Action Emit, bool Binary)
  819. {
  820. AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
  821. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  822. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  823. {
  824. if (Binary)
  825. {
  826. EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
  827. }
  828. Context.EmitLdc_I8(Op.Imm);
  829. Emit();
  830. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  831. }
  832. if (Op.RegisterSize == ARegisterSize.SIMD64)
  833. {
  834. EmitVectorZeroUpper(Context, Op.Rd);
  835. }
  836. }
  837. private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
  838. {
  839. EmitVectorShImmBinaryOp(Context, Emit, Imm, true);
  840. }
  841. private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
  842. {
  843. EmitVectorShImmBinaryOp(Context, Emit, Imm, false);
  844. }
  845. private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
  846. {
  847. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  848. int Bytes = Context.CurrOp.GetBitsCount() >> 3;
  849. for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
  850. {
  851. EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
  852. Context.EmitLdc_I4(Imm);
  853. Emit();
  854. EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
  855. }
  856. if (Op.RegisterSize == ARegisterSize.SIMD64)
  857. {
  858. EmitVectorZeroUpper(Context, Op.Rd);
  859. }
  860. }
  861. private static void EmitVectorShImmNarrowBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
  862. {
  863. EmitVectorShImmNarrowBinaryOp(Context, Emit, Imm, true);
  864. }
  865. private static void EmitVectorShImmNarrowBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
  866. {
  867. EmitVectorShImmNarrowBinaryOp(Context, Emit, Imm, false);
  868. }
  869. private static void EmitVectorShImmNarrowBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
  870. {
  871. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  872. int Elems = 8 >> Op.Size;
  873. int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
  874. for (int Index = 0; Index < Elems; Index++)
  875. {
  876. EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed);
  877. Context.EmitLdc_I4(Imm);
  878. Emit();
  879. EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size);
  880. }
  881. if (Part == 0)
  882. {
  883. EmitVectorZeroUpper(Context, Op.Rd);
  884. }
  885. }
  886. private static void EmitVectorShImmWidenBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
  887. {
  888. EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, true);
  889. }
  890. private static void EmitVectorShImmWidenBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
  891. {
  892. EmitVectorShImmWidenBinaryOp(Context, Emit, Imm, false);
  893. }
  894. private static void EmitVectorShImmWidenBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
  895. {
  896. AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
  897. int Elems = 8 >> Op.Size;
  898. int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
  899. for (int Index = 0; Index < Elems; Index++)
  900. {
  901. EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);
  902. Context.EmitLdc_I4(Imm);
  903. Emit();
  904. EmitVectorInsertTmp(Context, Index, Op.Size + 1);
  905. }
  906. Context.EmitLdvectmp();
  907. Context.EmitStvec(Op.Rd);
  908. }
  909. private static void EmitVectorWidenBinarySx(AILEmitterCtx Context, Action Emit)
  910. {
  911. EmitVectorWidenBinary(Context, Emit, true);
  912. }
  913. private static void EmitVectorWidenBinaryZx(AILEmitterCtx Context, Action Emit)
  914. {
  915. EmitVectorWidenBinary(Context, Emit, false);
  916. }
  917. private static void EmitVectorWidenBinary(AILEmitterCtx Context, Action Emit, bool Signed)
  918. {
  919. AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
  920. int Elems = 8 >> Op.Size;
  921. int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
  922. for (int Index = 0; Index < Elems; Index++)
  923. {
  924. EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed);
  925. EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed);
  926. Emit();
  927. EmitVectorInsertTmp(Context, Index, Op.Size + 1);
  928. }
  929. Context.EmitLdvectmp();
  930. Context.EmitStvec(Op.Rd);
  931. }
  932. private static void EmitVectorExtractF(AILEmitterCtx Context, int Reg, int Index, int Size)
  933. {
  934. Context.EmitLdvec(Reg);
  935. Context.EmitLdc_I4(Index);
  936. if (Size == 0)
  937. {
  938. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractSingle));
  939. }
  940. else if (Size == 1)
  941. {
  942. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractDouble));
  943. }
  944. else
  945. {
  946. throw new ArgumentOutOfRangeException(nameof(Size));
  947. }
  948. }
  949. private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index, int Size)
  950. {
  951. EmitVectorExtract(Context, Reg, Index, Size, true);
  952. }
  953. private static void EmitVectorExtractZx(AILEmitterCtx Context, int Reg, int Index, int Size)
  954. {
  955. EmitVectorExtract(Context, Reg, Index, Size, false);
  956. }
  957. private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
  958. {
  959. if (Size < 0 || Size > 3)
  960. {
  961. throw new ArgumentOutOfRangeException(nameof(Size));
  962. }
  963. IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
  964. Context.EmitLdvec(Reg);
  965. Context.EmitLdc_I4(Index);
  966. Context.EmitLdc_I4(Size);
  967. ASoftFallback.EmitCall(Context, Signed
  968. ? nameof(ASoftFallback.ExtractSVec)
  969. : nameof(ASoftFallback.ExtractVec));
  970. }
  971. private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
  972. {
  973. EmitVectorInsert(Context, Rd, 0, 3, 0);
  974. }
  975. private static void EmitVectorZeroUpper(AILEmitterCtx Context, int Rd)
  976. {
  977. EmitVectorInsert(Context, Rd, 1, 3, 0);
  978. }
  979. private static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size)
  980. {
  981. Context.EmitLdvec(Reg);
  982. Context.EmitLdc_I4(Index);
  983. if (Size == 0)
  984. {
  985. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertSingle));
  986. }
  987. else if (Size == 1)
  988. {
  989. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertDouble));
  990. }
  991. else
  992. {
  993. throw new ArgumentOutOfRangeException(nameof(Size));
  994. }
  995. Context.EmitStvec(Reg);
  996. }
  997. private static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size)
  998. {
  999. if (Size < 0 || Size > 3)
  1000. {
  1001. throw new ArgumentOutOfRangeException(nameof(Size));
  1002. }
  1003. Context.EmitLdvectmp();
  1004. Context.EmitLdc_I4(Index);
  1005. Context.EmitLdc_I4(Size);
  1006. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt));
  1007. Context.EmitStvectmp();
  1008. }
  1009. private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
  1010. {
  1011. if (Size < 0 || Size > 3)
  1012. {
  1013. throw new ArgumentOutOfRangeException(nameof(Size));
  1014. }
  1015. Context.EmitLdvec(Reg);
  1016. Context.EmitLdc_I4(Index);
  1017. Context.EmitLdc_I4(Size);
  1018. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt));
  1019. Context.EmitStvec(Reg);
  1020. }
  1021. private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
  1022. {
  1023. if (Size < 0 || Size > 3)
  1024. {
  1025. throw new ArgumentOutOfRangeException(nameof(Size));
  1026. }
  1027. Context.EmitLdvec(Reg);
  1028. Context.EmitLdc_I4(Index);
  1029. Context.EmitLdc_I4(Size);
  1030. Context.EmitLdc_I8(Value);
  1031. ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
  1032. Context.EmitStvec(Reg);
  1033. }
  1034. }
  1035. }