s390-mkopc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
  2. Copyright (C) 2000-2022 Free Software Foundation, Inc.
  3. Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
  4. This file is part of the GNU opcodes library.
  5. This library is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. It is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  12. License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this file; see the file COPYING. If not, write to the
  15. Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "opcode/s390.h"
  21. struct op_struct
  22. {
  23. char opcode[16];
  24. char mnemonic[16];
  25. char format[16];
  26. int mode_bits;
  27. int min_cpu;
  28. int flags;
  29. unsigned long long sort_value;
  30. int no_nibbles;
  31. };
  32. struct op_struct *op_array;
  33. int max_ops;
  34. int no_ops;
  35. static void
  36. createTable (void)
  37. {
  38. max_ops = 256;
  39. op_array = malloc (max_ops * sizeof (struct op_struct));
  40. no_ops = 0;
  41. }
  42. /* `insertOpcode': insert an op_struct into sorted opcode array. */
  43. static void
  44. insertOpcode (char *opcode, char *mnemonic, char *format,
  45. int min_cpu, int mode_bits, int flags)
  46. {
  47. char *str;
  48. unsigned long long sort_value;
  49. int no_nibbles;
  50. int ix, k;
  51. while (no_ops >= max_ops)
  52. {
  53. max_ops = max_ops * 2;
  54. op_array = realloc (op_array, max_ops * sizeof (struct op_struct));
  55. }
  56. sort_value = 0;
  57. str = opcode;
  58. for (ix = 0; ix < 16; ix++)
  59. {
  60. if (*str >= '0' && *str <= '9')
  61. sort_value = (sort_value << 4) + (*str - '0');
  62. else if (*str >= 'a' && *str <= 'f')
  63. sort_value = (sort_value << 4) + (*str - 'a' + 10);
  64. else if (*str >= 'A' && *str <= 'F')
  65. sort_value = (sort_value << 4) + (*str - 'A' + 10);
  66. else if (*str == '?')
  67. sort_value <<= 4;
  68. else
  69. break;
  70. str ++;
  71. }
  72. sort_value <<= 4*(16 - ix);
  73. sort_value += (min_cpu << 8) + mode_bits;
  74. no_nibbles = ix;
  75. for (ix = 0; ix < no_ops; ix++)
  76. if (sort_value > op_array[ix].sort_value)
  77. break;
  78. for (k = no_ops; k > ix; k--)
  79. op_array[k] = op_array[k-1];
  80. strcpy(op_array[ix].opcode, opcode);
  81. strcpy(op_array[ix].mnemonic, mnemonic);
  82. strcpy(op_array[ix].format, format);
  83. op_array[ix].sort_value = sort_value;
  84. op_array[ix].no_nibbles = no_nibbles;
  85. op_array[ix].min_cpu = min_cpu;
  86. op_array[ix].mode_bits = mode_bits;
  87. op_array[ix].flags = flags;
  88. no_ops++;
  89. }
  90. struct s390_cond_ext_format
  91. {
  92. char nibble;
  93. char extension[4];
  94. };
  95. /* The mnemonic extensions for conditional jumps used to replace
  96. the '*' tag. */
  97. #define NUM_COND_EXTENSIONS 20
  98. const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
  99. { { '1', "o" }, /* jump on overflow / if ones */
  100. { '2', "h" }, /* jump on A high */
  101. { '2', "p" }, /* jump on plus */
  102. { '3', "nle" }, /* jump on not low or equal */
  103. { '4', "l" }, /* jump on A low */
  104. { '4', "m" }, /* jump on minus / if mixed */
  105. { '5', "nhe" }, /* jump on not high or equal */
  106. { '6', "lh" }, /* jump on low or high */
  107. { '7', "ne" }, /* jump on A not equal B */
  108. { '7', "nz" }, /* jump on not zero / if not zeros */
  109. { '8', "e" }, /* jump on A equal B */
  110. { '8', "z" }, /* jump on zero / if zeros */
  111. { '9', "nlh" }, /* jump on not low or high */
  112. { 'a', "he" }, /* jump on high or equal */
  113. { 'b', "nl" }, /* jump on A not low */
  114. { 'b', "nm" }, /* jump on not minus / if not mixed */
  115. { 'c', "le" }, /* jump on low or equal */
  116. { 'd', "nh" }, /* jump on A not high */
  117. { 'd', "np" }, /* jump on not plus */
  118. { 'e', "no" }, /* jump on not overflow / if not ones */
  119. };
  120. /* The mnemonic extensions for conditional branches used to replace
  121. the '$' tag. */
  122. #define NUM_CRB_EXTENSIONS 12
  123. const struct s390_cond_ext_format s390_crb_extensions[NUM_CRB_EXTENSIONS] =
  124. { { '2', "h" }, /* jump on A high */
  125. { '2', "nle" }, /* jump on not low or equal */
  126. { '4', "l" }, /* jump on A low */
  127. { '4', "nhe" }, /* jump on not high or equal */
  128. { '6', "ne" }, /* jump on A not equal B */
  129. { '6', "lh" }, /* jump on low or high */
  130. { '8', "e" }, /* jump on A equal B */
  131. { '8', "nlh" }, /* jump on not low or high */
  132. { 'a', "nl" }, /* jump on A not low */
  133. { 'a', "he" }, /* jump on high or equal */
  134. { 'c', "nh" }, /* jump on A not high */
  135. { 'c', "le" }, /* jump on low or equal */
  136. };
  137. /* As with insertOpcode instructions are added to the sorted opcode
  138. array. Additionally mnemonics containing the '*<number>' tag are
  139. expanded to the set of conditional instructions described by
  140. s390_cond_extensions with the tag replaced by the respective
  141. mnemonic extensions. */
  142. static void
  143. insertExpandedMnemonic (char *opcode, char *mnemonic, char *format,
  144. int min_cpu, int mode_bits, int flags)
  145. {
  146. char *tag;
  147. char prefix[15];
  148. char suffix[15];
  149. char number[15];
  150. int mask_start, i = 0, tag_found = 0, reading_number = 0;
  151. int number_p = 0, suffix_p = 0, prefix_p = 0;
  152. const struct s390_cond_ext_format *ext_table;
  153. int ext_table_length;
  154. if (!(tag = strpbrk (mnemonic, "*$")))
  155. {
  156. insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags);
  157. return;
  158. }
  159. while (mnemonic[i] != '\0')
  160. {
  161. if (mnemonic[i] == *tag)
  162. {
  163. if (tag_found)
  164. goto malformed_mnemonic;
  165. tag_found = 1;
  166. reading_number = 1;
  167. }
  168. else
  169. switch (mnemonic[i])
  170. {
  171. case '0': case '1': case '2': case '3': case '4':
  172. case '5': case '6': case '7': case '8': case '9':
  173. if (!tag_found || !reading_number)
  174. goto malformed_mnemonic;
  175. number[number_p++] = mnemonic[i];
  176. break;
  177. default:
  178. if (reading_number)
  179. {
  180. if (!number_p)
  181. goto malformed_mnemonic;
  182. else
  183. reading_number = 0;
  184. }
  185. if (tag_found)
  186. suffix[suffix_p++] = mnemonic[i];
  187. else
  188. prefix[prefix_p++] = mnemonic[i];
  189. }
  190. i++;
  191. }
  192. prefix[prefix_p] = '\0';
  193. suffix[suffix_p] = '\0';
  194. number[number_p] = '\0';
  195. if (sscanf (number, "%d", &mask_start) != 1)
  196. goto malformed_mnemonic;
  197. if (mask_start & 3)
  198. {
  199. fprintf (stderr, "Conditional mask not at nibble boundary in: %s\n",
  200. mnemonic);
  201. return;
  202. }
  203. mask_start >>= 2;
  204. switch (*tag)
  205. {
  206. case '*':
  207. ext_table = s390_cond_extensions;
  208. ext_table_length = NUM_COND_EXTENSIONS;
  209. break;
  210. case '$':
  211. ext_table = s390_crb_extensions;
  212. ext_table_length = NUM_CRB_EXTENSIONS;
  213. break;
  214. default:
  215. abort (); /* Should be unreachable. */
  216. }
  217. for (i = 0; i < ext_table_length; i++)
  218. {
  219. char new_mnemonic[15];
  220. strcpy (new_mnemonic, prefix);
  221. opcode[mask_start] = ext_table[i].nibble;
  222. strcat (new_mnemonic, ext_table[i].extension);
  223. strcat (new_mnemonic, suffix);
  224. insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags);
  225. }
  226. return;
  227. malformed_mnemonic:
  228. fprintf (stderr, "Malformed mnemonic: %s\n", mnemonic);
  229. }
  230. static const char file_header[] =
  231. "/* The opcode table. This file was generated by s390-mkopc.\n\n"
  232. " The format of the opcode table is:\n\n"
  233. " NAME OPCODE MASK OPERANDS\n\n"
  234. " Name is the name of the instruction.\n"
  235. " OPCODE is the instruction opcode.\n"
  236. " MASK is the opcode mask; this is used to tell the disassembler\n"
  237. " which bits in the actual opcode must match OPCODE.\n"
  238. " OPERANDS is the list of operands.\n\n"
  239. " The disassembler reads the table in order and prints the first\n"
  240. " instruction which matches.\n"
  241. " MODE_BITS - zarch or esa\n"
  242. " MIN_CPU - number of the min cpu level required\n"
  243. " FLAGS - instruction flags. */\n\n"
  244. "const struct s390_opcode s390_opcodes[] =\n {\n";
  245. /* `dumpTable': write opcode table. */
  246. static void
  247. dumpTable (void)
  248. {
  249. char *str;
  250. int ix;
  251. /* Write hash table entries (slots). */
  252. printf ("%s", file_header);
  253. for (ix = 0; ix < no_ops; ix++)
  254. {
  255. printf (" { \"%s\", ", op_array[ix].mnemonic);
  256. for (str = op_array[ix].opcode; *str != 0; str++)
  257. if (*str == '?')
  258. *str = '0';
  259. printf ("OP%i(0x%sLL), ",
  260. op_array[ix].no_nibbles*4, op_array[ix].opcode);
  261. printf ("MASK_%s, INSTR_%s, ",
  262. op_array[ix].format, op_array[ix].format);
  263. printf ("%i, ", op_array[ix].mode_bits);
  264. printf ("%i, ", op_array[ix].min_cpu);
  265. printf ("%i}", op_array[ix].flags);
  266. if (ix < no_ops-1)
  267. printf (",\n");
  268. else
  269. printf ("\n");
  270. }
  271. printf ("};\n\n");
  272. printf ("const int s390_num_opcodes =\n");
  273. printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
  274. }
  275. int
  276. main (void)
  277. {
  278. char currentLine[256];
  279. createTable ();
  280. /* Read opcode descriptions from `stdin'. For each mnemonic,
  281. make an entry into the opcode table. */
  282. while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
  283. {
  284. char opcode[16];
  285. char mnemonic[16];
  286. char format[16];
  287. char description[80];
  288. char cpu_string[16];
  289. char modes_string[16];
  290. char flags_string[80];
  291. int min_cpu;
  292. int mode_bits;
  293. int flag_bits;
  294. int num_matched;
  295. char *str;
  296. if (currentLine[0] == '#' || currentLine[0] == '\n')
  297. continue;
  298. memset (opcode, 0, 8);
  299. num_matched =
  300. sscanf (currentLine, "%15s %15s %15s \"%79[^\"]\" %15s %15s %79[^\n]",
  301. opcode, mnemonic, format, description,
  302. cpu_string, modes_string, flags_string);
  303. if (num_matched != 6 && num_matched != 7)
  304. {
  305. fprintf (stderr, "Couldn't scan line %s\n", currentLine);
  306. exit (1);
  307. }
  308. if (strcmp (cpu_string, "g5") == 0
  309. || strcmp (cpu_string, "arch3") == 0)
  310. min_cpu = S390_OPCODE_G5;
  311. else if (strcmp (cpu_string, "g6") == 0)
  312. min_cpu = S390_OPCODE_G6;
  313. else if (strcmp (cpu_string, "z900") == 0
  314. || strcmp (cpu_string, "arch5") == 0)
  315. min_cpu = S390_OPCODE_Z900;
  316. else if (strcmp (cpu_string, "z990") == 0
  317. || strcmp (cpu_string, "arch6") == 0)
  318. min_cpu = S390_OPCODE_Z990;
  319. else if (strcmp (cpu_string, "z9-109") == 0)
  320. min_cpu = S390_OPCODE_Z9_109;
  321. else if (strcmp (cpu_string, "z9-ec") == 0
  322. || strcmp (cpu_string, "arch7") == 0)
  323. min_cpu = S390_OPCODE_Z9_EC;
  324. else if (strcmp (cpu_string, "z10") == 0
  325. || strcmp (cpu_string, "arch8") == 0)
  326. min_cpu = S390_OPCODE_Z10;
  327. else if (strcmp (cpu_string, "z196") == 0
  328. || strcmp (cpu_string, "arch9") == 0)
  329. min_cpu = S390_OPCODE_Z196;
  330. else if (strcmp (cpu_string, "zEC12") == 0
  331. || strcmp (cpu_string, "arch10") == 0)
  332. min_cpu = S390_OPCODE_ZEC12;
  333. else if (strcmp (cpu_string, "z13") == 0
  334. || strcmp (cpu_string, "arch11") == 0)
  335. min_cpu = S390_OPCODE_Z13;
  336. else if (strcmp (cpu_string, "z14") == 0
  337. || strcmp (cpu_string, "arch12") == 0)
  338. min_cpu = S390_OPCODE_ARCH12;
  339. else if (strcmp (cpu_string, "z15") == 0
  340. || strcmp (cpu_string, "arch13") == 0)
  341. min_cpu = S390_OPCODE_ARCH13;
  342. else if (strcmp (cpu_string, "z16") == 0
  343. || strcmp (cpu_string, "arch14") == 0)
  344. min_cpu = S390_OPCODE_ARCH14;
  345. else {
  346. fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
  347. exit (1);
  348. }
  349. str = modes_string;
  350. mode_bits = 0;
  351. do {
  352. if (strncmp (str, "esa", 3) == 0
  353. && (str[3] == 0 || str[3] == ',')) {
  354. mode_bits |= 1 << S390_OPCODE_ESA;
  355. str += 3;
  356. } else if (strncmp (str, "zarch", 5) == 0
  357. && (str[5] == 0 || str[5] == ',')) {
  358. mode_bits |= 1 << S390_OPCODE_ZARCH;
  359. str += 5;
  360. } else {
  361. fprintf (stderr, "Couldn't parse modes string %s\n",
  362. modes_string);
  363. exit (1);
  364. }
  365. if (*str == ',')
  366. str++;
  367. } while (*str != 0);
  368. flag_bits = 0;
  369. if (num_matched == 7)
  370. {
  371. str = flags_string;
  372. do {
  373. if (strncmp (str, "optparm", 7) == 0
  374. && (str[7] == 0 || str[7] == ',')) {
  375. flag_bits |= S390_INSTR_FLAG_OPTPARM;
  376. str += 7;
  377. } else if (strncmp (str, "optparm2", 8) == 0
  378. && (str[8] == 0 || str[8] == ',')) {
  379. flag_bits |= S390_INSTR_FLAG_OPTPARM2;
  380. str += 8;
  381. } else if (strncmp (str, "htm", 3) == 0
  382. && (str[3] == 0 || str[3] == ',')) {
  383. flag_bits |= S390_INSTR_FLAG_HTM;
  384. str += 3;
  385. } else if (strncmp (str, "vx", 2) == 0
  386. && (str[2] == 0 || str[2] == ',')) {
  387. flag_bits |= S390_INSTR_FLAG_VX;
  388. str += 2;
  389. } else {
  390. fprintf (stderr, "Couldn't parse flags string %s\n",
  391. flags_string);
  392. exit (1);
  393. }
  394. if (*str == ',')
  395. str++;
  396. } while (*str != 0);
  397. }
  398. insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits);
  399. }
  400. dumpTable ();
  401. return 0;
  402. }