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