CodeGeneratorIntrinsic.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. using ARMeilleure.IntermediateRepresentation;
  2. using System;
  3. using System.Diagnostics;
  4. namespace ARMeilleure.CodeGen.Arm64
  5. {
  6. static class CodeGeneratorIntrinsic
  7. {
  8. public static void GenerateOperation(CodeGenContext context, Operation operation)
  9. {
  10. Intrinsic intrin = operation.Intrinsic;
  11. IntrinsicInfo info = IntrinsicTable.GetInfo(intrin & ~(Intrinsic.Arm64VTypeMask | Intrinsic.Arm64VSizeMask));
  12. switch (info.Type)
  13. {
  14. case IntrinsicType.ScalarUnary:
  15. GenerateVectorUnary(
  16. context,
  17. 0,
  18. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  19. info.Inst,
  20. operation.Destination,
  21. operation.GetSource(0));
  22. break;
  23. case IntrinsicType.ScalarUnaryByElem:
  24. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  25. GenerateVectorUnaryByElem(
  26. context,
  27. 0,
  28. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  29. info.Inst,
  30. (uint)operation.GetSource(1).AsInt32(),
  31. operation.Destination,
  32. operation.GetSource(0));
  33. break;
  34. case IntrinsicType.ScalarBinary:
  35. GenerateVectorBinary(
  36. context,
  37. 0,
  38. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  39. info.Inst,
  40. operation.Destination,
  41. operation.GetSource(0),
  42. operation.GetSource(1));
  43. break;
  44. case IntrinsicType.ScalarBinaryFPByElem:
  45. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  46. GenerateVectorBinaryFPByElem(
  47. context,
  48. 0,
  49. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  50. info.Inst,
  51. (uint)operation.GetSource(2).AsInt32(),
  52. operation.Destination,
  53. operation.GetSource(0),
  54. operation.GetSource(1));
  55. break;
  56. case IntrinsicType.ScalarBinaryRd:
  57. GenerateVectorUnary(
  58. context,
  59. 0,
  60. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  61. info.Inst,
  62. operation.Destination,
  63. operation.GetSource(1));
  64. break;
  65. case IntrinsicType.ScalarBinaryShl:
  66. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  67. GenerateVectorBinaryShlImm(
  68. context,
  69. 0,
  70. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  71. info.Inst,
  72. operation.Destination,
  73. operation.GetSource(0),
  74. (uint)operation.GetSource(1).AsInt32());
  75. break;
  76. case IntrinsicType.ScalarBinaryShr:
  77. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  78. GenerateVectorBinaryShrImm(
  79. context,
  80. 0,
  81. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  82. info.Inst,
  83. operation.Destination,
  84. operation.GetSource(0),
  85. (uint)operation.GetSource(1).AsInt32());
  86. break;
  87. case IntrinsicType.ScalarFPCompare:
  88. GenerateScalarFPCompare(
  89. context,
  90. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  91. info.Inst,
  92. operation.Destination,
  93. operation.GetSource(0),
  94. operation.GetSource(1));
  95. break;
  96. case IntrinsicType.ScalarFPConvFixed:
  97. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  98. GenerateVectorBinaryShrImm(
  99. context,
  100. 0,
  101. ((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
  102. info.Inst,
  103. operation.Destination,
  104. operation.GetSource(0),
  105. (uint)operation.GetSource(1).AsInt32());
  106. break;
  107. case IntrinsicType.ScalarFPConvFixedGpr:
  108. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  109. GenerateScalarFPConvGpr(
  110. context,
  111. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  112. info.Inst,
  113. operation.Destination,
  114. operation.GetSource(0),
  115. (uint)operation.GetSource(1).AsInt32());
  116. break;
  117. case IntrinsicType.ScalarFPConvGpr:
  118. GenerateScalarFPConvGpr(
  119. context,
  120. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  121. info.Inst,
  122. operation.Destination,
  123. operation.GetSource(0));
  124. break;
  125. case IntrinsicType.ScalarTernary:
  126. GenerateScalarTernary(
  127. context,
  128. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  129. info.Inst,
  130. operation.Destination,
  131. operation.GetSource(1),
  132. operation.GetSource(2),
  133. operation.GetSource(0));
  134. break;
  135. case IntrinsicType.ScalarTernaryFPRdByElem:
  136. Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
  137. GenerateVectorBinaryFPByElem(
  138. context,
  139. 0,
  140. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  141. info.Inst,
  142. (uint)operation.GetSource(3).AsInt32(),
  143. operation.Destination,
  144. operation.GetSource(1),
  145. operation.GetSource(2));
  146. break;
  147. case IntrinsicType.ScalarTernaryShlRd:
  148. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  149. GenerateVectorBinaryShlImm(
  150. context,
  151. 0,
  152. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  153. info.Inst,
  154. operation.Destination,
  155. operation.GetSource(1),
  156. (uint)operation.GetSource(2).AsInt32());
  157. break;
  158. case IntrinsicType.ScalarTernaryShrRd:
  159. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  160. GenerateVectorBinaryShrImm(
  161. context,
  162. 0,
  163. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  164. info.Inst,
  165. operation.Destination,
  166. operation.GetSource(1),
  167. (uint)operation.GetSource(2).AsInt32());
  168. break;
  169. case IntrinsicType.VectorUnary:
  170. GenerateVectorUnary(
  171. context,
  172. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  173. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  174. info.Inst,
  175. operation.Destination,
  176. operation.GetSource(0));
  177. break;
  178. case IntrinsicType.VectorUnaryByElem:
  179. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  180. GenerateVectorUnaryByElem(
  181. context,
  182. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  183. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  184. info.Inst,
  185. (uint)operation.GetSource(1).AsInt32(),
  186. operation.Destination,
  187. operation.GetSource(0));
  188. break;
  189. case IntrinsicType.VectorBinary:
  190. GenerateVectorBinary(
  191. context,
  192. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  193. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  194. info.Inst,
  195. operation.Destination,
  196. operation.GetSource(0),
  197. operation.GetSource(1));
  198. break;
  199. case IntrinsicType.VectorBinaryBitwise:
  200. GenerateVectorBinary(
  201. context,
  202. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  203. info.Inst,
  204. operation.Destination,
  205. operation.GetSource(0),
  206. operation.GetSource(1));
  207. break;
  208. case IntrinsicType.VectorBinaryByElem:
  209. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  210. GenerateVectorBinaryByElem(
  211. context,
  212. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  213. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  214. info.Inst,
  215. (uint)operation.GetSource(2).AsInt32(),
  216. operation.Destination,
  217. operation.GetSource(0),
  218. operation.GetSource(1));
  219. break;
  220. case IntrinsicType.VectorBinaryFPByElem:
  221. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  222. GenerateVectorBinaryFPByElem(
  223. context,
  224. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  225. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  226. info.Inst,
  227. (uint)operation.GetSource(2).AsInt32(),
  228. operation.Destination,
  229. operation.GetSource(0),
  230. operation.GetSource(1));
  231. break;
  232. case IntrinsicType.VectorBinaryRd:
  233. GenerateVectorUnary(
  234. context,
  235. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  236. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  237. info.Inst,
  238. operation.Destination,
  239. operation.GetSource(1));
  240. break;
  241. case IntrinsicType.VectorBinaryShl:
  242. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  243. GenerateVectorBinaryShlImm(
  244. context,
  245. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  246. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  247. info.Inst,
  248. operation.Destination,
  249. operation.GetSource(0),
  250. (uint)operation.GetSource(1).AsInt32());
  251. break;
  252. case IntrinsicType.VectorBinaryShr:
  253. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  254. GenerateVectorBinaryShrImm(
  255. context,
  256. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  257. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  258. info.Inst,
  259. operation.Destination,
  260. operation.GetSource(0),
  261. (uint)operation.GetSource(1).AsInt32());
  262. break;
  263. case IntrinsicType.VectorFPConvFixed:
  264. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  265. GenerateVectorBinaryShrImm(
  266. context,
  267. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  268. ((uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift) + 2u,
  269. info.Inst,
  270. operation.Destination,
  271. operation.GetSource(0),
  272. (uint)operation.GetSource(1).AsInt32());
  273. break;
  274. case IntrinsicType.VectorInsertByElem:
  275. Debug.Assert(operation.GetSource(1).Kind == OperandKind.Constant);
  276. Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
  277. GenerateVectorInsertByElem(
  278. context,
  279. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  280. info.Inst,
  281. (uint)operation.GetSource(3).AsInt32(),
  282. (uint)operation.GetSource(1).AsInt32(),
  283. operation.Destination,
  284. operation.GetSource(2));
  285. break;
  286. case IntrinsicType.VectorLookupTable:
  287. Debug.Assert((uint)(operation.SourcesCount - 2) <= 3);
  288. for (int i = 1; i < operation.SourcesCount - 1; i++)
  289. {
  290. Register currReg = operation.GetSource(i).GetRegister();
  291. Register prevReg = operation.GetSource(i - 1).GetRegister();
  292. Debug.Assert(prevReg.Index + 1 == currReg.Index && currReg.Type == RegisterType.Vector);
  293. }
  294. GenerateVectorBinary(
  295. context,
  296. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  297. info.Inst | ((uint)(operation.SourcesCount - 2) << 13),
  298. operation.Destination,
  299. operation.GetSource(0),
  300. operation.GetSource(operation.SourcesCount - 1));
  301. break;
  302. case IntrinsicType.VectorTernaryFPRdByElem:
  303. Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
  304. GenerateVectorBinaryFPByElem(
  305. context,
  306. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  307. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  308. info.Inst,
  309. (uint)operation.GetSource(3).AsInt32(),
  310. operation.Destination,
  311. operation.GetSource(1),
  312. operation.GetSource(2));
  313. break;
  314. case IntrinsicType.VectorTernaryRd:
  315. GenerateVectorBinary(
  316. context,
  317. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  318. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  319. info.Inst,
  320. operation.Destination,
  321. operation.GetSource(1),
  322. operation.GetSource(2));
  323. break;
  324. case IntrinsicType.VectorTernaryRdBitwise:
  325. GenerateVectorBinary(
  326. context,
  327. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  328. info.Inst,
  329. operation.Destination,
  330. operation.GetSource(1),
  331. operation.GetSource(2));
  332. break;
  333. case IntrinsicType.VectorTernaryRdByElem:
  334. Debug.Assert(operation.GetSource(3).Kind == OperandKind.Constant);
  335. GenerateVectorBinaryByElem(
  336. context,
  337. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  338. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  339. info.Inst,
  340. (uint)operation.GetSource(3).AsInt32(),
  341. operation.Destination,
  342. operation.GetSource(1),
  343. operation.GetSource(2));
  344. break;
  345. case IntrinsicType.VectorTernaryShlRd:
  346. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  347. GenerateVectorBinaryShlImm(
  348. context,
  349. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  350. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  351. info.Inst,
  352. operation.Destination,
  353. operation.GetSource(1),
  354. (uint)operation.GetSource(2).AsInt32());
  355. break;
  356. case IntrinsicType.VectorTernaryShrRd:
  357. Debug.Assert(operation.GetSource(2).Kind == OperandKind.Constant);
  358. GenerateVectorBinaryShrImm(
  359. context,
  360. (uint)(intrin & Intrinsic.Arm64VTypeMask) >> (int)Intrinsic.Arm64VTypeShift,
  361. (uint)(intrin & Intrinsic.Arm64VSizeMask) >> (int)Intrinsic.Arm64VSizeShift,
  362. info.Inst,
  363. operation.Destination,
  364. operation.GetSource(1),
  365. (uint)operation.GetSource(2).AsInt32());
  366. break;
  367. case IntrinsicType.GetRegister:
  368. context.Assembler.WriteInstruction(info.Inst, operation.Destination);
  369. break;
  370. case IntrinsicType.SetRegister:
  371. context.Assembler.WriteInstruction(info.Inst, operation.GetSource(0));
  372. break;
  373. default:
  374. throw new NotImplementedException(info.Type.ToString());
  375. }
  376. }
  377. private static void GenerateScalarFPCompare(
  378. CodeGenContext context,
  379. uint sz,
  380. uint instruction,
  381. Operand dest,
  382. Operand rn,
  383. Operand rm)
  384. {
  385. instruction |= (sz << 22);
  386. if (rm.Kind == OperandKind.Constant && rm.Value == 0)
  387. {
  388. instruction |= 0b1000;
  389. rm = rn;
  390. }
  391. context.Assembler.WriteInstructionRm16NoRet(instruction, rn, rm);
  392. context.Assembler.Mrs(dest, 1, 3, 4, 2, 0);
  393. }
  394. private static void GenerateScalarFPConvGpr(
  395. CodeGenContext context,
  396. uint sz,
  397. uint instruction,
  398. Operand rd,
  399. Operand rn)
  400. {
  401. instruction |= (sz << 22);
  402. if (rd.Type.IsInteger())
  403. {
  404. context.Assembler.WriteInstructionAuto(instruction, rd, rn);
  405. }
  406. else
  407. {
  408. if (rn.Type == OperandType.I64)
  409. {
  410. instruction |= Assembler.SfFlag;
  411. }
  412. context.Assembler.WriteInstruction(instruction, rd, rn);
  413. }
  414. }
  415. private static void GenerateScalarFPConvGpr(
  416. CodeGenContext context,
  417. uint sz,
  418. uint instruction,
  419. Operand rd,
  420. Operand rn,
  421. uint fBits)
  422. {
  423. Debug.Assert(fBits <= 64);
  424. instruction |= (sz << 22);
  425. instruction |= (64 - fBits) << 10;
  426. if (rd.Type.IsInteger())
  427. {
  428. Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);
  429. context.Assembler.WriteInstructionAuto(instruction, rd, rn);
  430. }
  431. else
  432. {
  433. if (rn.Type == OperandType.I64)
  434. {
  435. instruction |= Assembler.SfFlag;
  436. }
  437. else
  438. {
  439. Debug.Assert(fBits <= 32);
  440. }
  441. context.Assembler.WriteInstruction(instruction, rd, rn);
  442. }
  443. }
  444. private static void GenerateScalarTernary(
  445. CodeGenContext context,
  446. uint sz,
  447. uint instruction,
  448. Operand rd,
  449. Operand rn,
  450. Operand rm,
  451. Operand ra)
  452. {
  453. instruction |= (sz << 22);
  454. context.Assembler.WriteInstruction(instruction, rd, rn, rm, ra);
  455. }
  456. private static void GenerateVectorUnary(
  457. CodeGenContext context,
  458. uint q,
  459. uint sz,
  460. uint instruction,
  461. Operand rd,
  462. Operand rn)
  463. {
  464. instruction |= (q << 30) | (sz << 22);
  465. context.Assembler.WriteInstruction(instruction, rd, rn);
  466. }
  467. private static void GenerateVectorUnaryByElem(
  468. CodeGenContext context,
  469. uint q,
  470. uint sz,
  471. uint instruction,
  472. uint srcIndex,
  473. Operand rd,
  474. Operand rn)
  475. {
  476. uint imm5 = (srcIndex << ((int)sz + 1)) | (1u << (int)sz);
  477. instruction |= (q << 30) | (imm5 << 16);
  478. context.Assembler.WriteInstruction(instruction, rd, rn);
  479. }
  480. private static void GenerateVectorBinary(
  481. CodeGenContext context,
  482. uint q,
  483. uint instruction,
  484. Operand rd,
  485. Operand rn,
  486. Operand rm)
  487. {
  488. instruction |= (q << 30);
  489. context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
  490. }
  491. private static void GenerateVectorBinary(
  492. CodeGenContext context,
  493. uint q,
  494. uint sz,
  495. uint instruction,
  496. Operand rd,
  497. Operand rn,
  498. Operand rm)
  499. {
  500. instruction |= (q << 30) | (sz << 22);
  501. context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
  502. }
  503. private static void GenerateVectorBinaryByElem(
  504. CodeGenContext context,
  505. uint q,
  506. uint size,
  507. uint instruction,
  508. uint srcIndex,
  509. Operand rd,
  510. Operand rn,
  511. Operand rm)
  512. {
  513. instruction |= (q << 30) | (size << 22);
  514. if (size == 2)
  515. {
  516. instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
  517. }
  518. else
  519. {
  520. instruction |= ((srcIndex & 3) << 20) | ((srcIndex & 4) << 9);
  521. }
  522. context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
  523. }
  524. private static void GenerateVectorBinaryFPByElem(
  525. CodeGenContext context,
  526. uint q,
  527. uint sz,
  528. uint instruction,
  529. uint srcIndex,
  530. Operand rd,
  531. Operand rn,
  532. Operand rm)
  533. {
  534. instruction |= (q << 30) | (sz << 22);
  535. if (sz != 0)
  536. {
  537. instruction |= (srcIndex & 1) << 11;
  538. }
  539. else
  540. {
  541. instruction |= ((srcIndex & 1) << 21) | ((srcIndex & 2) << 10);
  542. }
  543. context.Assembler.WriteInstructionRm16(instruction, rd, rn, rm);
  544. }
  545. private static void GenerateVectorBinaryShlImm(
  546. CodeGenContext context,
  547. uint q,
  548. uint sz,
  549. uint instruction,
  550. Operand rd,
  551. Operand rn,
  552. uint shift)
  553. {
  554. instruction |= (q << 30);
  555. Debug.Assert(shift >= 0 && shift < (8u << (int)sz));
  556. uint imm = (8u << (int)sz) | (shift & (0x3fu >> (int)(3 - sz)));
  557. instruction |= (imm << 16);
  558. context.Assembler.WriteInstruction(instruction, rd, rn);
  559. }
  560. private static void GenerateVectorBinaryShrImm(
  561. CodeGenContext context,
  562. uint q,
  563. uint sz,
  564. uint instruction,
  565. Operand rd,
  566. Operand rn,
  567. uint shift)
  568. {
  569. instruction |= (q << 30);
  570. Debug.Assert(shift > 0 && shift <= (8u << (int)sz));
  571. uint imm = (8u << (int)sz) | ((8u << (int)sz) - shift);
  572. instruction |= (imm << 16);
  573. context.Assembler.WriteInstruction(instruction, rd, rn);
  574. }
  575. private static void GenerateVectorInsertByElem(
  576. CodeGenContext context,
  577. uint sz,
  578. uint instruction,
  579. uint srcIndex,
  580. uint dstIndex,
  581. Operand rd,
  582. Operand rn)
  583. {
  584. uint imm4 = srcIndex << (int)sz;
  585. uint imm5 = (dstIndex << ((int)sz + 1)) | (1u << (int)sz);
  586. instruction |= imm4 << 11;
  587. instruction |= imm5 << 16;
  588. context.Assembler.WriteInstruction(instruction, rd, rn);
  589. }
  590. }
  591. }