gen_opcode_table.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Generate opcode table initializers for the in-kernel disassembler.
  4. *
  5. * Copyright IBM Corp. 2017
  6. *
  7. */
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <stdio.h>
  12. #define STRING_SIZE_MAX 20
  13. struct insn_type {
  14. unsigned char byte;
  15. unsigned char mask;
  16. char **format;
  17. };
  18. struct insn {
  19. struct insn_type *type;
  20. char opcode[STRING_SIZE_MAX];
  21. char name[STRING_SIZE_MAX];
  22. char upper[STRING_SIZE_MAX];
  23. char format[STRING_SIZE_MAX];
  24. unsigned int name_len;
  25. };
  26. struct insn_group {
  27. struct insn_type *type;
  28. int offset;
  29. int count;
  30. char opcode[2];
  31. };
  32. struct insn_format {
  33. char *format;
  34. int type;
  35. };
  36. struct gen_opcode {
  37. struct insn *insn;
  38. int nr;
  39. struct insn_group *group;
  40. int nr_groups;
  41. };
  42. /*
  43. * Table of instruction format types. Each opcode is defined with at
  44. * least one byte (two nibbles), three nibbles, or two bytes (four
  45. * nibbles).
  46. * The byte member of each instruction format type entry defines
  47. * within which byte of an instruction the third (and fourth) nibble
  48. * of an opcode can be found. The mask member is the and-mask that
  49. * needs to be applied on this byte in order to get the third (and
  50. * fourth) nibble of the opcode.
  51. * The format array defines all instruction formats (as defined in the
  52. * Principles of Operation) which have the same position of the opcode
  53. * nibbles.
  54. * A special case are instruction formats with 1-byte opcodes. In this
  55. * case the byte member always is zero, so that the mask is applied on
  56. * the (only) byte that contains the opcode.
  57. */
  58. static struct insn_type insn_type_table[] = {
  59. {
  60. .byte = 0,
  61. .mask = 0xff,
  62. .format = (char *[]) {
  63. "MII",
  64. "RR",
  65. "RS",
  66. "RSI",
  67. "RX",
  68. "SI",
  69. "SMI",
  70. "SS",
  71. NULL,
  72. },
  73. },
  74. {
  75. .byte = 1,
  76. .mask = 0x0f,
  77. .format = (char *[]) {
  78. "RI",
  79. "RIL",
  80. "SSF",
  81. NULL,
  82. },
  83. },
  84. {
  85. .byte = 1,
  86. .mask = 0xff,
  87. .format = (char *[]) {
  88. "E",
  89. "IE",
  90. "RRE",
  91. "RRF",
  92. "RRR",
  93. "S",
  94. "SIL",
  95. "SSE",
  96. NULL,
  97. },
  98. },
  99. {
  100. .byte = 5,
  101. .mask = 0xff,
  102. .format = (char *[]) {
  103. "RIE",
  104. "RIS",
  105. "RRS",
  106. "RSE",
  107. "RSL",
  108. "RSY",
  109. "RXE",
  110. "RXF",
  111. "RXY",
  112. "SIY",
  113. "VRI",
  114. "VRR",
  115. "VRS",
  116. "VRV",
  117. "VRX",
  118. "VSI",
  119. NULL,
  120. },
  121. },
  122. };
  123. static struct insn_type *insn_format_to_type(char *format)
  124. {
  125. char tmp[STRING_SIZE_MAX];
  126. char *base_format, **ptr;
  127. int i;
  128. strcpy(tmp, format);
  129. base_format = tmp;
  130. base_format = strsep(&base_format, "_");
  131. for (i = 0; i < sizeof(insn_type_table) / sizeof(insn_type_table[0]); i++) {
  132. ptr = insn_type_table[i].format;
  133. while (*ptr) {
  134. if (!strcmp(base_format, *ptr))
  135. return &insn_type_table[i];
  136. ptr++;
  137. }
  138. }
  139. exit(EXIT_FAILURE);
  140. }
  141. static void read_instructions(struct gen_opcode *desc)
  142. {
  143. struct insn insn;
  144. int rc, i;
  145. while (1) {
  146. rc = scanf("%s %s %s", insn.opcode, insn.name, insn.format);
  147. if (rc == EOF)
  148. break;
  149. if (rc != 3)
  150. exit(EXIT_FAILURE);
  151. insn.type = insn_format_to_type(insn.format);
  152. insn.name_len = strlen(insn.name);
  153. for (i = 0; i <= insn.name_len; i++)
  154. insn.upper[i] = toupper((unsigned char)insn.name[i]);
  155. desc->nr++;
  156. desc->insn = realloc(desc->insn, desc->nr * sizeof(*desc->insn));
  157. if (!desc->insn)
  158. exit(EXIT_FAILURE);
  159. desc->insn[desc->nr - 1] = insn;
  160. }
  161. }
  162. static int cmpformat(const void *a, const void *b)
  163. {
  164. return strcmp(((struct insn *)a)->format, ((struct insn *)b)->format);
  165. }
  166. static void print_formats(struct gen_opcode *desc)
  167. {
  168. char *format;
  169. int i, count;
  170. qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpformat);
  171. format = "";
  172. count = 0;
  173. printf("enum {\n");
  174. for (i = 0; i < desc->nr; i++) {
  175. if (!strcmp(format, desc->insn[i].format))
  176. continue;
  177. count++;
  178. format = desc->insn[i].format;
  179. printf("\tINSTR_%s,\n", format);
  180. }
  181. printf("}; /* %d */\n\n", count);
  182. }
  183. static int cmp_long_insn(const void *a, const void *b)
  184. {
  185. return strcmp(((struct insn *)a)->name, ((struct insn *)b)->name);
  186. }
  187. static void print_long_insn(struct gen_opcode *desc)
  188. {
  189. struct insn *insn;
  190. int i, count;
  191. qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmp_long_insn);
  192. count = 0;
  193. printf("enum {\n");
  194. for (i = 0; i < desc->nr; i++) {
  195. insn = &desc->insn[i];
  196. if (insn->name_len < 6)
  197. continue;
  198. printf("\tLONG_INSN_%s,\n", insn->upper);
  199. count++;
  200. }
  201. printf("}; /* %d */\n\n", count);
  202. printf("#define LONG_INSN_INITIALIZER { \\\n");
  203. for (i = 0; i < desc->nr; i++) {
  204. insn = &desc->insn[i];
  205. if (insn->name_len < 6)
  206. continue;
  207. printf("\t[LONG_INSN_%s] = \"%s\", \\\n", insn->upper, insn->name);
  208. }
  209. printf("}\n\n");
  210. }
  211. static void print_opcode(struct insn *insn, int nr)
  212. {
  213. char *opcode;
  214. opcode = insn->opcode;
  215. if (insn->type->byte != 0)
  216. opcode += 2;
  217. printf("\t[%4d] = { .opfrag = 0x%s, .format = INSTR_%s, ", nr, opcode, insn->format);
  218. if (insn->name_len < 6)
  219. printf(".name = \"%s\" ", insn->name);
  220. else
  221. printf(".offset = LONG_INSN_%s ", insn->upper);
  222. printf("}, \\\n");
  223. }
  224. static void add_to_group(struct gen_opcode *desc, struct insn *insn, int offset)
  225. {
  226. struct insn_group *group;
  227. group = desc->group ? &desc->group[desc->nr_groups - 1] : NULL;
  228. if (group && (!strncmp(group->opcode, insn->opcode, 2) || group->type->byte == 0)) {
  229. group->count++;
  230. return;
  231. }
  232. desc->nr_groups++;
  233. desc->group = realloc(desc->group, desc->nr_groups * sizeof(*desc->group));
  234. if (!desc->group)
  235. exit(EXIT_FAILURE);
  236. group = &desc->group[desc->nr_groups - 1];
  237. memcpy(group->opcode, insn->opcode, 2);
  238. group->type = insn->type;
  239. group->offset = offset;
  240. group->count = 1;
  241. }
  242. static int cmpopcode(const void *a, const void *b)
  243. {
  244. return strcmp(((struct insn *)a)->opcode, ((struct insn *)b)->opcode);
  245. }
  246. static void print_opcode_table(struct gen_opcode *desc)
  247. {
  248. char opcode[2] = "";
  249. struct insn *insn;
  250. int i, offset;
  251. qsort(desc->insn, desc->nr, sizeof(*desc->insn), cmpopcode);
  252. printf("#define OPCODE_TABLE_INITIALIZER { \\\n");
  253. offset = 0;
  254. for (i = 0; i < desc->nr; i++) {
  255. insn = &desc->insn[i];
  256. if (insn->type->byte == 0)
  257. continue;
  258. add_to_group(desc, insn, offset);
  259. if (strncmp(opcode, insn->opcode, 2)) {
  260. memcpy(opcode, insn->opcode, 2);
  261. printf("\t/* %.2s */ \\\n", opcode);
  262. }
  263. print_opcode(insn, offset);
  264. offset++;
  265. }
  266. printf("\t/* 1-byte opcode instructions */ \\\n");
  267. for (i = 0; i < desc->nr; i++) {
  268. insn = &desc->insn[i];
  269. if (insn->type->byte != 0)
  270. continue;
  271. add_to_group(desc, insn, offset);
  272. print_opcode(insn, offset);
  273. offset++;
  274. }
  275. printf("}\n\n");
  276. }
  277. static void print_opcode_table_offsets(struct gen_opcode *desc)
  278. {
  279. struct insn_group *group;
  280. int i;
  281. printf("#define OPCODE_OFFSET_INITIALIZER { \\\n");
  282. for (i = 0; i < desc->nr_groups; i++) {
  283. group = &desc->group[i];
  284. printf("\t{ .opcode = 0x%.2s, .mask = 0x%02x, .byte = %d, .offset = %d, .count = %d }, \\\n",
  285. group->opcode, group->type->mask, group->type->byte, group->offset, group->count);
  286. }
  287. printf("}\n\n");
  288. }
  289. int main(int argc, char **argv)
  290. {
  291. struct gen_opcode _desc = { 0 };
  292. struct gen_opcode *desc = &_desc;
  293. read_instructions(desc);
  294. printf("#ifndef __S390_GENERATED_DIS_DEFS_H__\n");
  295. printf("#define __S390_GENERATED_DIS_DEFS_H__\n");
  296. printf("/*\n");
  297. printf(" * DO NOT MODIFY.\n");
  298. printf(" *\n");
  299. printf(" * This file was generated by %s\n", __FILE__);
  300. printf(" */\n\n");
  301. print_formats(desc);
  302. print_long_insn(desc);
  303. print_opcode_table(desc);
  304. print_opcode_table_offsets(desc);
  305. printf("#endif\n");
  306. exit(EXIT_SUCCESS);
  307. }