gdb: add target_ops::supports_displaced_step
[deliverable/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;
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')
952c3f51 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
952c3f51
AK
349 if (strcmp (cpu_string, "g5") == 0
350 || strcmp (cpu_string, "arch3") == 0)
1e2e8c52
AK
351 min_cpu = S390_OPCODE_G5;
352 else if (strcmp (cpu_string, "g6") == 0)
353 min_cpu = S390_OPCODE_G6;
952c3f51
AK
354 else if (strcmp (cpu_string, "z900") == 0
355 || strcmp (cpu_string, "arch5") == 0)
1e2e8c52 356 min_cpu = S390_OPCODE_Z900;
952c3f51
AK
357 else if (strcmp (cpu_string, "z990") == 0
358 || strcmp (cpu_string, "arch6") == 0)
1e2e8c52
AK
359 min_cpu = S390_OPCODE_Z990;
360 else if (strcmp (cpu_string, "z9-109") == 0)
361 min_cpu = S390_OPCODE_Z9_109;
952c3f51
AK
362 else if (strcmp (cpu_string, "z9-ec") == 0
363 || strcmp (cpu_string, "arch7") == 0)
1e2e8c52 364 min_cpu = S390_OPCODE_Z9_EC;
952c3f51
AK
365 else if (strcmp (cpu_string, "z10") == 0
366 || strcmp (cpu_string, "arch8") == 0)
1e2e8c52 367 min_cpu = S390_OPCODE_Z10;
952c3f51
AK
368 else if (strcmp (cpu_string, "z196") == 0
369 || strcmp (cpu_string, "arch9") == 0)
1e2e8c52 370 min_cpu = S390_OPCODE_Z196;
952c3f51
AK
371 else if (strcmp (cpu_string, "zEC12") == 0
372 || strcmp (cpu_string, "arch10") == 0)
1e2e8c52 373 min_cpu = S390_OPCODE_ZEC12;
952c3f51
AK
374 else if (strcmp (cpu_string, "z13") == 0
375 || strcmp (cpu_string, "arch11") == 0)
1e2e8c52 376 min_cpu = S390_OPCODE_Z13;
47826cdb
AK
377 else if (strcmp (cpu_string, "z14") == 0
378 || strcmp (cpu_string, "arch12") == 0)
64025b4e 379 min_cpu = S390_OPCODE_ARCH12;
46e292ab
AK
380 else if (strcmp (cpu_string, "z15") == 0
381 || strcmp (cpu_string, "arch13") == 0)
fc60b8c8 382 min_cpu = S390_OPCODE_ARCH13;
1e2e8c52
AK
383 else {
384 fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
385 exit (1);
386 }
387
388 str = modes_string;
389 mode_bits = 0;
390 do {
391 if (strncmp (str, "esa", 3) == 0
392 && (str[3] == 0 || str[3] == ',')) {
393 mode_bits |= 1 << S390_OPCODE_ESA;
394 str += 3;
395 } else if (strncmp (str, "zarch", 5) == 0
396 && (str[5] == 0 || str[5] == ',')) {
397 mode_bits |= 1 << S390_OPCODE_ZARCH;
398 str += 5;
399 } else {
400 fprintf (stderr, "Couldn't parse modes string %s\n",
401 modes_string);
402 exit (1);
403 }
404 if (*str == ',')
405 str++;
406 } while (*str != 0);
407
408 flag_bits = 0;
409
410 if (num_matched == 7)
411 {
412 str = flags_string;
af169f23 413 do {
1e2e8c52
AK
414 if (strncmp (str, "optparm", 7) == 0
415 && (str[7] == 0 || str[7] == ',')) {
416 flag_bits |= S390_INSTR_FLAG_OPTPARM;
417 str += 7;
a09f2586
AK
418 } else if (strncmp (str, "optparm2", 8) == 0
419 && (str[8] == 0 || str[8] == ',')) {
420 flag_bits |= S390_INSTR_FLAG_OPTPARM2;
421 str += 8;
7ecc513a 422 } else if (strncmp (str, "htm", 3) == 0
a09f2586 423 && (str[3] == 0 || str[3] == ',')) {
7ecc513a
DV
424 flag_bits |= S390_INSTR_FLAG_HTM;
425 str += 3;
426 } else if (strncmp (str, "vx", 2) == 0
a09f2586 427 && (str[2] == 0 || str[2] == ',')) {
7ecc513a
DV
428 flag_bits |= S390_INSTR_FLAG_VX;
429 str += 2;
af169f23 430 } else {
1e2e8c52
AK
431 fprintf (stderr, "Couldn't parse flags string %s\n",
432 flags_string);
af169f23
MS
433 exit (1);
434 }
435 if (*str == ',')
436 str++;
437 } while (*str != 0);
e7390eec 438 }
1e2e8c52 439 insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits);
a85d7ed0
NC
440 }
441
b6849f55
NC
442 dumpTable ();
443 return 0;
a85d7ed0 444}
This page took 0.902567 seconds and 4 git commands to generate.