Instruction.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /*
  2. Copyright (c) 2018 tevador
  3. This file is part of RandomX.
  4. RandomX is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. RandomX is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with RandomX. If not, see<http://www.gnu.org/licenses/>.
  14. */
  15. #include "Instruction.hpp"
  16. #include "common.hpp"
  17. namespace RandomX {
  18. void Instruction::print(std::ostream& os) const {
  19. os << names[opcode] << " ";
  20. auto handler = engine[opcode];
  21. (this->*handler)(os);
  22. }
  23. void Instruction::genAddressReg(std::ostream& os) const {
  24. os << ((alt % 4) ? "L1" : "L2") << "[r" << (int)src << "]";
  25. }
  26. void Instruction::genAddressImm(std::ostream& os) const {
  27. os << ((alt % 4) ? "L1" : "L2") << "[" << (imm32 & ((alt % 4) ? ScratchpadL1Mask : ScratchpadL2Mask)) << "]";
  28. }
  29. void Instruction::h_IADD_R(std::ostream& os) const {
  30. if (src != dst) {
  31. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  32. }
  33. else {
  34. os << "r" << (int)dst << ", " << imm32 << std::endl;
  35. }
  36. }
  37. void Instruction::h_IADD_M(std::ostream& os) const {
  38. if (src != dst) {
  39. os << "r" << (int)dst << ", ";
  40. genAddressReg(os);
  41. os << std::endl;
  42. }
  43. else {
  44. os << "r" << (int)dst << ", ";
  45. genAddressImm(os);
  46. os << std::endl;
  47. }
  48. }
  49. void Instruction::h_IADD_RC(std::ostream& os) const {
  50. os << "r" << (int)dst << ", r" << (int)src << ", " << imm32 << std::endl;
  51. }
  52. //1 uOP
  53. void Instruction::h_ISUB_R(std::ostream& os) const {
  54. if (src != dst) {
  55. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  56. }
  57. else {
  58. os << "r" << (int)dst << ", " << imm32 << std::endl;
  59. }
  60. }
  61. void Instruction::h_ISUB_M(std::ostream& os) const {
  62. if (src != dst) {
  63. os << "r" << (int)dst << ", ";
  64. genAddressReg(os);
  65. os << std::endl;
  66. }
  67. else {
  68. os << "r" << (int)dst << ", ";
  69. genAddressImm(os);
  70. os << std::endl;
  71. }
  72. }
  73. void Instruction::h_IMUL_9C(std::ostream& os) const {
  74. os << "r" << (int)dst << ", " << imm32 << std::endl;
  75. }
  76. void Instruction::h_IMUL_R(std::ostream& os) const {
  77. if (src != dst) {
  78. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  79. }
  80. else {
  81. os << "r" << (int)dst << ", " << imm32 << std::endl;
  82. }
  83. }
  84. void Instruction::h_IMUL_M(std::ostream& os) const {
  85. if (src != dst) {
  86. os << "r" << (int)dst << ", ";
  87. genAddressReg(os);
  88. os << std::endl;
  89. }
  90. else {
  91. os << "r" << (int)dst << ", ";
  92. genAddressImm(os);
  93. os << std::endl;
  94. }
  95. }
  96. void Instruction::h_IMULH_R(std::ostream& os) const {
  97. if (src != dst) {
  98. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  99. }
  100. else {
  101. os << "r" << (int)dst << ", " << imm32 << std::endl;
  102. }
  103. }
  104. void Instruction::h_IMULH_M(std::ostream& os) const {
  105. if (src != dst) {
  106. os << "r" << (int)dst << ", ";
  107. genAddressReg(os);
  108. os << std::endl;
  109. }
  110. else {
  111. os << "r" << (int)dst << ", ";
  112. genAddressImm(os);
  113. os << std::endl;
  114. }
  115. }
  116. void Instruction::h_ISMULH_R(std::ostream& os) const {
  117. if (src != dst) {
  118. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  119. }
  120. else {
  121. os << "r" << (int)dst << ", " << imm32 << std::endl;
  122. }
  123. }
  124. void Instruction::h_ISMULH_M(std::ostream& os) const {
  125. if (src != dst) {
  126. os << "r" << (int)dst << ", ";
  127. genAddressReg(os);
  128. os << std::endl;
  129. }
  130. else {
  131. os << "r" << (int)dst << ", ";
  132. genAddressImm(os);
  133. os << std::endl;
  134. }
  135. }
  136. void Instruction::h_INEG_R(std::ostream& os) const {
  137. os << "r" << (int)dst << std::endl;
  138. }
  139. void Instruction::h_IXOR_R(std::ostream& os) const {
  140. if (src != dst) {
  141. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  142. }
  143. else {
  144. os << "r" << (int)dst << ", " << imm32 << std::endl;
  145. }
  146. }
  147. void Instruction::h_IXOR_M(std::ostream& os) const {
  148. if (src != dst) {
  149. os << "r" << (int)dst << ", ";
  150. genAddressReg(os);
  151. os << std::endl;
  152. }
  153. else {
  154. os << "r" << (int)dst << ", ";
  155. genAddressImm(os);
  156. os << std::endl;
  157. }
  158. }
  159. void Instruction::h_IROR_R(std::ostream& os) const {
  160. if (src != dst) {
  161. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  162. }
  163. else {
  164. os << "r" << (int)dst << ", " << (imm32 & 63) << std::endl;
  165. }
  166. }
  167. void Instruction::h_IROL_R(std::ostream& os) const {
  168. if (src != dst) {
  169. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  170. }
  171. else {
  172. os << "r" << (int)dst << ", " << (imm32 & 63) << std::endl;
  173. }
  174. }
  175. void Instruction::h_IDIV_C(std::ostream& os) const {
  176. os << "r" << (int)dst << ", " << (uint32_t)imm32 << std::endl;
  177. }
  178. void Instruction::h_ISDIV_C(std::ostream& os) const {
  179. os << "r" << (int)dst << ", " << imm32 << std::endl;
  180. }
  181. void Instruction::h_FPSWAP_R(std::ostream& os) const {
  182. const char reg = (dst >= 4) ? 'e' : 'f';
  183. auto dstIndex = dst % 4;
  184. os << reg << dstIndex << std::endl;
  185. }
  186. void Instruction::h_FPADD_R(std::ostream& os) const {
  187. auto dstIndex = dst % 4;
  188. auto srcIndex = src % 4;
  189. os << "f" << dstIndex << ", a" << srcIndex << std::endl;
  190. }
  191. void Instruction::h_FPADD_M(std::ostream& os) const {
  192. auto dstIndex = dst % 4;
  193. os << "f" << dstIndex << ", ";
  194. genAddressReg(os);
  195. os << std::endl;
  196. }
  197. void Instruction::h_FPSUB_R(std::ostream& os) const {
  198. auto dstIndex = dst % 4;
  199. auto srcIndex = src % 4;
  200. os << "f" << dstIndex << ", a" << srcIndex << std::endl;
  201. }
  202. void Instruction::h_FPSUB_M(std::ostream& os) const {
  203. auto dstIndex = dst % 4;
  204. os << "f" << dstIndex << ", ";
  205. genAddressReg(os);
  206. os << std::endl;
  207. }
  208. void Instruction::h_FPNEG_R(std::ostream& os) const {
  209. auto dstIndex = dst % 4;
  210. os << "f" << dstIndex << std::endl;
  211. }
  212. void Instruction::h_FPMUL_R(std::ostream& os) const {
  213. auto dstIndex = dst % 4;
  214. auto srcIndex = src % 4;
  215. os << "e" << dstIndex << ", a" << srcIndex << std::endl;
  216. }
  217. void Instruction::h_FPMUL_M(std::ostream& os) const {
  218. auto dstIndex = dst % 4;
  219. os << "e" << dstIndex << ", ";
  220. genAddressReg(os);
  221. os << std::endl;
  222. }
  223. void Instruction::h_FPDIV_R(std::ostream& os) const {
  224. auto dstIndex = dst % 4;
  225. auto srcIndex = src % 4;
  226. os << "e" << dstIndex << ", a" << srcIndex << std::endl;
  227. }
  228. void Instruction::h_FPDIV_M(std::ostream& os) const {
  229. auto dstIndex = dst % 4;
  230. os << "e" << dstIndex << ", ";
  231. genAddressReg(os);
  232. os << std::endl;
  233. }
  234. void Instruction::h_FPSQRT_R(std::ostream& os) const {
  235. auto dstIndex = dst % 4;
  236. os << "e" << dstIndex << std::endl;
  237. }
  238. void Instruction::h_CFROUND(std::ostream& os) const {
  239. os << "r" << (int)dst << ", " << (alt & 63) << std::endl;
  240. }
  241. static inline const char* condition(int index) {
  242. switch (index)
  243. {
  244. case 0:
  245. return "be";
  246. case 1:
  247. return "ab";
  248. case 2:
  249. return "sg";
  250. case 3:
  251. return "ns";
  252. case 4:
  253. return "of";
  254. case 5:
  255. return "no";
  256. case 6:
  257. return "lt";
  258. case 7:
  259. return "ge";
  260. }
  261. }
  262. void Instruction::h_COND_R(std::ostream& os) const {
  263. os << "r" << (int)dst << ", " << condition((alt >> 2) & 7) << "(r" << (int)src << ", " << imm32 << ")" << std::endl;
  264. }
  265. void Instruction::h_COND_M(std::ostream& os) const {
  266. os << "r" << (int)dst << ", " << condition((alt >> 2) & 7) << "(";
  267. genAddressReg(os);
  268. os << ", " << imm32 << ")" << std::endl;
  269. }
  270. #include "instructionWeights.hpp"
  271. #define INST_NAME(x) REPN(#x, WT(x))
  272. #define INST_HANDLE(x) REPN(&Instruction::h_##x, WT(x))
  273. const char* Instruction::names[256] = {
  274. //Integer
  275. INST_NAME(IADD_R)
  276. INST_NAME(IADD_M)
  277. INST_NAME(IADD_RC)
  278. INST_NAME(ISUB_R)
  279. INST_NAME(ISUB_M)
  280. INST_NAME(IMUL_9C)
  281. INST_NAME(IMUL_R)
  282. INST_NAME(IMUL_M)
  283. INST_NAME(IMULH_R)
  284. INST_NAME(IMULH_M)
  285. INST_NAME(ISMULH_R)
  286. INST_NAME(ISMULH_M)
  287. INST_NAME(IDIV_C)
  288. INST_NAME(ISDIV_C)
  289. INST_NAME(INEG_R)
  290. INST_NAME(IXOR_R)
  291. INST_NAME(IXOR_M)
  292. INST_NAME(IROR_R)
  293. INST_NAME(IROL_R)
  294. //Common floating point
  295. INST_NAME(FPSWAP_R)
  296. //Floating point group F
  297. INST_NAME(FPADD_R)
  298. INST_NAME(FPADD_M)
  299. INST_NAME(FPSUB_R)
  300. INST_NAME(FPSUB_M)
  301. INST_NAME(FPNEG_R)
  302. //Floating point group E
  303. INST_NAME(FPMUL_R)
  304. INST_NAME(FPMUL_M)
  305. INST_NAME(FPDIV_R)
  306. INST_NAME(FPDIV_M)
  307. INST_NAME(FPSQRT_R)
  308. //Control
  309. INST_NAME(COND_R)
  310. INST_NAME(COND_M)
  311. INST_NAME(CFROUND)
  312. };
  313. InstructionVisualizer Instruction::engine[256] = {
  314. //Integer
  315. INST_HANDLE(IADD_R)
  316. INST_HANDLE(IADD_M)
  317. INST_HANDLE(IADD_RC)
  318. INST_HANDLE(ISUB_R)
  319. INST_HANDLE(ISUB_M)
  320. INST_HANDLE(IMUL_9C)
  321. INST_HANDLE(IMUL_R)
  322. INST_HANDLE(IMUL_M)
  323. INST_HANDLE(IMULH_R)
  324. INST_HANDLE(IMULH_M)
  325. INST_HANDLE(ISMULH_R)
  326. INST_HANDLE(ISMULH_M)
  327. INST_HANDLE(IDIV_C)
  328. INST_HANDLE(ISDIV_C)
  329. INST_HANDLE(INEG_R)
  330. INST_HANDLE(IXOR_R)
  331. INST_HANDLE(IXOR_M)
  332. INST_HANDLE(IROR_R)
  333. INST_HANDLE(IROL_R)
  334. //Common floating point
  335. INST_HANDLE(FPSWAP_R)
  336. //Floating point group F
  337. INST_HANDLE(FPADD_R)
  338. INST_HANDLE(FPADD_M)
  339. INST_HANDLE(FPSUB_R)
  340. INST_HANDLE(FPSUB_M)
  341. INST_HANDLE(FPNEG_R)
  342. //Floating point group E
  343. INST_HANDLE(FPMUL_R)
  344. INST_HANDLE(FPMUL_M)
  345. INST_HANDLE(FPDIV_R)
  346. INST_HANDLE(FPDIV_M)
  347. INST_HANDLE(FPSQRT_R)
  348. //Control
  349. INST_HANDLE(COND_R)
  350. INST_HANDLE(COND_M)
  351. INST_HANDLE(CFROUND)
  352. };
  353. }