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