/ src / ARMeilleure / Instructions / InstEmitSimdHelperArm64.cs
InstEmitSimdHelperArm64.cs
  1  using ARMeilleure.Decoders;
  2  using ARMeilleure.IntermediateRepresentation;
  3  using ARMeilleure.State;
  4  using ARMeilleure.Translation;
  5  
  6  using static ARMeilleure.Instructions.InstEmitHelper;
  7  using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  8  
  9  namespace ARMeilleure.Instructions
 10  {
 11      static class InstEmitSimdHelperArm64
 12      {
 13          public static void EmitScalarUnaryOpF(ArmEmitterContext context, Intrinsic inst)
 14          {
 15              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
 16  
 17              Operand n = GetVec(op.Rn);
 18  
 19              if ((op.Size & 1) != 0)
 20              {
 21                  inst |= Intrinsic.Arm64VDouble;
 22              }
 23  
 24              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
 25          }
 26  
 27          public static void EmitScalarUnaryOpFFromGp(ArmEmitterContext context, Intrinsic inst)
 28          {
 29              OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
 30  
 31              Operand n = GetIntOrZR(context, op.Rn);
 32  
 33              if ((op.Size & 1) != 0)
 34              {
 35                  inst |= Intrinsic.Arm64VDouble;
 36              }
 37  
 38              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
 39          }
 40  
 41          public static void EmitScalarUnaryOpFToGp(ArmEmitterContext context, Intrinsic inst)
 42          {
 43              OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
 44  
 45              Operand n = GetVec(op.Rn);
 46  
 47              if ((op.Size & 1) != 0)
 48              {
 49                  inst |= Intrinsic.Arm64VDouble;
 50              }
 51  
 52              SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
 53                  ? context.AddIntrinsicInt(inst, n)
 54                  : context.AddIntrinsicLong(inst, n));
 55          }
 56  
 57          public static void EmitScalarBinaryOpF(ArmEmitterContext context, Intrinsic inst)
 58          {
 59              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
 60  
 61              Operand n = GetVec(op.Rn);
 62              Operand m = GetVec(op.Rm);
 63  
 64              if ((op.Size & 1) != 0)
 65              {
 66                  inst |= Intrinsic.Arm64VDouble;
 67              }
 68  
 69              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
 70          }
 71  
 72          public static void EmitScalarBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst)
 73          {
 74              OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
 75  
 76              Operand n = GetVec(op.Rn);
 77              Operand m = GetVec(op.Rm);
 78  
 79              if ((op.Size & 1) != 0)
 80              {
 81                  inst |= Intrinsic.Arm64VDouble;
 82              }
 83  
 84              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
 85          }
 86  
 87          public static void EmitScalarTernaryOpF(ArmEmitterContext context, Intrinsic inst)
 88          {
 89              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
 90  
 91              Operand n = GetVec(op.Rn);
 92              Operand m = GetVec(op.Rm);
 93              Operand a = GetVec(op.Ra);
 94  
 95              if ((op.Size & 1) != 0)
 96              {
 97                  inst |= Intrinsic.Arm64VDouble;
 98              }
 99  
100              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, a, n, m));
101          }
102  
103          public static void EmitScalarTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst)
104          {
105              OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
106  
107              Operand d = GetVec(op.Rd);
108              Operand n = GetVec(op.Rn);
109              Operand m = GetVec(op.Rm);
110  
111              if ((op.Size & 1) != 0)
112              {
113                  inst |= Intrinsic.Arm64VDouble;
114              }
115  
116              context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
117          }
118  
119          public static void EmitScalarUnaryOp(ArmEmitterContext context, Intrinsic inst)
120          {
121              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
122  
123              Operand n = GetVec(op.Rn);
124  
125              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
126  
127              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
128          }
129  
130          public static void EmitScalarBinaryOp(ArmEmitterContext context, Intrinsic inst)
131          {
132              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
133  
134              Operand n = GetVec(op.Rn);
135              Operand m = GetVec(op.Rm);
136  
137              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
138  
139              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
140          }
141  
142          public static void EmitScalarBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
143          {
144              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
145  
146              Operand d = GetVec(op.Rd);
147              Operand n = GetVec(op.Rn);
148  
149              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
150  
151              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
152          }
153  
154          public static void EmitScalarTernaryOpRd(ArmEmitterContext context, Intrinsic inst)
155          {
156              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
157  
158              Operand d = GetVec(op.Rd);
159              Operand n = GetVec(op.Rn);
160              Operand m = GetVec(op.Rm);
161  
162              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
163  
164              context.Copy(d, context.AddIntrinsic(inst, d, n, m));
165          }
166  
167          public static void EmitScalarShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift)
168          {
169              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
170  
171              Operand n = GetVec(op.Rn);
172  
173              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
174  
175              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift)));
176          }
177  
178          public static void EmitScalarShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
179          {
180              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
181  
182              Operand d = GetVec(op.Rd);
183              Operand n = GetVec(op.Rn);
184  
185              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
186  
187              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
188          }
189  
190          public static void EmitScalarSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
191          {
192              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
193  
194              Operand d = GetVec(op.Rd);
195              Operand n = GetVec(op.Rn);
196  
197              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
198  
199              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
200  
201              context.SetPendingQcFlagSync();
202          }
203  
204          public static void EmitScalarSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst)
205          {
206              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
207  
208              Operand n = GetVec(op.Rn);
209  
210              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
211  
212              Operand result = context.AddIntrinsic(inst, n);
213  
214              context.Copy(GetVec(op.Rd), result);
215  
216              context.SetPendingQcFlagSync();
217          }
218  
219          public static void EmitScalarSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst)
220          {
221              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
222  
223              Operand n = GetVec(op.Rn);
224              Operand m = GetVec(op.Rm);
225  
226              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
227  
228              Operand result = context.AddIntrinsic(inst, n, m);
229  
230              context.Copy(GetVec(op.Rd), result);
231  
232              context.SetPendingQcFlagSync();
233          }
234  
235          public static void EmitScalarSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
236          {
237              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
238  
239              Operand d = GetVec(op.Rd);
240              Operand n = GetVec(op.Rn);
241  
242              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
243  
244              Operand result = context.AddIntrinsic(inst, d, n);
245  
246              context.Copy(GetVec(op.Rd), result);
247  
248              context.SetPendingQcFlagSync();
249          }
250  
251          public static void EmitScalarConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits)
252          {
253              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
254  
255              Operand n = GetVec(op.Rn);
256  
257              if ((op.Size & 1) != 0)
258              {
259                  inst |= Intrinsic.Arm64VDouble;
260              }
261  
262              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
263          }
264  
265          public static void EmitScalarConvertBinaryOpFFromGp(ArmEmitterContext context, Intrinsic inst, int fBits)
266          {
267              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
268  
269              Operand n = GetIntOrZR(context, op.Rn);
270  
271              if ((op.Size & 1) != 0)
272              {
273                  inst |= Intrinsic.Arm64VDouble;
274              }
275  
276              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
277          }
278  
279          public static void EmitScalarConvertBinaryOpFToGp(ArmEmitterContext context, Intrinsic inst, int fBits)
280          {
281              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
282  
283              Operand n = GetVec(op.Rn);
284  
285              if ((op.Size & 1) != 0)
286              {
287                  inst |= Intrinsic.Arm64VDouble;
288              }
289  
290              SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
291                  ? context.AddIntrinsicInt(inst, n, Const(fBits))
292                  : context.AddIntrinsicLong(inst, n, Const(fBits)));
293          }
294  
295          public static void EmitVectorUnaryOpF(ArmEmitterContext context, Intrinsic inst)
296          {
297              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
298  
299              Operand n = GetVec(op.Rn);
300  
301              if ((op.Size & 1) != 0)
302              {
303                  inst |= Intrinsic.Arm64VDouble;
304              }
305  
306              if (op.RegisterSize == RegisterSize.Simd128)
307              {
308                  inst |= Intrinsic.Arm64V128;
309              }
310  
311              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
312          }
313  
314          public static void EmitVectorBinaryOpF(ArmEmitterContext context, Intrinsic inst)
315          {
316              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
317  
318              Operand n = GetVec(op.Rn);
319              Operand m = GetVec(op.Rm);
320  
321              if ((op.Size & 1) != 0)
322              {
323                  inst |= Intrinsic.Arm64VDouble;
324              }
325  
326              if (op.RegisterSize == RegisterSize.Simd128)
327              {
328                  inst |= Intrinsic.Arm64V128;
329              }
330  
331              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
332          }
333  
334          public static void EmitVectorBinaryOpFRd(ArmEmitterContext context, Intrinsic inst)
335          {
336              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
337  
338              Operand d = GetVec(op.Rd);
339              Operand n = GetVec(op.Rn);
340  
341              if ((op.Size & 1) != 0)
342              {
343                  inst |= Intrinsic.Arm64VDouble;
344              }
345  
346              if (op.RegisterSize == RegisterSize.Simd128)
347              {
348                  inst |= Intrinsic.Arm64V128;
349              }
350  
351              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
352          }
353  
354          public static void EmitVectorBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst)
355          {
356              OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
357  
358              Operand n = GetVec(op.Rn);
359              Operand m = GetVec(op.Rm);
360  
361              if ((op.Size & 1) != 0)
362              {
363                  inst |= Intrinsic.Arm64VDouble;
364              }
365  
366              if (op.RegisterSize == RegisterSize.Simd128)
367              {
368                  inst |= Intrinsic.Arm64V128;
369              }
370  
371              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
372          }
373  
374          public static void EmitVectorTernaryOpFRd(ArmEmitterContext context, Intrinsic inst)
375          {
376              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
377  
378              Operand d = GetVec(op.Rd);
379              Operand n = GetVec(op.Rn);
380              Operand m = GetVec(op.Rm);
381  
382              if ((op.Size & 1) != 0)
383              {
384                  inst |= Intrinsic.Arm64VDouble;
385              }
386  
387              if (op.RegisterSize == RegisterSize.Simd128)
388              {
389                  inst |= Intrinsic.Arm64V128;
390              }
391  
392              context.Copy(d, context.AddIntrinsic(inst, d, n, m));
393          }
394  
395          public static void EmitVectorTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst)
396          {
397              OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp;
398  
399              Operand d = GetVec(op.Rd);
400              Operand n = GetVec(op.Rn);
401              Operand m = GetVec(op.Rm);
402  
403              if ((op.Size & 1) != 0)
404              {
405                  inst |= Intrinsic.Arm64VDouble;
406              }
407  
408              if (op.RegisterSize == RegisterSize.Simd128)
409              {
410                  inst |= Intrinsic.Arm64V128;
411              }
412  
413              context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
414          }
415  
416          public static void EmitVectorUnaryOp(ArmEmitterContext context, Intrinsic inst)
417          {
418              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
419  
420              Operand n = GetVec(op.Rn);
421  
422              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
423  
424              if (op.RegisterSize == RegisterSize.Simd128)
425              {
426                  inst |= Intrinsic.Arm64V128;
427              }
428  
429              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n));
430          }
431  
432          public static void EmitVectorBinaryOp(ArmEmitterContext context, Intrinsic inst)
433          {
434              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
435  
436              Operand n = GetVec(op.Rn);
437              Operand m = GetVec(op.Rm);
438  
439              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
440  
441              if (op.RegisterSize == RegisterSize.Simd128)
442              {
443                  inst |= Intrinsic.Arm64V128;
444              }
445  
446              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m));
447          }
448  
449          public static void EmitVectorBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
450          {
451              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
452  
453              Operand d = GetVec(op.Rd);
454              Operand n = GetVec(op.Rn);
455  
456              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
457  
458              if (op.RegisterSize == RegisterSize.Simd128)
459              {
460                  inst |= Intrinsic.Arm64V128;
461              }
462  
463              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n));
464          }
465  
466          public static void EmitVectorBinaryOpByElem(ArmEmitterContext context, Intrinsic inst)
467          {
468              OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
469  
470              Operand n = GetVec(op.Rn);
471              Operand m = GetVec(op.Rm);
472  
473              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
474  
475              if (op.RegisterSize == RegisterSize.Simd128)
476              {
477                  inst |= Intrinsic.Arm64V128;
478              }
479  
480              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index)));
481          }
482  
483          public static void EmitVectorTernaryOpRd(ArmEmitterContext context, Intrinsic inst)
484          {
485              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
486  
487              Operand d = GetVec(op.Rd);
488              Operand n = GetVec(op.Rn);
489              Operand m = GetVec(op.Rm);
490  
491              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
492  
493              if (op.RegisterSize == RegisterSize.Simd128)
494              {
495                  inst |= Intrinsic.Arm64V128;
496              }
497  
498              context.Copy(d, context.AddIntrinsic(inst, d, n, m));
499          }
500  
501          public static void EmitVectorTernaryOpRdByElem(ArmEmitterContext context, Intrinsic inst)
502          {
503              OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
504  
505              Operand d = GetVec(op.Rd);
506              Operand n = GetVec(op.Rn);
507              Operand m = GetVec(op.Rm);
508  
509              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
510  
511              if (op.RegisterSize == RegisterSize.Simd128)
512              {
513                  inst |= Intrinsic.Arm64V128;
514              }
515  
516              context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index)));
517          }
518  
519          public static void EmitVectorShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift)
520          {
521              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
522  
523              Operand n = GetVec(op.Rn);
524  
525              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
526  
527              if (op.RegisterSize == RegisterSize.Simd128)
528              {
529                  inst |= Intrinsic.Arm64V128;
530              }
531  
532              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift)));
533          }
534  
535          public static void EmitVectorShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
536          {
537              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
538  
539              Operand d = GetVec(op.Rd);
540              Operand n = GetVec(op.Rn);
541  
542              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
543  
544              if (op.RegisterSize == RegisterSize.Simd128)
545              {
546                  inst |= Intrinsic.Arm64V128;
547              }
548  
549              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
550          }
551  
552          public static void EmitVectorSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift)
553          {
554              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
555  
556              Operand d = GetVec(op.Rd);
557              Operand n = GetVec(op.Rn);
558  
559              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
560  
561              if (op.RegisterSize == RegisterSize.Simd128)
562              {
563                  inst |= Intrinsic.Arm64V128;
564              }
565  
566              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift)));
567  
568              context.SetPendingQcFlagSync();
569          }
570  
571          public static void EmitVectorSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst)
572          {
573              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
574  
575              Operand n = GetVec(op.Rn);
576  
577              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
578  
579              if (op.RegisterSize == RegisterSize.Simd128)
580              {
581                  inst |= Intrinsic.Arm64V128;
582              }
583  
584              Operand result = context.AddIntrinsic(inst, n);
585  
586              context.Copy(GetVec(op.Rd), result);
587  
588              context.SetPendingQcFlagSync();
589          }
590  
591          public static void EmitVectorSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst)
592          {
593              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
594  
595              Operand n = GetVec(op.Rn);
596              Operand m = GetVec(op.Rm);
597  
598              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
599  
600              if (op.RegisterSize == RegisterSize.Simd128)
601              {
602                  inst |= Intrinsic.Arm64V128;
603              }
604  
605              Operand result = context.AddIntrinsic(inst, n, m);
606  
607              context.Copy(GetVec(op.Rd), result);
608  
609              context.SetPendingQcFlagSync();
610          }
611  
612          public static void EmitVectorSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst)
613          {
614              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
615  
616              Operand d = GetVec(op.Rd);
617              Operand n = GetVec(op.Rn);
618  
619              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
620  
621              if (op.RegisterSize == RegisterSize.Simd128)
622              {
623                  inst |= Intrinsic.Arm64V128;
624              }
625  
626              Operand result = context.AddIntrinsic(inst, d, n);
627  
628              context.Copy(GetVec(op.Rd), result);
629  
630              context.SetPendingQcFlagSync();
631          }
632  
633          public static void EmitVectorSaturatingBinaryOpByElem(ArmEmitterContext context, Intrinsic inst)
634          {
635              OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp;
636  
637              Operand n = GetVec(op.Rn);
638              Operand m = GetVec(op.Rm);
639  
640              inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift);
641  
642              if (op.RegisterSize == RegisterSize.Simd128)
643              {
644                  inst |= Intrinsic.Arm64V128;
645              }
646  
647              Operand result = context.AddIntrinsic(inst, n, m, Const(op.Index));
648  
649              context.Copy(GetVec(op.Rd), result);
650  
651              context.SetPendingQcFlagSync();
652          }
653  
654          public static void EmitVectorConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits)
655          {
656              OpCodeSimd op = (OpCodeSimd)context.CurrOp;
657  
658              Operand n = GetVec(op.Rn);
659  
660              if ((op.Size & 1) != 0)
661              {
662                  inst |= Intrinsic.Arm64VDouble;
663              }
664  
665              if (op.RegisterSize == RegisterSize.Simd128)
666              {
667                  inst |= Intrinsic.Arm64V128;
668              }
669  
670              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits)));
671          }
672  
673          public static void EmitVectorLookupTable(ArmEmitterContext context, Intrinsic inst)
674          {
675              OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp;
676  
677              Operand[] operands = new Operand[op.Size + 1];
678  
679              operands[op.Size] = GetVec(op.Rm);
680  
681              for (int index = 0; index < op.Size; index++)
682              {
683                  operands[index] = GetVec((op.Rn + index) & 0x1F);
684              }
685  
686              if (op.RegisterSize == RegisterSize.Simd128)
687              {
688                  inst |= Intrinsic.Arm64V128;
689              }
690  
691              context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, operands));
692          }
693  
694          public static void EmitFcmpOrFcmpe(ArmEmitterContext context, bool signalNaNs)
695          {
696              OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
697  
698              bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
699  
700              Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
701  
702              if ((op.Size & 1) != 0)
703              {
704                  inst |= Intrinsic.Arm64VDouble;
705              }
706  
707              Operand n = GetVec(op.Rn);
708              Operand m = cmpWithZero ? Const(0) : GetVec(op.Rm);
709  
710              Operand nzcv = context.AddIntrinsicInt(inst, n, m);
711  
712              Operand one = Const(1);
713  
714              SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(28)), one));
715              SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(29)), one));
716              SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(30)), one));
717              SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(31)), one));
718          }
719      }
720  }