]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/s390-mkopc.c
aarch64: Add support for Armv8-R DFB alias
[thirdparty/binutils-gdb.git] / opcodes / s390-mkopc.c
CommitLineData
a85d7ed0 1/* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
b3adc24a 2 Copyright (C) 2000-2020 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;
98116973
AA
243 default:
244 abort (); /* Should be unreachable. */
45a5551e
AK
245 }
246
247 for (i = 0; i < ext_table_length; i++)
fcb7aa2f
AK
248 {
249 char new_mnemonic[15];
250
251 strcpy (new_mnemonic, prefix);
45a5551e
AK
252 opcode[mask_start] = ext_table[i].nibble;
253 strcat (new_mnemonic, ext_table[i].extension);
fcb7aa2f 254 strcat (new_mnemonic, suffix);
1e2e8c52 255 insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags);
fcb7aa2f
AK
256 }
257 return;
258
259 malformed_mnemonic:
260 fprintf (stderr, "Malformed mnemonic: %s\n", mnemonic);
261}
262
cdaaa29d 263static const char file_header[] =
b6849f55
NC
264 "/* The opcode table. This file was generated by s390-mkopc.\n\n"
265 " The format of the opcode table is:\n\n"
266 " NAME OPCODE MASK OPERANDS\n\n"
267 " Name is the name of the instruction.\n"
268 " OPCODE is the instruction opcode.\n"
269 " MASK is the opcode mask; this is used to tell the disassembler\n"
270 " which bits in the actual opcode must match OPCODE.\n"
271 " OPERANDS is the list of operands.\n\n"
272 " The disassembler reads the table in order and prints the first\n"
1e2e8c52
AK
273 " instruction which matches.\n"
274 " MODE_BITS - zarch or esa\n"
275 " MIN_CPU - number of the min cpu level required\n"
276 " FLAGS - instruction flags. */\n\n"
b6849f55
NC
277 "const struct s390_opcode s390_opcodes[] =\n {\n";
278
279/* `dumpTable': write opcode table. */
a85d7ed0 280
a85d7ed0 281static void
b6849f55 282dumpTable (void)
a85d7ed0 283{
b6849f55
NC
284 char *str;
285 int ix;
a85d7ed0 286
b6849f55 287 /* Write hash table entries (slots). */
61d4014c 288 printf ("%s", file_header);
b6849f55
NC
289
290 for (ix = 0; ix < no_ops; ix++)
291 {
292 printf (" { \"%s\", ", op_array[ix].mnemonic);
a85d7ed0
NC
293 for (str = op_array[ix].opcode; *str != 0; str++)
294 if (*str == '?')
295 *str = '0';
cdaaa29d 296 printf ("OP%i(0x%sLL), ",
b6849f55
NC
297 op_array[ix].no_nibbles*4, op_array[ix].opcode);
298 printf ("MASK_%s, INSTR_%s, ",
299 op_array[ix].format, op_array[ix].format);
af169f23 300 printf ("%i, ", op_array[ix].mode_bits);
1e2e8c52
AK
301 printf ("%i, ", op_array[ix].min_cpu);
302 printf ("%i}", op_array[ix].flags);
a85d7ed0 303 if (ix < no_ops-1)
b6849f55 304 printf (",\n");
a85d7ed0 305 else
b6849f55 306 printf ("\n");
a85d7ed0 307 }
b6849f55
NC
308 printf ("};\n\n");
309 printf ("const int s390_num_opcodes =\n");
310 printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
a85d7ed0
NC
311}
312
a85d7ed0 313int
b6849f55 314main (void)
a85d7ed0 315{
b6849f55 316 char currentLine[256];
cdaaa29d 317
b6849f55
NC
318 createTable ();
319
320 /* Read opcode descriptions from `stdin'. For each mnemonic,
321 make an entry into the opcode table. */
322 while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
323 {
a85d7ed0
NC
324 char opcode[16];
325 char mnemonic[16];
326 char format[16];
d2ae9c84 327 char description[80];
af169f23
MS
328 char cpu_string[16];
329 char modes_string[16];
1e2e8c52 330 char flags_string[80];
af169f23
MS
331 int min_cpu;
332 int mode_bits;
1e2e8c52
AK
333 int flag_bits;
334 int num_matched;
af169f23 335 char *str;
a85d7ed0 336
aac129d7 337 if (currentLine[0] == '#' || currentLine[0] == '\n')
952c3f51 338 continue;
b6849f55 339 memset (opcode, 0, 8);
1e2e8c52
AK
340 num_matched =
341 sscanf (currentLine, "%15s %15s %15s \"%79[^\"]\" %15s %15s %79[^\n]",
342 opcode, mnemonic, format, description,
343 cpu_string, modes_string, flags_string);
344 if (num_matched != 6 && num_matched != 7)
b6849f55 345 {
1e2e8c52
AK
346 fprintf (stderr, "Couldn't scan line %s\n", currentLine);
347 exit (1);
348 }
af169f23 349
952c3f51
AK
350 if (strcmp (cpu_string, "g5") == 0
351 || strcmp (cpu_string, "arch3") == 0)
1e2e8c52
AK
352 min_cpu = S390_OPCODE_G5;
353 else if (strcmp (cpu_string, "g6") == 0)
354 min_cpu = S390_OPCODE_G6;
952c3f51
AK
355 else if (strcmp (cpu_string, "z900") == 0
356 || strcmp (cpu_string, "arch5") == 0)
1e2e8c52 357 min_cpu = S390_OPCODE_Z900;
952c3f51
AK
358 else if (strcmp (cpu_string, "z990") == 0
359 || strcmp (cpu_string, "arch6") == 0)
1e2e8c52
AK
360 min_cpu = S390_OPCODE_Z990;
361 else if (strcmp (cpu_string, "z9-109") == 0)
362 min_cpu = S390_OPCODE_Z9_109;
952c3f51
AK
363 else if (strcmp (cpu_string, "z9-ec") == 0
364 || strcmp (cpu_string, "arch7") == 0)
1e2e8c52 365 min_cpu = S390_OPCODE_Z9_EC;
952c3f51
AK
366 else if (strcmp (cpu_string, "z10") == 0
367 || strcmp (cpu_string, "arch8") == 0)
1e2e8c52 368 min_cpu = S390_OPCODE_Z10;
952c3f51
AK
369 else if (strcmp (cpu_string, "z196") == 0
370 || strcmp (cpu_string, "arch9") == 0)
1e2e8c52 371 min_cpu = S390_OPCODE_Z196;
952c3f51
AK
372 else if (strcmp (cpu_string, "zEC12") == 0
373 || strcmp (cpu_string, "arch10") == 0)
1e2e8c52 374 min_cpu = S390_OPCODE_ZEC12;
952c3f51
AK
375 else if (strcmp (cpu_string, "z13") == 0
376 || strcmp (cpu_string, "arch11") == 0)
1e2e8c52 377 min_cpu = S390_OPCODE_Z13;
47826cdb
AK
378 else if (strcmp (cpu_string, "z14") == 0
379 || strcmp (cpu_string, "arch12") == 0)
64025b4e 380 min_cpu = S390_OPCODE_ARCH12;
46e292ab
AK
381 else if (strcmp (cpu_string, "z15") == 0
382 || strcmp (cpu_string, "arch13") == 0)
fc60b8c8 383 min_cpu = S390_OPCODE_ARCH13;
1e2e8c52
AK
384 else {
385 fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
386 exit (1);
387 }
388
389 str = modes_string;
390 mode_bits = 0;
391 do {
392 if (strncmp (str, "esa", 3) == 0
393 && (str[3] == 0 || str[3] == ',')) {
394 mode_bits |= 1 << S390_OPCODE_ESA;
395 str += 3;
396 } else if (strncmp (str, "zarch", 5) == 0
397 && (str[5] == 0 || str[5] == ',')) {
398 mode_bits |= 1 << S390_OPCODE_ZARCH;
399 str += 5;
400 } else {
401 fprintf (stderr, "Couldn't parse modes string %s\n",
402 modes_string);
403 exit (1);
404 }
405 if (*str == ',')
406 str++;
407 } while (*str != 0);
408
409 flag_bits = 0;
410
411 if (num_matched == 7)
412 {
413 str = flags_string;
af169f23 414 do {
1e2e8c52
AK
415 if (strncmp (str, "optparm", 7) == 0
416 && (str[7] == 0 || str[7] == ',')) {
417 flag_bits |= S390_INSTR_FLAG_OPTPARM;
418 str += 7;
a09f2586
AK
419 } else if (strncmp (str, "optparm2", 8) == 0
420 && (str[8] == 0 || str[8] == ',')) {
421 flag_bits |= S390_INSTR_FLAG_OPTPARM2;
422 str += 8;
7ecc513a 423 } else if (strncmp (str, "htm", 3) == 0
a09f2586 424 && (str[3] == 0 || str[3] == ',')) {
7ecc513a
DV
425 flag_bits |= S390_INSTR_FLAG_HTM;
426 str += 3;
427 } else if (strncmp (str, "vx", 2) == 0
a09f2586 428 && (str[2] == 0 || str[2] == ',')) {
7ecc513a
DV
429 flag_bits |= S390_INSTR_FLAG_VX;
430 str += 2;
af169f23 431 } else {
1e2e8c52
AK
432 fprintf (stderr, "Couldn't parse flags string %s\n",
433 flags_string);
af169f23
MS
434 exit (1);
435 }
436 if (*str == ',')
437 str++;
438 } while (*str != 0);
e7390eec 439 }
1e2e8c52 440 insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits);
a85d7ed0
NC
441 }
442
b6849f55
NC
443 dumpTable ();
444 return 0;
a85d7ed0 445}