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