InstEmitSimdLogical.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using static ARMeilleure.Instructions.InstEmitHelper;
  5. using static ARMeilleure.Instructions.InstEmitSimdHelper;
  6. using static ARMeilleure.IntermediateRepresentation.OperandHelper;
  7. namespace ARMeilleure.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void And_V(ArmEmitterContext context)
  12. {
  13. if (Optimizations.UseSse2)
  14. {
  15. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  16. Operand n = GetVec(op.Rn);
  17. Operand m = GetVec(op.Rm);
  18. Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
  19. if (op.RegisterSize == RegisterSize.Simd64)
  20. {
  21. res = context.VectorZeroUpper64(res);
  22. }
  23. context.Copy(GetVec(op.Rd), res);
  24. }
  25. else
  26. {
  27. EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseAnd(op1, op2));
  28. }
  29. }
  30. public static void Bic_V(ArmEmitterContext context)
  31. {
  32. if (Optimizations.UseSse2)
  33. {
  34. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  35. Operand n = GetVec(op.Rn);
  36. Operand m = GetVec(op.Rm);
  37. Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, m, n);
  38. if (op.RegisterSize == RegisterSize.Simd64)
  39. {
  40. res = context.VectorZeroUpper64(res);
  41. }
  42. context.Copy(GetVec(op.Rd), res);
  43. }
  44. else
  45. {
  46. EmitVectorBinaryOpZx(context, (op1, op2) =>
  47. {
  48. return context.BitwiseAnd(op1, context.BitwiseNot(op2));
  49. });
  50. }
  51. }
  52. public static void Bic_Vi(ArmEmitterContext context)
  53. {
  54. EmitVectorImmBinaryOp(context, (op1, op2) =>
  55. {
  56. return context.BitwiseAnd(op1, context.BitwiseNot(op2));
  57. });
  58. }
  59. public static void Bif_V(ArmEmitterContext context)
  60. {
  61. EmitBifBit(context, notRm: true);
  62. }
  63. public static void Bit_V(ArmEmitterContext context)
  64. {
  65. EmitBifBit(context, notRm: false);
  66. }
  67. private static void EmitBifBit(ArmEmitterContext context, bool notRm)
  68. {
  69. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  70. if (Optimizations.UseSse2)
  71. {
  72. Operand d = GetVec(op.Rd);
  73. Operand n = GetVec(op.Rn);
  74. Operand m = GetVec(op.Rm);
  75. Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, d);
  76. if (notRm)
  77. {
  78. res = context.AddIntrinsic(Intrinsic.X86Pandn, m, res);
  79. }
  80. else
  81. {
  82. res = context.AddIntrinsic(Intrinsic.X86Pand, m, res);
  83. }
  84. res = context.AddIntrinsic(Intrinsic.X86Pxor, d, res);
  85. if (op.RegisterSize == RegisterSize.Simd64)
  86. {
  87. res = context.VectorZeroUpper64(res);
  88. }
  89. context.Copy(GetVec(op.Rd), res);
  90. }
  91. else
  92. {
  93. Operand res = context.VectorZero();
  94. int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1;
  95. for (int index = 0; index < elems; index++)
  96. {
  97. Operand d = EmitVectorExtractZx(context, op.Rd, index, 3);
  98. Operand n = EmitVectorExtractZx(context, op.Rn, index, 3);
  99. Operand m = EmitVectorExtractZx(context, op.Rm, index, 3);
  100. if (notRm)
  101. {
  102. m = context.BitwiseNot(m);
  103. }
  104. Operand e = context.BitwiseExclusiveOr(d, n);
  105. e = context.BitwiseAnd(e, m);
  106. e = context.BitwiseExclusiveOr(e, d);
  107. res = EmitVectorInsert(context, res, e, index, 3);
  108. }
  109. context.Copy(GetVec(op.Rd), res);
  110. }
  111. }
  112. public static void Bsl_V(ArmEmitterContext context)
  113. {
  114. if (Optimizations.UseSse2)
  115. {
  116. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  117. Operand d = GetVec(op.Rd);
  118. Operand n = GetVec(op.Rn);
  119. Operand m = GetVec(op.Rm);
  120. Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
  121. res = context.AddIntrinsic(Intrinsic.X86Pand, res, d);
  122. res = context.AddIntrinsic(Intrinsic.X86Pxor, res, m);
  123. if (op.RegisterSize == RegisterSize.Simd64)
  124. {
  125. res = context.VectorZeroUpper64(res);
  126. }
  127. context.Copy(GetVec(op.Rd), res);
  128. }
  129. else
  130. {
  131. EmitVectorTernaryOpZx(context, (op1, op2, op3) =>
  132. {
  133. return context.BitwiseExclusiveOr(
  134. context.BitwiseAnd(op1,
  135. context.BitwiseExclusiveOr(op2, op3)), op3);
  136. });
  137. }
  138. }
  139. public static void Eor_V(ArmEmitterContext context)
  140. {
  141. if (Optimizations.UseSse2)
  142. {
  143. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  144. Operand n = GetVec(op.Rn);
  145. Operand m = GetVec(op.Rm);
  146. Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
  147. if (op.RegisterSize == RegisterSize.Simd64)
  148. {
  149. res = context.VectorZeroUpper64(res);
  150. }
  151. context.Copy(GetVec(op.Rd), res);
  152. }
  153. else
  154. {
  155. EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseExclusiveOr(op1, op2));
  156. }
  157. }
  158. public static void Not_V(ArmEmitterContext context)
  159. {
  160. if (Optimizations.UseSse2)
  161. {
  162. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  163. Operand n = GetVec(op.Rn);
  164. Operand mask = X86GetAllElements(context, -1L);
  165. Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, n, mask);
  166. if (op.RegisterSize == RegisterSize.Simd64)
  167. {
  168. res = context.VectorZeroUpper64(res);
  169. }
  170. context.Copy(GetVec(op.Rd), res);
  171. }
  172. else
  173. {
  174. EmitVectorUnaryOpZx(context, (op1) => context.BitwiseNot(op1));
  175. }
  176. }
  177. public static void Orn_V(ArmEmitterContext context)
  178. {
  179. if (Optimizations.UseSse2)
  180. {
  181. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  182. Operand n = GetVec(op.Rn);
  183. Operand m = GetVec(op.Rm);
  184. Operand mask = X86GetAllElements(context, -1L);
  185. Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, m, mask);
  186. res = context.AddIntrinsic(Intrinsic.X86Por, res, n);
  187. if (op.RegisterSize == RegisterSize.Simd64)
  188. {
  189. res = context.VectorZeroUpper64(res);
  190. }
  191. context.Copy(GetVec(op.Rd), res);
  192. }
  193. else
  194. {
  195. EmitVectorBinaryOpZx(context, (op1, op2) =>
  196. {
  197. return context.BitwiseOr(op1, context.BitwiseNot(op2));
  198. });
  199. }
  200. }
  201. public static void Orr_V(ArmEmitterContext context)
  202. {
  203. if (Optimizations.UseSse2)
  204. {
  205. OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
  206. Operand n = GetVec(op.Rn);
  207. Operand m = GetVec(op.Rm);
  208. Operand res = context.AddIntrinsic(Intrinsic.X86Por, n, m);
  209. if (op.RegisterSize == RegisterSize.Simd64)
  210. {
  211. res = context.VectorZeroUpper64(res);
  212. }
  213. context.Copy(GetVec(op.Rd), res);
  214. }
  215. else
  216. {
  217. EmitVectorBinaryOpZx(context, (op1, op2) => context.BitwiseOr(op1, op2));
  218. }
  219. }
  220. public static void Orr_Vi(ArmEmitterContext context)
  221. {
  222. EmitVectorImmBinaryOp(context, (op1, op2) => context.BitwiseOr(op1, op2));
  223. }
  224. public static void Rbit_V(ArmEmitterContext context)
  225. {
  226. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  227. Operand res = context.VectorZero();
  228. int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
  229. for (int index = 0; index < elems; index++)
  230. {
  231. Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
  232. ne = context.ConvertI64ToI32(ne);
  233. Operand de = context.Call(new _U32_U32(SoftFallback.ReverseBits8), ne);
  234. de = context.ZeroExtend32(OperandType.I64, de);
  235. res = EmitVectorInsert(context, res, de, index, 0);
  236. }
  237. context.Copy(GetVec(op.Rd), res);
  238. }
  239. public static void Rev16_V(ArmEmitterContext context)
  240. {
  241. if (Optimizations.UseSsse3)
  242. {
  243. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  244. Operand n = GetVec(op.Rn);
  245. const long maskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
  246. const long maskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
  247. Operand mask = X86GetScalar(context, maskE0);
  248. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  249. Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
  250. if (op.RegisterSize == RegisterSize.Simd64)
  251. {
  252. res = context.VectorZeroUpper64(res);
  253. }
  254. context.Copy(GetVec(op.Rd), res);
  255. }
  256. else
  257. {
  258. EmitRev_V(context, containerSize: 1);
  259. }
  260. }
  261. public static void Rev32_V(ArmEmitterContext context)
  262. {
  263. if (Optimizations.UseSsse3)
  264. {
  265. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  266. Operand n = GetVec(op.Rn);
  267. Operand mask;
  268. if (op.Size == 0)
  269. {
  270. const long maskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
  271. const long maskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
  272. mask = X86GetScalar(context, maskE0);
  273. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  274. }
  275. else /* if (op.Size == 1) */
  276. {
  277. const long maskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
  278. const long maskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
  279. mask = X86GetScalar(context, maskE0);
  280. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  281. }
  282. Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
  283. if (op.RegisterSize == RegisterSize.Simd64)
  284. {
  285. res = context.VectorZeroUpper64(res);
  286. }
  287. context.Copy(GetVec(op.Rd), res);
  288. }
  289. else
  290. {
  291. EmitRev_V(context, containerSize: 2);
  292. }
  293. }
  294. public static void Rev64_V(ArmEmitterContext context)
  295. {
  296. if (Optimizations.UseSsse3)
  297. {
  298. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  299. Operand n = GetVec(op.Rn);
  300. Operand mask;
  301. if (op.Size == 0)
  302. {
  303. const long maskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
  304. const long maskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
  305. mask = X86GetScalar(context, maskE0);
  306. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  307. }
  308. else if (op.Size == 1)
  309. {
  310. const long maskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
  311. const long maskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
  312. mask = X86GetScalar(context, maskE0);
  313. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  314. }
  315. else /* if (op.Size == 2) */
  316. {
  317. const long maskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
  318. const long maskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
  319. mask = X86GetScalar(context, maskE0);
  320. mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
  321. }
  322. Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
  323. if (op.RegisterSize == RegisterSize.Simd64)
  324. {
  325. res = context.VectorZeroUpper64(res);
  326. }
  327. context.Copy(GetVec(op.Rd), res);
  328. }
  329. else
  330. {
  331. EmitRev_V(context, containerSize: 3);
  332. }
  333. }
  334. private static void EmitRev_V(ArmEmitterContext context, int containerSize)
  335. {
  336. OpCodeSimd op = (OpCodeSimd)context.CurrOp;
  337. Operand res = context.VectorZero();
  338. int elems = op.GetBytesCount() >> op.Size;
  339. int containerMask = (1 << (containerSize - op.Size)) - 1;
  340. for (int index = 0; index < elems; index++)
  341. {
  342. int revIndex = index ^ containerMask;
  343. Operand ne = EmitVectorExtractZx(context, op.Rn, revIndex, op.Size);
  344. res = EmitVectorInsert(context, res, ne, index, op.Size);
  345. }
  346. context.Copy(GetVec(op.Rd), res);
  347. }
  348. }
  349. }