The miasma theory
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

231 строка
10KB

  1. /*
  2. Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic
  3. Xiasma is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation.
  4. And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version.
  5. It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3.
  6. */
  7. #include <xolatile/xtandard.c>
  8. enum {
  9. FORMAT_NULL,
  10. FORMAT_REGISTER, FORMAT_VARIABLE, FORMAT_CONSTANT, FORMAT_VARIADIC,
  11. FORMAT_REGISTER_REGISTER, FORMAT_REGISTER_VARIABLE, FORMAT_REGISTER_CONSTANT, FORMAT_VARIABLE_REGISTER,
  12. FORMAT_VARIABLE_CONSTANT, FORMAT_VARIADIC_REGISTER, FORMAT_VARIADIC_VARIABLE, FORMAT_VARIADIC_CONSTANT,
  13. FORMAT_COUNT
  14. };
  15. enum {
  16. INSTRUCTION_NO_OPERATION, INSTRUCTION_MOVE, INSTRUCTION_CALL, INSTRUCTION_RETURN,
  17. INSTRUCTION_SYSTEM_ENTER, INSTRUCTION_SYSTEM_EXIT, INSTRUCTION_SYSTEM_CALL, INSTRUCTION_SYSTEM_RETURN,
  18. INSTRUCTION_ADD, INSTRUCTION_BIT_OR, INSTRUCTION_ADD_CARRY, INSTRUCTION_SUBTRACT_CARRY,
  19. INSTRUCTION_BIT_AND, INSTRUCTION_SUBTRACT, INSTRUCTION_BIT_EXCLUSIVE_OR, INSTRUCTION_COMPARE,
  20. INSTRUCTION_COUNT
  21. };
  22. enum {
  23. REGISTER_0_64, REGISTER_1_64, REGISTER_2_64, REGISTER_3_64, REGISTER_4_64, REGISTER_5_64, REGISTER_6_64, REGISTER_7_64,
  24. REGISTER_8_64, REGISTER_9_64, REGISTER_A_64, REGISTER_B_64, REGISTER_C_64, REGISTER_D_64, REGISTER_E_64, REGISTER_F_64,
  25. REGISTER_0_32, REGISTER_1_32, REGISTER_2_32, REGISTER_3_32, REGISTER_4_32, REGISTER_5_32, REGISTER_6_32, REGISTER_7_32,
  26. REGISTER_8_32, REGISTER_9_32, REGISTER_A_32, REGISTER_B_32, REGISTER_C_32, REGISTER_D_32, REGISTER_E_32, REGISTER_F_32,
  27. REGISTER_0_16, REGISTER_1_16, REGISTER_2_16, REGISTER_3_16, REGISTER_4_16, REGISTER_5_16, REGISTER_6_16, REGISTER_7_16,
  28. REGISTER_8_16, REGISTER_9_16, REGISTER_A_16, REGISTER_B_16, REGISTER_C_16, REGISTER_D_16, REGISTER_E_16, REGISTER_F_16,
  29. REGISTER_0_8, REGISTER_1_8, REGISTER_2_8, REGISTER_3_8, REGISTER_4_8, REGISTER_5_8, REGISTER_6_8, REGISTER_7_8,
  30. REGISTER_8_8, REGISTER_9_8, REGISTER_A_8, REGISTER_B_8, REGISTER_C_8, REGISTER_D_8, REGISTER_E_8, REGISTER_F_8,
  31. REGISTER_0_8X, REGISTER_1_8X, REGISTER_2_8X, REGISTER_3_8X,
  32. REGISTER_COUNT
  33. };
  34. static void (* encode [FORMAT_COUNT] [INSTRUCTION_COUNT]) (int instruction, int left, int right);
  35. static int data [16] = { 0 };
  36. static void data_push (int byte) { data [0]++; data [data [0]] = byte; }
  37. static void data_pop (void) { data [data [0]] = 0X00; data [0]--; }
  38. static int data_look (int look) { return (data [look]); }
  39. static int data_size (void) { return (data [0]); }
  40. static void data_free (void) { data [0] = 0; }
  41. static void data_echo (void) {
  42. char byte [4] = " ";
  43. int i;
  44. for (i = 0; i != data [0]; ++i) {
  45. byte [0] = "0123456789ABCDEF" [data [i + 1] / 16];
  46. byte [1] = "0123456789ABCDEF" [data [i + 1] % 16];
  47. echo (byte);
  48. }
  49. }
  50. static void unimplemented (int instruction, int left, int right) {
  51. (void) instruction;
  52. (void) left;
  53. (void) right;
  54. fatal_failure (1, "Unimplemented...");
  55. }
  56. static int register_word (char * name) {
  57. char * register_name [REGISTER_COUNT] = {
  58. "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
  59. "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
  60. "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
  61. "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
  62. "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
  63. "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",
  64. "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
  65. "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b",
  66. "ah", "ch", "dh", "bh"
  67. };
  68. int i;
  69. for (i = 0; i != REGISTER_COUNT; ++i) {
  70. if (string_compare (name, register_name [i]) != 0) {
  71. return (i);
  72. }
  73. }
  74. return (-1);
  75. }
  76. static int instruction_word (char * name) {
  77. char * instruction_name [INSTRUCTION_COUNT] = {
  78. "nop", "mov", "call", "ret", "sysenter", "sysexit", "syscall", "sysret",
  79. "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"
  80. };
  81. int i;
  82. for (i = 0; i != INSTRUCTION_COUNT; ++i) {
  83. if (string_compare (name, instruction_name [i]) != 0) {
  84. return (i);
  85. }
  86. }
  87. return (-1);
  88. }
  89. static void prefix_register_size (int left, int right) {
  90. if ((left >= REGISTER_0_64) && (left <= REGISTER_7_64) && (right >= REGISTER_0_64) && (right <= REGISTER_7_64)) {
  91. data_push (0X48);
  92. } else if ((left >= REGISTER_8_64) && (left <= REGISTER_F_64) && (right >= REGISTER_0_64) && (right <= REGISTER_7_64)) {
  93. data_push (0X49);
  94. } else if ((left >= REGISTER_0_64) && (left <= REGISTER_7_64) && (right >= REGISTER_8_64) && (right <= REGISTER_F_64)) {
  95. data_push (0X4C);
  96. } else if ((left >= REGISTER_8_64) && (left <= REGISTER_F_64) && (right >= REGISTER_8_64) && (right <= REGISTER_F_64)) {
  97. data_push (0X4D);
  98. } else if ((left >= REGISTER_0_16) && (left <= REGISTER_7_16)) {
  99. data_push (0X66);
  100. } else if ((left >= REGISTER_8_16) && (left <= REGISTER_F_16)) {
  101. data_push (0X67);
  102. } else {
  103. fatal_failure (1, "prefix_register_size");
  104. }
  105. }
  106. static void infix_regular_instruction (int instruction) {
  107. switch (instruction) {
  108. case INSTRUCTION_ADD: data_push (0X01); break;
  109. case INSTRUCTION_BIT_OR: data_push (0X09); break;
  110. case INSTRUCTION_ADD_CARRY: data_push (0X11); break;
  111. case INSTRUCTION_SUBTRACT_CARRY: data_push (0X19); break;
  112. case INSTRUCTION_BIT_AND: data_push (0X21); break;
  113. case INSTRUCTION_SUBTRACT: data_push (0X29); break;
  114. case INSTRUCTION_BIT_EXCLUSIVE_OR: data_push (0X31); break;
  115. case INSTRUCTION_COMPARE: data_push (0X39); break;
  116. case INSTRUCTION_MOVE: data_push (0X89); break;
  117. }
  118. }
  119. static void suffix_register_combination (int left, int right) {
  120. data_push (((0X0C + ((right % 8) / 2)) << 4) | ((right % 2) * 8 + (left % 8)));
  121. }
  122. static void encode_regular_register_register (int instruction, int left, int right) {
  123. prefix_register_size (left, right);
  124. infix_regular_instruction (instruction);
  125. suffix_register_combination (left, right);
  126. }
  127. int main (void) {
  128. /* Won't be hardcoded, will use multiple files like 'gnatmake'... */
  129. char * source [48] = {
  130. "add", "rax", "r15",
  131. "or", "rcx", "r15",
  132. "adc", "rdx", "r15",
  133. "sbb", "rbx", "r15",
  134. "and", "rsp", "r15",
  135. "sub", "rbp", "r15",
  136. "xor", "rsi", "r15",
  137. "cmp", "rdi", "r15",
  138. "mov", "r8", "r15",
  139. "mov", "r9", "r15",
  140. "mov", "r10", "r15",
  141. "mov", "r11", "r15",
  142. "mov", "r12", "r15",
  143. "mov", "r13", "r15",
  144. "mov", "r14", "r15",
  145. "mov", "r15", "r15"
  146. };
  147. int buffer [48];
  148. int i, j;
  149. for (i = 0; i != FORMAT_COUNT; ++i) {
  150. for (j = 0; j != INSTRUCTION_COUNT; ++j) {
  151. encode [i] [j] = unimplemented;
  152. }
  153. }
  154. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_ADD] = encode_regular_register_register;
  155. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_OR] = encode_regular_register_register;
  156. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_ADD_CARRY] = encode_regular_register_register;
  157. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_SUBTRACT_CARRY] = encode_regular_register_register;
  158. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_AND] = encode_regular_register_register;
  159. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_SUBTRACT] = encode_regular_register_register;
  160. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_BIT_EXCLUSIVE_OR] = encode_regular_register_register;
  161. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_COMPARE] = encode_regular_register_register;
  162. encode [FORMAT_REGISTER_REGISTER] [INSTRUCTION_MOVE] = encode_regular_register_register;
  163. for (i = 0; i != 48; ++i) {
  164. /* These depend on format, will not assume IRR... */
  165. if ((buffer [i] = instruction_word (source [i])) == -1) {
  166. echo ("Word must be an instruction!\n");
  167. echo ("This '");
  168. echo (source [i]);
  169. echo ("' is not an instruction...\n");
  170. exit (EXIT_FAILURE);
  171. } ++i;
  172. if ((buffer [i] = register_word (source [i])) == -1) {
  173. echo ("Word must be a register!\n");
  174. echo ("This '");
  175. echo (source [i]);
  176. echo ("' is not a register...\n");
  177. exit (EXIT_FAILURE);
  178. } ++i;
  179. if ((buffer [i] = register_word (source [i])) == -1) {
  180. echo ("Word must be a register!\n");
  181. echo ("This '");
  182. echo (source [i]);
  183. echo ("' is not a register...\n");
  184. exit (EXIT_FAILURE);
  185. }
  186. echo ("\033[1;33m");
  187. echo (source [i - 2]);
  188. echo ("\033[0m \033[1;34m");
  189. echo (source [i - 1]);
  190. echo ("\033[0m \033[1;35m");
  191. echo (source [i]);
  192. echo ("\033[0m --- ");
  193. encode [FORMAT_REGISTER_REGISTER] [buffer [i - 2]] (buffer [i - 2], buffer [i - 1], buffer [i]);
  194. data_echo ();
  195. data_free ();
  196. echo ("\n");
  197. }
  198. return (EXIT_SUCCESS);
  199. }