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