Assembly.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "pch.h"
  2. #include "Assembly.h"
  3. #include "CppUnitTest.h"
  4. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  5. int globalFunc(int a, int b)
  6. {
  7. return a * b;
  8. }
  9. class A
  10. {
  11. public:
  12. virtual int getValue()
  13. {
  14. return 0;
  15. }
  16. };
  17. class B : public A
  18. {
  19. public:
  20. virtual int getValue() override
  21. {
  22. return 10;
  23. }
  24. };
  25. namespace FrameworkTests
  26. {
  27. TEST_CLASS (AssemblyTests)
  28. {
  29. public:
  30. TEST_METHOD (Add8Test)
  31. {
  32. Framework::Assembly::AssemblyBlock codeBlock;
  33. codeBlock.addMoveValue(Framework::Assembly::RAX,
  34. Framework::Assembly::RDX,
  35. Framework::Assembly::LOWER8);
  36. codeBlock.addInstruction(
  37. new Framework::Assembly::Instruction(Framework::Assembly::ADD,
  38. {new Framework::Assembly::GPRegisterArgument(
  39. Framework::Assembly::RAX, Framework::Assembly::LOWER8),
  40. new Framework::Assembly::GPRegisterArgument(
  41. Framework::Assembly::RCX,
  42. Framework::Assembly::LOWER8)}));
  43. char (*add)(char a, char b)
  44. = (char (*)(char, char))codeBlock.compile();
  45. char result = add(22, 15);
  46. char result2 = add(5, 6);
  47. Assert::AreEqual((char)37, result);
  48. Assert::AreEqual((char)11, result2);
  49. }
  50. TEST_METHOD (Add16Test)
  51. {
  52. Framework::Assembly::AssemblyBlock codeBlock;
  53. codeBlock.addMoveValue(Framework::Assembly::RAX,
  54. Framework::Assembly::RDX,
  55. Framework::Assembly::LOWER16);
  56. codeBlock.addInstruction(new Framework::Assembly::Instruction(
  57. Framework::Assembly::ADD,
  58. {new Framework::Assembly::GPRegisterArgument(
  59. Framework::Assembly::RAX, Framework::Assembly::LOWER16),
  60. new Framework::Assembly::GPRegisterArgument(
  61. Framework::Assembly::RCX,
  62. Framework::Assembly::LOWER16)}));
  63. short (*add)(short a, short b)
  64. = (short (*)(short, short))codeBlock.compile();
  65. short result = add(22, 15);
  66. short result2 = add(5, 6);
  67. Assert::AreEqual((short)37, result);
  68. Assert::AreEqual((short)11, result2);
  69. }
  70. TEST_METHOD (Add32Test)
  71. {
  72. Framework::Assembly::AssemblyBlock codeBlock;
  73. codeBlock.addMoveValue(Framework::Assembly::RAX,
  74. Framework::Assembly::RDX,
  75. Framework::Assembly::LOWER32);
  76. codeBlock.addInstruction(new Framework::Assembly::Instruction(
  77. Framework::Assembly::ADD,
  78. {new Framework::Assembly::GPRegisterArgument(
  79. Framework::Assembly::RAX, Framework::Assembly::LOWER32),
  80. new Framework::Assembly::GPRegisterArgument(
  81. Framework::Assembly::RCX,
  82. Framework::Assembly::LOWER32)}));
  83. int (*add)(int a, int b) = (int (*)(int, int))codeBlock.compile();
  84. int result = add(22, 15);
  85. int result2 = add(5, 6);
  86. Assert::AreEqual((int)37, result);
  87. Assert::AreEqual((int)11, result2);
  88. }
  89. TEST_METHOD (Add64Test)
  90. {
  91. Framework::Assembly::AssemblyBlock codeBlock;
  92. codeBlock.addMoveValue(
  93. Framework::Assembly::RAX, Framework::Assembly::RDX);
  94. codeBlock.addInstruction(
  95. new Framework::Assembly::Instruction(Framework::Assembly::ADD,
  96. {new Framework::Assembly::GPRegisterArgument(
  97. Framework::Assembly::RAX),
  98. new Framework::Assembly::GPRegisterArgument(
  99. Framework::Assembly::RCX)}));
  100. __int64 (*add)(__int64 a, __int64 b)
  101. = (__int64 (*)(__int64, __int64))codeBlock.compile();
  102. __int64 result = add(22, 15);
  103. __int64 result2 = add(5, 6);
  104. Assert::AreEqual((__int64)37, result);
  105. Assert::AreEqual((__int64)11, result2);
  106. }
  107. TEST_METHOD (AddFloatTest)
  108. {
  109. Framework::Assembly::AssemblyBlock codeBlock;
  110. codeBlock.addInstruction(
  111. new Framework::Assembly::Instruction(Framework::Assembly::ADDSS,
  112. {new Framework::Assembly::FPRegisterArgument(
  113. Framework::Assembly::MM0,
  114. Framework::Assembly::FPRegisterPart::X),
  115. new Framework::Assembly::FPRegisterArgument(
  116. Framework::Assembly::MM1,
  117. Framework::Assembly::FPRegisterPart::X)}));
  118. float (*add)(float a, float b)
  119. = (float (*)(float, float))codeBlock.compile();
  120. float result = add(4.24f, 8.54f);
  121. float result2 = add(0.3f, 7.6f);
  122. Assert::AreEqual((float)(4.24f + 8.54f), result);
  123. Assert::AreEqual((float)(0.3f + 7.6f), result2);
  124. }
  125. TEST_METHOD (AddDoubleTest)
  126. {
  127. Framework::Assembly::AssemblyBlock codeBlock;
  128. codeBlock.addInstruction(
  129. new Framework::Assembly::Instruction(Framework::Assembly::ADDSD,
  130. {new Framework::Assembly::FPRegisterArgument(
  131. Framework::Assembly::MM0,
  132. Framework::Assembly::FPRegisterPart::X),
  133. new Framework::Assembly::FPRegisterArgument(
  134. Framework::Assembly::MM1,
  135. Framework::Assembly::FPRegisterPart::X)}));
  136. double (*add)(double a, double b)
  137. = (double (*)(double, double))codeBlock.compile();
  138. double result = add(4.24, 8.54);
  139. double result2 = add(0.3, 7.6);
  140. Assert::AreEqual(4.24 + 8.54, result);
  141. Assert::AreEqual(0.3 + 7.6, result2);
  142. }
  143. TEST_METHOD (returnRefTest)
  144. {
  145. char cRef = 1;
  146. short sRef = 2;
  147. int iRef = 3;
  148. __int64 lRef = 4;
  149. float fRef = 5.0f;
  150. double dRef = 6.0;
  151. Framework::Assembly::AssemblyBlock ccodeBlock;
  152. ccodeBlock.addLoadValue(&cRef, Framework::Assembly::RAX);
  153. char (*getc)() = (char (*)())ccodeBlock.compile();
  154. char cresult = getc();
  155. Assert::AreEqual((char)1, cresult);
  156. cRef = 11;
  157. cresult = getc();
  158. Assert::AreEqual((char)11, cresult);
  159. Framework::Assembly::AssemblyBlock scodeBlock;
  160. scodeBlock.addLoadValue(&sRef, Framework::Assembly::RAX);
  161. short (*gets)() = (short (*)())scodeBlock.compile();
  162. short sresult = gets();
  163. Assert::AreEqual((short)2, sresult);
  164. sRef = 22;
  165. sresult = gets();
  166. Assert::AreEqual((short)22, sresult);
  167. Framework::Assembly::AssemblyBlock icodeBlock;
  168. icodeBlock.addLoadValue(&iRef, Framework::Assembly::RAX);
  169. int (*geti)() = (int (*)())icodeBlock.compile();
  170. int iresult = geti();
  171. Assert::AreEqual((int)3, iresult);
  172. iRef = 33;
  173. iresult = geti();
  174. Assert::AreEqual((int)33, iresult);
  175. Framework::Assembly::AssemblyBlock lcodeBlock;
  176. lcodeBlock.addLoadValue(&lRef, Framework::Assembly::RAX);
  177. __int64 (*getl)() = (__int64 (*)())lcodeBlock.compile();
  178. __int64 lresult = getl();
  179. Assert::AreEqual((__int64)4, lresult);
  180. lRef = 44;
  181. lresult = getl();
  182. Assert::AreEqual((__int64)44, lresult);
  183. Framework::Assembly::AssemblyBlock fcodeBlock;
  184. fcodeBlock.addLoadValue(&fRef, Framework::Assembly::MM0);
  185. float (*getf)() = (float (*)())fcodeBlock.compile();
  186. float fresult = getf();
  187. Assert::AreEqual((float)5.0f, fresult);
  188. fRef = 55.0f;
  189. fresult = getf();
  190. Assert::AreEqual((float)55.0f, fresult);
  191. Framework::Assembly::AssemblyBlock dcodeBlock;
  192. dcodeBlock.addLoadValue(&dRef, Framework::Assembly::MM0);
  193. double (*getd)() = (double (*)())dcodeBlock.compile();
  194. double dresult = getd();
  195. Assert::AreEqual((double)6.0, dresult);
  196. dRef = 66.0;
  197. dresult = getd();
  198. Assert::AreEqual((double)66.0, dresult);
  199. }
  200. int c;
  201. int testMethod(int a, int b)
  202. {
  203. return a + b + c;
  204. }
  205. TEST_METHOD (testCall)
  206. {
  207. std::cout << 1.463f << 4.235;
  208. Framework::Assembly::AssemblyBlock gfcodeBlock;
  209. gfcodeBlock.addEnter();
  210. gfcodeBlock.addMoveValue(Framework::Assembly::RCX, 20);
  211. gfcodeBlock.addMoveValue(Framework::Assembly::RDX, 50);
  212. gfcodeBlock.addCall(globalFunc);
  213. gfcodeBlock.addLeave();
  214. int (*f)() = gfcodeBlock.compileToFunction<int (*)()>();
  215. int result = f();
  216. Assert::AreEqual(globalFunc(20, 50), result);
  217. Framework::Assembly::AssemblyBlock lfcodeBlock;
  218. lfcodeBlock.addEnter();
  219. lfcodeBlock.addLoadAddress(this, Framework::Assembly::RCX);
  220. lfcodeBlock.addMoveValue(Framework::Assembly::RCX, 20);
  221. lfcodeBlock.addMoveValue(Framework::Assembly::RDX, 50);
  222. lfcodeBlock.addMemberCall(&AssemblyTests::testMethod);
  223. lfcodeBlock.addLeave();
  224. c = 1;
  225. f = lfcodeBlock.compileToFunction<int (*)()>();
  226. result = f();
  227. A* a = new B();
  228. Assert::AreEqual(testMethod(20, 50), result);
  229. Framework::Assembly::AssemblyBlock vfcodeBlock;
  230. vfcodeBlock.addEnter();
  231. vfcodeBlock.addLoadAddress(a, Framework::Assembly::RCX);
  232. vfcodeBlock.addMemberCall(&A::getValue);
  233. vfcodeBlock.addLeave();
  234. c = 1;
  235. f = vfcodeBlock.compileToFunction<int (*)()>();
  236. result = f();
  237. Assert::AreEqual(a->getValue(), result);
  238. delete a;
  239. }
  240. };
  241. } // namespace FrameworkTests