Instruction.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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 << ((mod % 4) ? "L1" : "L2") << "[r" << (int)src << "]";
  25. }
  26. void Instruction::genAddressRegDst(std::ostream& os) const {
  27. os << ((mod % 4) ? "L1" : "L2") << "[r" << (int)dst << "]";
  28. }
  29. void Instruction::genAddressImm(std::ostream& os) const {
  30. os << "L3" << "[" << (imm32 & ScratchpadL3Mask) << "]";
  31. }
  32. void Instruction::h_IADD_R(std::ostream& os) const {
  33. if (src != dst) {
  34. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  35. }
  36. else {
  37. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  38. }
  39. }
  40. void Instruction::h_IADD_M(std::ostream& os) const {
  41. if (src != dst) {
  42. os << "r" << (int)dst << ", ";
  43. genAddressReg(os);
  44. os << std::endl;
  45. }
  46. else {
  47. os << "r" << (int)dst << ", ";
  48. genAddressImm(os);
  49. os << std::endl;
  50. }
  51. }
  52. void Instruction::h_IADD_RC(std::ostream& os) const {
  53. os << "r" << (int)dst << ", r" << (int)src << ", " << (int32_t)imm32 << std::endl;
  54. }
  55. //1 uOP
  56. void Instruction::h_ISUB_R(std::ostream& os) const {
  57. if (src != dst) {
  58. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  59. }
  60. else {
  61. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  62. }
  63. }
  64. void Instruction::h_ISUB_M(std::ostream& os) const {
  65. if (src != dst) {
  66. os << "r" << (int)dst << ", ";
  67. genAddressReg(os);
  68. os << std::endl;
  69. }
  70. else {
  71. os << "r" << (int)dst << ", ";
  72. genAddressImm(os);
  73. os << std::endl;
  74. }
  75. }
  76. void Instruction::h_IMUL_9C(std::ostream& os) const {
  77. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  78. }
  79. void Instruction::h_IMUL_R(std::ostream& os) const {
  80. if (src != dst) {
  81. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  82. }
  83. else {
  84. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  85. }
  86. }
  87. void Instruction::h_IMUL_M(std::ostream& os) const {
  88. if (src != dst) {
  89. os << "r" << (int)dst << ", ";
  90. genAddressReg(os);
  91. os << std::endl;
  92. }
  93. else {
  94. os << "r" << (int)dst << ", ";
  95. genAddressImm(os);
  96. os << std::endl;
  97. }
  98. }
  99. void Instruction::h_IMULH_R(std::ostream& os) const {
  100. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  101. }
  102. void Instruction::h_IMULH_M(std::ostream& os) const {
  103. if (src != dst) {
  104. os << "r" << (int)dst << ", ";
  105. genAddressReg(os);
  106. os << std::endl;
  107. }
  108. else {
  109. os << "r" << (int)dst << ", ";
  110. genAddressImm(os);
  111. os << std::endl;
  112. }
  113. }
  114. void Instruction::h_ISMULH_R(std::ostream& os) const {
  115. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  116. }
  117. void Instruction::h_ISMULH_M(std::ostream& os) const {
  118. if (src != dst) {
  119. os << "r" << (int)dst << ", ";
  120. genAddressReg(os);
  121. os << std::endl;
  122. }
  123. else {
  124. os << "r" << (int)dst << ", ";
  125. genAddressImm(os);
  126. os << std::endl;
  127. }
  128. }
  129. void Instruction::h_INEG_R(std::ostream& os) const {
  130. os << "r" << (int)dst << std::endl;
  131. }
  132. void Instruction::h_IXOR_R(std::ostream& os) const {
  133. if (src != dst) {
  134. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  135. }
  136. else {
  137. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  138. }
  139. }
  140. void Instruction::h_IXOR_M(std::ostream& os) const {
  141. if (src != dst) {
  142. os << "r" << (int)dst << ", ";
  143. genAddressReg(os);
  144. os << std::endl;
  145. }
  146. else {
  147. os << "r" << (int)dst << ", ";
  148. genAddressImm(os);
  149. os << std::endl;
  150. }
  151. }
  152. void Instruction::h_IROR_R(std::ostream& os) const {
  153. if (src != dst) {
  154. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  155. }
  156. else {
  157. os << "r" << (int)dst << ", " << (imm32 & 63) << std::endl;
  158. }
  159. }
  160. void Instruction::h_IROL_R(std::ostream& os) const {
  161. if (src != dst) {
  162. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  163. }
  164. else {
  165. os << "r" << (int)dst << ", " << (imm32 & 63) << std::endl;
  166. }
  167. }
  168. void Instruction::h_IDIV_C(std::ostream& os) const {
  169. os << "r" << (int)dst << ", " << imm32 << std::endl;
  170. }
  171. void Instruction::h_ISDIV_C(std::ostream& os) const {
  172. os << "r" << (int)dst << ", " << (int32_t)imm32 << std::endl;
  173. }
  174. void Instruction::h_ISWAP_R(std::ostream& os) const {
  175. os << "r" << (int)dst << ", r" << (int)src << std::endl;
  176. }
  177. void Instruction::h_FSWAP_R(std::ostream& os) const {
  178. const char reg = (dst >= 4) ? 'e' : 'f';
  179. auto dstIndex = dst % 4;
  180. os << reg << dstIndex << std::endl;
  181. }
  182. void Instruction::h_FADD_R(std::ostream& os) const {
  183. auto dstIndex = dst % 4;
  184. auto srcIndex = src % 4;
  185. os << "f" << dstIndex << ", a" << srcIndex << std::endl;
  186. }
  187. void Instruction::h_FADD_M(std::ostream& os) const {
  188. auto dstIndex = dst % 4;
  189. os << "f" << dstIndex << ", ";
  190. genAddressReg(os);
  191. os << std::endl;
  192. }
  193. void Instruction::h_FSUB_R(std::ostream& os) const {
  194. auto dstIndex = dst % 4;
  195. auto srcIndex = src % 4;
  196. os << "f" << dstIndex << ", a" << srcIndex << std::endl;
  197. }
  198. void Instruction::h_FSUB_M(std::ostream& os) const {
  199. auto dstIndex = dst % 4;
  200. os << "f" << dstIndex << ", ";
  201. genAddressReg(os);
  202. os << std::endl;
  203. }
  204. void Instruction::h_FSCAL_R(std::ostream& os) const {
  205. auto dstIndex = dst % 4;
  206. os << "f" << dstIndex << std::endl;
  207. }
  208. void Instruction::h_FMUL_R(std::ostream& os) const {
  209. auto dstIndex = dst % 4;
  210. auto srcIndex = src % 4;
  211. os << "e" << dstIndex << ", a" << srcIndex << std::endl;
  212. }
  213. void Instruction::h_FMUL_M(std::ostream& os) const {
  214. auto dstIndex = dst % 4;
  215. os << "e" << dstIndex << ", ";
  216. genAddressReg(os);
  217. os << std::endl;
  218. }
  219. void Instruction::h_FDIV_R(std::ostream& os) const {
  220. auto dstIndex = dst % 4;
  221. auto srcIndex = src % 4;
  222. os << "e" << dstIndex << ", a" << srcIndex << std::endl;
  223. }
  224. void Instruction::h_FDIV_M(std::ostream& os) const {
  225. auto dstIndex = dst % 4;
  226. os << "e" << dstIndex << ", ";
  227. genAddressReg(os);
  228. os << std::endl;
  229. }
  230. void Instruction::h_FSQRT_R(std::ostream& os) const {
  231. auto dstIndex = dst % 4;
  232. os << "e" << dstIndex << std::endl;
  233. }
  234. void Instruction::h_CFROUND(std::ostream& os) const {
  235. os << "r" << (int)src << ", " << (imm32 & 63) << std::endl;
  236. }
  237. static inline const char* condition(int index) {
  238. switch (index)
  239. {
  240. case 0:
  241. return "be";
  242. case 1:
  243. return "ab";
  244. case 2:
  245. return "sg";
  246. case 3:
  247. return "ns";
  248. case 4:
  249. return "of";
  250. case 5:
  251. return "no";
  252. case 6:
  253. return "lt";
  254. case 7:
  255. return "ge";
  256. default:
  257. UNREACHABLE;
  258. }
  259. }
  260. void Instruction::h_COND_R(std::ostream& os) const {
  261. os << "r" << (int)dst << ", " << condition((mod >> 2) & 7) << "(r" << (int)src << ", " << (int32_t)imm32 << ")" << std::endl;
  262. }
  263. void Instruction::h_COND_M(std::ostream& os) const {
  264. os << "r" << (int)dst << ", " << condition((mod >> 2) & 7) << "(";
  265. genAddressReg(os);
  266. os << ", " << (int32_t)imm32 << ")" << std::endl;
  267. }
  268. void Instruction::h_ISTORE(std::ostream& os) const {
  269. genAddressRegDst(os);
  270. os << ", r" << (int)src << std::endl;
  271. }
  272. void Instruction::h_FSTORE(std::ostream& os) const {
  273. const char reg = (src >= 4) ? 'e' : 'f';
  274. genAddressRegDst(os);
  275. auto srcIndex = src % 4;
  276. os << ", " << reg << srcIndex << std::endl;
  277. }
  278. void Instruction::h_NOP(std::ostream& os) const {
  279. os << std::endl;
  280. }
  281. #include "instructionWeights.hpp"
  282. #define INST_NAME(x) REPN(#x, WT(x))
  283. #define INST_HANDLE(x) REPN(&Instruction::h_##x, WT(x))
  284. const char* Instruction::names[256] = {
  285. //Integer
  286. INST_NAME(IADD_R)
  287. INST_NAME(IADD_M)
  288. INST_NAME(IADD_RC)
  289. INST_NAME(ISUB_R)
  290. INST_NAME(ISUB_M)
  291. INST_NAME(IMUL_9C)
  292. INST_NAME(IMUL_R)
  293. INST_NAME(IMUL_M)
  294. INST_NAME(IMULH_R)
  295. INST_NAME(IMULH_M)
  296. INST_NAME(ISMULH_R)
  297. INST_NAME(ISMULH_M)
  298. INST_NAME(IDIV_C)
  299. INST_NAME(ISDIV_C)
  300. INST_NAME(INEG_R)
  301. INST_NAME(IXOR_R)
  302. INST_NAME(IXOR_M)
  303. INST_NAME(IROR_R)
  304. INST_NAME(IROL_R)
  305. INST_NAME(ISWAP_R)
  306. //Common floating point
  307. INST_NAME(FSWAP_R)
  308. //Floating point group F
  309. INST_NAME(FADD_R)
  310. INST_NAME(FADD_M)
  311. INST_NAME(FSUB_R)
  312. INST_NAME(FSUB_M)
  313. INST_NAME(FSCAL_R)
  314. //Floating point group E
  315. INST_NAME(FMUL_R)
  316. INST_NAME(FMUL_M)
  317. INST_NAME(FDIV_R)
  318. INST_NAME(FDIV_M)
  319. INST_NAME(FSQRT_R)
  320. //Control
  321. INST_NAME(COND_R)
  322. INST_NAME(COND_M)
  323. INST_NAME(CFROUND)
  324. INST_NAME(ISTORE)
  325. INST_NAME(FSTORE)
  326. INST_NAME(NOP)
  327. };
  328. InstructionVisualizer Instruction::engine[256] = {
  329. //Integer
  330. INST_HANDLE(IADD_R)
  331. INST_HANDLE(IADD_M)
  332. INST_HANDLE(IADD_RC)
  333. INST_HANDLE(ISUB_R)
  334. INST_HANDLE(ISUB_M)
  335. INST_HANDLE(IMUL_9C)
  336. INST_HANDLE(IMUL_R)
  337. INST_HANDLE(IMUL_M)
  338. INST_HANDLE(IMULH_R)
  339. INST_HANDLE(IMULH_M)
  340. INST_HANDLE(ISMULH_R)
  341. INST_HANDLE(ISMULH_M)
  342. INST_HANDLE(IDIV_C)
  343. INST_HANDLE(ISDIV_C)
  344. INST_HANDLE(INEG_R)
  345. INST_HANDLE(IXOR_R)
  346. INST_HANDLE(IXOR_M)
  347. INST_HANDLE(IROR_R)
  348. INST_HANDLE(IROL_R)
  349. INST_HANDLE(ISWAP_R)
  350. //Common floating point
  351. INST_HANDLE(FSWAP_R)
  352. //Floating point group F
  353. INST_HANDLE(FADD_R)
  354. INST_HANDLE(FADD_M)
  355. INST_HANDLE(FSUB_R)
  356. INST_HANDLE(FSUB_M)
  357. INST_HANDLE(FSCAL_R)
  358. //Floating point group E
  359. INST_HANDLE(FMUL_R)
  360. INST_HANDLE(FMUL_M)
  361. INST_HANDLE(FDIV_R)
  362. INST_HANDLE(FDIV_M)
  363. INST_HANDLE(FSQRT_R)
  364. //Control
  365. INST_HANDLE(COND_R)
  366. INST_HANDLE(COND_M)
  367. INST_HANDLE(CFROUND)
  368. INST_HANDLE(ISTORE)
  369. INST_HANDLE(FSTORE)
  370. INST_HANDLE(NOP)
  371. };
  372. }