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