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