PR gold/5996
[deliverable/binutils-gdb.git] / opcodes / s390-mkopc.c
CommitLineData
a85d7ed0 1/* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
9b201bb5 2 Copyright 2000, 2001, 2003, 2007 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
5746fb46
AK
125/* The mnemonic extensions for conditional branches used to replace
126 the '*' tag. */
127#define NUM_COND_EXTENSIONS 12
fcb7aa2f 128const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
5746fb46
AK
129{ { '2', "h" }, /* jump on A high */
130 { '3', "nle" }, /* jump on not low or equal */
131 { '4', "l" }, /* jump on A low */
132 { '5', "nhe" }, /* jump on not high or equal */
133 { '6', "lh" }, /* jump on low or high */
134 { '7', "ne" }, /* jump on A not equal B */
135 { '8', "e" }, /* jump on A equal B */
136 { '9', "nlh" }, /* jump on not low or high */
137 { 'a', "he" }, /* jump on high or equal */
138 { 'b', "nl" }, /* jump on A not low */
139 { 'c', "le" }, /* jump on low or equal */
140 { 'd', "nh" }, /* jump on A not high */
141};
fcb7aa2f
AK
142
143/* As with insertOpcode instructions are added to the sorted opcode
144 array. Additionally mnemonics containing the '*<number>' tag are
145 expanded to the set of conditional instructions described by
5746fb46
AK
146 s390_cond_extensions with the tag replaced by the respective
147 mnemonic extensions. */
fcb7aa2f
AK
148
149static void
5746fb46
AK
150insertExpandedMnemonic (char *opcode, char *mnemonic, char *format,
151 int min_cpu, int mode_bits)
fcb7aa2f 152{
5746fb46 153 char *tag;
fcb7aa2f
AK
154 char prefix[5];
155 char suffix[5];
156 char number[5];
5746fb46 157 int mask_start, i = 0, tag_found = 0, reading_number = 0;
fcb7aa2f
AK
158 int number_p = 0, suffix_p = 0, prefix_p = 0;
159
5746fb46
AK
160 if (!(tag = strchr (mnemonic, '*')))
161 {
162 insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits);
163 return;
164 }
165
fcb7aa2f
AK
166 while (mnemonic[i] != '\0')
167 {
5746fb46 168 if (mnemonic[i] == *tag)
fcb7aa2f 169 {
5746fb46 170 if (tag_found)
fcb7aa2f
AK
171 goto malformed_mnemonic;
172
5746fb46 173 tag_found = 1;
fcb7aa2f 174 reading_number = 1;
fcb7aa2f 175 }
5746fb46
AK
176 else
177 switch (mnemonic[i])
178 {
179 case '0': case '1': case '2': case '3': case '4':
180 case '5': case '6': case '7': case '8': case '9':
181 if (!tag_found || !reading_number)
182 goto malformed_mnemonic;
183
184 number[number_p++] = mnemonic[i];
185 break;
186
187 default:
188 if (reading_number)
189 {
190 if (!number_p)
191 goto malformed_mnemonic;
192 else
193 reading_number = 0;
194 }
195
196 if (tag_found)
197 suffix[suffix_p++] = mnemonic[i];
198 else
199 prefix[prefix_p++] = mnemonic[i];
200 }
fcb7aa2f
AK
201 i++;
202 }
203
204 prefix[prefix_p] = '\0';
205 suffix[suffix_p] = '\0';
206 number[number_p] = '\0';
207
208 if (sscanf (number, "%d", &mask_start) != 1)
209 goto malformed_mnemonic;
210
211 if (mask_start & 3)
212 {
213 fprintf (stderr, "Conditional mask not at nibble boundary in: %s\n",
214 mnemonic);
215 return;
216 }
217
218 mask_start >>= 2;
219
220 for (i = 0; i < NUM_COND_EXTENSIONS; i++)
221 {
222 char new_mnemonic[15];
223
224 strcpy (new_mnemonic, prefix);
5746fb46 225 opcode[mask_start] = s390_cond_extensions[i].nibble;
fcb7aa2f
AK
226 strcat (new_mnemonic, s390_cond_extensions[i].extension);
227 strcat (new_mnemonic, suffix);
fcb7aa2f
AK
228 insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits);
229 }
230 return;
231
232 malformed_mnemonic:
233 fprintf (stderr, "Malformed mnemonic: %s\n", mnemonic);
234}
235
b6849f55
NC
236static char file_header[] =
237 "/* The opcode table. This file was generated by s390-mkopc.\n\n"
238 " The format of the opcode table is:\n\n"
239 " NAME OPCODE MASK OPERANDS\n\n"
240 " Name is the name of the instruction.\n"
241 " OPCODE is the instruction opcode.\n"
242 " MASK is the opcode mask; this is used to tell the disassembler\n"
243 " which bits in the actual opcode must match OPCODE.\n"
244 " OPERANDS is the list of operands.\n\n"
245 " The disassembler reads the table in order and prints the first\n"
246 " instruction which matches. */\n\n"
247 "const struct s390_opcode s390_opcodes[] =\n {\n";
248
249/* `dumpTable': write opcode table. */
a85d7ed0 250
a85d7ed0 251static void
b6849f55 252dumpTable (void)
a85d7ed0 253{
b6849f55
NC
254 char *str;
255 int ix;
a85d7ed0 256
b6849f55
NC
257 /* Write hash table entries (slots). */
258 printf (file_header);
259
260 for (ix = 0; ix < no_ops; ix++)
261 {
262 printf (" { \"%s\", ", op_array[ix].mnemonic);
a85d7ed0
NC
263 for (str = op_array[ix].opcode; *str != 0; str++)
264 if (*str == '?')
265 *str = '0';
b6849f55
NC
266 printf ("OP%i(0x%sLL), ",
267 op_array[ix].no_nibbles*4, op_array[ix].opcode);
268 printf ("MASK_%s, INSTR_%s, ",
269 op_array[ix].format, op_array[ix].format);
af169f23
MS
270 printf ("%i, ", op_array[ix].mode_bits);
271 printf ("%i}", op_array[ix].min_cpu);
a85d7ed0 272 if (ix < no_ops-1)
b6849f55 273 printf (",\n");
a85d7ed0 274 else
b6849f55 275 printf ("\n");
a85d7ed0 276 }
b6849f55
NC
277 printf ("};\n\n");
278 printf ("const int s390_num_opcodes =\n");
279 printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
a85d7ed0
NC
280}
281
a85d7ed0 282int
b6849f55 283main (void)
a85d7ed0 284{
b6849f55
NC
285 char currentLine[256];
286
287 createTable ();
288
289 /* Read opcode descriptions from `stdin'. For each mnemonic,
290 make an entry into the opcode table. */
291 while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
292 {
a85d7ed0
NC
293 char opcode[16];
294 char mnemonic[16];
295 char format[16];
296 char description[64];
af169f23
MS
297 char cpu_string[16];
298 char modes_string[16];
299 int min_cpu;
300 int mode_bits;
301 char *str;
a85d7ed0
NC
302
303 if (currentLine[0] == '#')
304 continue;
b6849f55 305 memset (opcode, 0, 8);
af169f23
MS
306 if (sscanf (currentLine, "%15s %15s %15s \"%[^\"]\" %15s %15s",
307 opcode, mnemonic, format, description,
308 cpu_string, modes_string) == 6)
b6849f55 309 {
af169f23
MS
310 if (strcmp (cpu_string, "g5") == 0)
311 min_cpu = S390_OPCODE_G5;
312 else if (strcmp (cpu_string, "g6") == 0)
313 min_cpu = S390_OPCODE_G6;
314 else if (strcmp (cpu_string, "z900") == 0)
315 min_cpu = S390_OPCODE_Z900;
bac02689
MS
316 else if (strcmp (cpu_string, "z990") == 0)
317 min_cpu = S390_OPCODE_Z990;
ad101263
MS
318 else if (strcmp (cpu_string, "z9-109") == 0)
319 min_cpu = S390_OPCODE_Z9_109;
b5639b37
MS
320 else if (strcmp (cpu_string, "z9-ec") == 0)
321 min_cpu = S390_OPCODE_Z9_EC;
5746fb46
AK
322 else if (strcmp (cpu_string, "z10") == 0)
323 min_cpu = S390_OPCODE_Z10;
af169f23
MS
324 else {
325 fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
326 exit (1);
327 }
328
329 str = modes_string;
330 mode_bits = 0;
331 do {
332 if (strncmp (str, "esa", 3) == 0
333 && (str[3] == 0 || str[3] == ',')) {
334 mode_bits |= 1 << S390_OPCODE_ESA;
335 str += 3;
336 } else if (strncmp (str, "zarch", 5) == 0
337 && (str[5] == 0 || str[5] == ',')) {
338 mode_bits |= 1 << S390_OPCODE_ZARCH;
339 str += 5;
340 } else {
341 fprintf (stderr, "Couldn't parse modes string %s\n",
342 modes_string);
343 exit (1);
344 }
345 if (*str == ',')
346 str++;
347 } while (*str != 0);
fcb7aa2f 348
5746fb46 349 insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits);
b6849f55
NC
350 }
351 else
352 fprintf (stderr, "Couldn't scan line %s\n", currentLine);
a85d7ed0
NC
353 }
354
b6849f55
NC
355 dumpTable ();
356 return 0;
a85d7ed0 357}
This page took 0.35504 seconds and 4 git commands to generate.