s390-mkopc.c revision 1.1.1.10.2.1 1 1.1 christos /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
2 1.1.1.10.2.1 perseant Copyright (C) 2000-2024 Free Software Foundation, Inc.
3 1.1 christos Contributed by Martin Schwidefsky (schwidefsky (at) de.ibm.com).
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this file; see the file COPYING. If not, write to the
19 1.1 christos Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include <stdio.h>
23 1.1 christos #include <stdlib.h>
24 1.1.1.10.2.1 perseant #include <stdarg.h>
25 1.1 christos #include <string.h>
26 1.1.1.5 christos #include "opcode/s390.h"
27 1.1 christos
28 1.1.1.10.2.1 perseant #define STRINGIFY(x) _STRINGIFY(x)
29 1.1.1.10.2.1 perseant #define _STRINGIFY(x) #x
30 1.1.1.10.2.1 perseant
31 1.1.1.10.2.1 perseant /* Length of strings without terminating '\0' character. */
32 1.1.1.10.2.1 perseant #define MAX_OPCODE_LEN 15
33 1.1.1.10.2.1 perseant #define MAX_MNEMONIC_LEN 15
34 1.1.1.10.2.1 perseant #define MAX_FORMAT_LEN 15
35 1.1.1.10.2.1 perseant #define MAX_DESCRIPTION_LEN 127
36 1.1.1.10.2.1 perseant
37 1.1.1.10.2.1 perseant #define MAX_CPU_LEN 15
38 1.1.1.10.2.1 perseant #define MAX_MODES_LEN 15
39 1.1.1.10.2.1 perseant #define MAX_FLAGS_LEN 79
40 1.1.1.10.2.1 perseant
41 1.1.1.10.2.1 perseant /* Return code. */
42 1.1.1.10.2.1 perseant int return_code = EXIT_SUCCESS;
43 1.1.1.10.2.1 perseant
44 1.1.1.10.2.1 perseant /* Helper to print an error message and set the return code. */
45 1.1.1.10.2.1 perseant static void __attribute__ ((format (printf, 1, 2)))
46 1.1.1.10.2.1 perseant print_error (const char *fmt, ...)
47 1.1.1.10.2.1 perseant {
48 1.1.1.10.2.1 perseant va_list ap;
49 1.1.1.10.2.1 perseant
50 1.1.1.10.2.1 perseant va_start(ap, fmt);
51 1.1.1.10.2.1 perseant fprintf(stderr, "Error: ");
52 1.1.1.10.2.1 perseant vfprintf(stderr, fmt, ap);
53 1.1.1.10.2.1 perseant va_end(ap);
54 1.1.1.10.2.1 perseant
55 1.1.1.10.2.1 perseant return_code = EXIT_FAILURE;
56 1.1.1.10.2.1 perseant }
57 1.1.1.10.2.1 perseant
58 1.1 christos struct op_struct
59 1.1 christos {
60 1.1.1.10.2.1 perseant char opcode[MAX_OPCODE_LEN + 1];
61 1.1.1.10.2.1 perseant char mnemonic[MAX_MNEMONIC_LEN + 1];
62 1.1.1.10.2.1 perseant char format[MAX_FORMAT_LEN + 1];
63 1.1 christos int mode_bits;
64 1.1 christos int min_cpu;
65 1.1.1.5 christos int flags;
66 1.1.1.10.2.1 perseant char description[MAX_DESCRIPTION_LEN + 1];
67 1.1.1.2 christos
68 1.1 christos unsigned long long sort_value;
69 1.1 christos int no_nibbles;
70 1.1 christos };
71 1.1 christos
72 1.1 christos struct op_struct *op_array;
73 1.1 christos int max_ops;
74 1.1 christos int no_ops;
75 1.1 christos
76 1.1 christos static void
77 1.1 christos createTable (void)
78 1.1 christos {
79 1.1 christos max_ops = 256;
80 1.1 christos op_array = malloc (max_ops * sizeof (struct op_struct));
81 1.1 christos no_ops = 0;
82 1.1 christos }
83 1.1 christos
84 1.1 christos /* `insertOpcode': insert an op_struct into sorted opcode array. */
85 1.1 christos
86 1.1 christos static void
87 1.1 christos insertOpcode (char *opcode, char *mnemonic, char *format,
88 1.1.1.10.2.1 perseant int min_cpu, int mode_bits, int flags, char* description)
89 1.1 christos {
90 1.1 christos char *str;
91 1.1 christos unsigned long long sort_value;
92 1.1 christos int no_nibbles;
93 1.1 christos int ix, k;
94 1.1 christos
95 1.1 christos while (no_ops >= max_ops)
96 1.1 christos {
97 1.1 christos max_ops = max_ops * 2;
98 1.1 christos op_array = realloc (op_array, max_ops * sizeof (struct op_struct));
99 1.1 christos }
100 1.1 christos
101 1.1 christos sort_value = 0;
102 1.1 christos str = opcode;
103 1.1 christos for (ix = 0; ix < 16; ix++)
104 1.1 christos {
105 1.1 christos if (*str >= '0' && *str <= '9')
106 1.1 christos sort_value = (sort_value << 4) + (*str - '0');
107 1.1 christos else if (*str >= 'a' && *str <= 'f')
108 1.1 christos sort_value = (sort_value << 4) + (*str - 'a' + 10);
109 1.1 christos else if (*str >= 'A' && *str <= 'F')
110 1.1 christos sort_value = (sort_value << 4) + (*str - 'A' + 10);
111 1.1 christos else if (*str == '?')
112 1.1 christos sort_value <<= 4;
113 1.1 christos else
114 1.1 christos break;
115 1.1 christos str ++;
116 1.1 christos }
117 1.1 christos sort_value <<= 4*(16 - ix);
118 1.1 christos sort_value += (min_cpu << 8) + mode_bits;
119 1.1 christos no_nibbles = ix;
120 1.1 christos for (ix = 0; ix < no_ops; ix++)
121 1.1 christos if (sort_value > op_array[ix].sort_value)
122 1.1 christos break;
123 1.1 christos for (k = no_ops; k > ix; k--)
124 1.1 christos op_array[k] = op_array[k-1];
125 1.1.1.10.2.1 perseant strncpy (op_array[ix].opcode, opcode, MAX_OPCODE_LEN);
126 1.1.1.10.2.1 perseant op_array[ix].opcode[MAX_OPCODE_LEN] = '\0';
127 1.1.1.10.2.1 perseant strncpy (op_array[ix].mnemonic, mnemonic, MAX_MNEMONIC_LEN);
128 1.1.1.10.2.1 perseant op_array[ix].mnemonic[MAX_MNEMONIC_LEN] = '\0';
129 1.1.1.10.2.1 perseant strncpy (op_array[ix].format, format, MAX_FORMAT_LEN);
130 1.1.1.10.2.1 perseant op_array[ix].format[MAX_FORMAT_LEN] = '\0';
131 1.1 christos op_array[ix].sort_value = sort_value;
132 1.1 christos op_array[ix].no_nibbles = no_nibbles;
133 1.1 christos op_array[ix].min_cpu = min_cpu;
134 1.1 christos op_array[ix].mode_bits = mode_bits;
135 1.1.1.5 christos op_array[ix].flags = flags;
136 1.1.1.10.2.1 perseant strncpy (op_array[ix].description, description, MAX_DESCRIPTION_LEN);
137 1.1.1.10.2.1 perseant op_array[ix].description[MAX_DESCRIPTION_LEN] = '\0';
138 1.1 christos no_ops++;
139 1.1 christos }
140 1.1 christos
141 1.1 christos struct s390_cond_ext_format
142 1.1 christos {
143 1.1 christos char nibble;
144 1.1 christos char extension[4];
145 1.1.1.10.2.1 perseant char *description_suffix;
146 1.1.1.10.2.1 perseant
147 1.1 christos };
148 1.1 christos
149 1.1 christos /* The mnemonic extensions for conditional jumps used to replace
150 1.1 christos the '*' tag. */
151 1.1 christos #define NUM_COND_EXTENSIONS 20
152 1.1 christos const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
153 1.1.1.10.2.1 perseant { { '1', "o", "on overflow / if ones" }, /* jump on overflow / if ones */
154 1.1.1.10.2.1 perseant { '2', "h", "on A high" }, /* jump on A high */
155 1.1.1.10.2.1 perseant { '2', "p", "on plus" }, /* jump on plus */
156 1.1.1.10.2.1 perseant { '3', "nle", "on not low or equal" }, /* jump on not low or equal */
157 1.1.1.10.2.1 perseant { '4', "l", "on A low" }, /* jump on A low */
158 1.1.1.10.2.1 perseant { '4', "m", "on minus / if mixed" }, /* jump on minus / if mixed */
159 1.1.1.10.2.1 perseant { '5', "nhe", "on not high or equal" }, /* jump on not high or equal */
160 1.1.1.10.2.1 perseant { '6', "lh", "on low or high" }, /* jump on low or high */
161 1.1.1.10.2.1 perseant { '7', "ne", "on A not equal B" }, /* jump on A not equal B */
162 1.1.1.10.2.1 perseant { '7', "nz", "on not zero / if not zeros" }, /* jump on not zero / if not zeros */
163 1.1.1.10.2.1 perseant { '8', "e", "on A equal B" }, /* jump on A equal B */
164 1.1.1.10.2.1 perseant { '8', "z", "on zero / if zeros" }, /* jump on zero / if zeros */
165 1.1.1.10.2.1 perseant { '9', "nlh", "on not low or high" }, /* jump on not low or high */
166 1.1.1.10.2.1 perseant { 'a', "he", "on high or equal" }, /* jump on high or equal */
167 1.1.1.10.2.1 perseant { 'b', "nl", "on A not low" }, /* jump on A not low */
168 1.1.1.10.2.1 perseant { 'b', "nm", "on not minus / if not mixed" }, /* jump on not minus / if not mixed */
169 1.1.1.10.2.1 perseant { 'c', "le", "on low or equal" }, /* jump on low or equal */
170 1.1.1.10.2.1 perseant { 'd', "nh", "on A not high" }, /* jump on A not high */
171 1.1.1.10.2.1 perseant { 'd', "np", "on not plus" }, /* jump on not plus */
172 1.1.1.10.2.1 perseant { 'e', "no", "on not overflow / if not ones" },/* jump on not overflow / if not ones */
173 1.1 christos };
174 1.1 christos
175 1.1 christos /* The mnemonic extensions for conditional branches used to replace
176 1.1 christos the '$' tag. */
177 1.1 christos #define NUM_CRB_EXTENSIONS 12
178 1.1 christos const struct s390_cond_ext_format s390_crb_extensions[NUM_CRB_EXTENSIONS] =
179 1.1.1.10.2.1 perseant { { '2', "h", "on A high" }, /* jump on A high */
180 1.1.1.10.2.1 perseant { '2', "nle", "on not low or equal" }, /* jump on not low or equal */
181 1.1.1.10.2.1 perseant { '4', "l", "on A low" }, /* jump on A low */
182 1.1.1.10.2.1 perseant { '4', "nhe", "on not high or equal" }, /* jump on not high or equal */
183 1.1.1.10.2.1 perseant { '6', "ne", "on A not equal B" }, /* jump on A not equal B */
184 1.1.1.10.2.1 perseant { '6', "lh", "on low or high" }, /* jump on low or high */
185 1.1.1.10.2.1 perseant { '8', "e", "on A equal B" }, /* jump on A equal B */
186 1.1.1.10.2.1 perseant { '8', "nlh", "on not low or high" }, /* jump on not low or high */
187 1.1.1.10.2.1 perseant { 'a', "nl", "on A not low" }, /* jump on A not low */
188 1.1.1.10.2.1 perseant { 'a', "he", "on high or equal" }, /* jump on high or equal */
189 1.1.1.10.2.1 perseant { 'c', "nh", "on A not high" }, /* jump on A not high */
190 1.1.1.10.2.1 perseant { 'c', "le", "on low or equal" }, /* jump on low or equal */
191 1.1 christos };
192 1.1 christos
193 1.1 christos /* As with insertOpcode instructions are added to the sorted opcode
194 1.1 christos array. Additionally mnemonics containing the '*<number>' tag are
195 1.1 christos expanded to the set of conditional instructions described by
196 1.1 christos s390_cond_extensions with the tag replaced by the respective
197 1.1 christos mnemonic extensions. */
198 1.1 christos
199 1.1 christos static void
200 1.1 christos insertExpandedMnemonic (char *opcode, char *mnemonic, char *format,
201 1.1.1.10.2.1 perseant int min_cpu, int mode_bits, int flags, char *description)
202 1.1 christos {
203 1.1 christos char *tag;
204 1.1.1.10.2.1 perseant char prefix[MAX_MNEMONIC_LEN + 1];
205 1.1.1.10.2.1 perseant char suffix[MAX_MNEMONIC_LEN + 1];
206 1.1.1.10.2.1 perseant char number[MAX_MNEMONIC_LEN + 1];
207 1.1 christos int mask_start, i = 0, tag_found = 0, reading_number = 0;
208 1.1 christos int number_p = 0, suffix_p = 0, prefix_p = 0;
209 1.1 christos const struct s390_cond_ext_format *ext_table;
210 1.1 christos int ext_table_length;
211 1.1 christos
212 1.1 christos if (!(tag = strpbrk (mnemonic, "*$")))
213 1.1 christos {
214 1.1.1.10.2.1 perseant insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags, description);
215 1.1 christos return;
216 1.1 christos }
217 1.1 christos
218 1.1 christos while (mnemonic[i] != '\0')
219 1.1 christos {
220 1.1 christos if (mnemonic[i] == *tag)
221 1.1 christos {
222 1.1 christos if (tag_found)
223 1.1 christos goto malformed_mnemonic;
224 1.1 christos
225 1.1 christos tag_found = 1;
226 1.1 christos reading_number = 1;
227 1.1 christos }
228 1.1 christos else
229 1.1 christos switch (mnemonic[i])
230 1.1 christos {
231 1.1 christos case '0': case '1': case '2': case '3': case '4':
232 1.1 christos case '5': case '6': case '7': case '8': case '9':
233 1.1 christos if (!tag_found || !reading_number)
234 1.1 christos goto malformed_mnemonic;
235 1.1 christos
236 1.1 christos number[number_p++] = mnemonic[i];
237 1.1 christos break;
238 1.1 christos
239 1.1 christos default:
240 1.1 christos if (reading_number)
241 1.1 christos {
242 1.1 christos if (!number_p)
243 1.1 christos goto malformed_mnemonic;
244 1.1 christos else
245 1.1 christos reading_number = 0;
246 1.1 christos }
247 1.1 christos
248 1.1 christos if (tag_found)
249 1.1 christos suffix[suffix_p++] = mnemonic[i];
250 1.1 christos else
251 1.1 christos prefix[prefix_p++] = mnemonic[i];
252 1.1 christos }
253 1.1 christos i++;
254 1.1 christos }
255 1.1 christos
256 1.1 christos prefix[prefix_p] = '\0';
257 1.1 christos suffix[suffix_p] = '\0';
258 1.1 christos number[number_p] = '\0';
259 1.1 christos
260 1.1 christos if (sscanf (number, "%d", &mask_start) != 1)
261 1.1 christos goto malformed_mnemonic;
262 1.1 christos
263 1.1 christos if (mask_start & 3)
264 1.1 christos {
265 1.1.1.10.2.1 perseant print_error ("Mnemonic \"%s\": Conditional mask not at nibble boundary\n", mnemonic);
266 1.1 christos return;
267 1.1 christos }
268 1.1 christos
269 1.1 christos mask_start >>= 2;
270 1.1 christos
271 1.1 christos switch (*tag)
272 1.1 christos {
273 1.1 christos case '*':
274 1.1 christos ext_table = s390_cond_extensions;
275 1.1 christos ext_table_length = NUM_COND_EXTENSIONS;
276 1.1 christos break;
277 1.1 christos case '$':
278 1.1 christos ext_table = s390_crb_extensions;
279 1.1 christos ext_table_length = NUM_CRB_EXTENSIONS;
280 1.1 christos break;
281 1.1.1.9 christos default:
282 1.1.1.9 christos abort (); /* Should be unreachable. */
283 1.1 christos }
284 1.1 christos
285 1.1 christos for (i = 0; i < ext_table_length; i++)
286 1.1 christos {
287 1.1.1.10.2.1 perseant char new_mnemonic[MAX_MNEMONIC_LEN + 1];
288 1.1.1.10.2.1 perseant char new_description[MAX_DESCRIPTION_LEN + 1];
289 1.1 christos
290 1.1 christos opcode[mask_start] = ext_table[i].nibble;
291 1.1.1.10.2.1 perseant
292 1.1.1.10.2.1 perseant if (snprintf (new_mnemonic, sizeof (new_mnemonic), "%s%s%s", prefix,
293 1.1.1.10.2.1 perseant ext_table[i].extension, suffix) >= sizeof (new_mnemonic))
294 1.1.1.10.2.1 perseant {
295 1.1.1.10.2.1 perseant print_error ("Mnemonic: \"%s\": Concatenated mnemonic exceeds max. length\n", mnemonic);
296 1.1.1.10.2.1 perseant return;
297 1.1.1.10.2.1 perseant }
298 1.1.1.10.2.1 perseant
299 1.1.1.10.2.1 perseant if (snprintf (new_description, sizeof (new_description), "%s %s", description,
300 1.1.1.10.2.1 perseant ext_table[i].description_suffix) >= sizeof (new_description))
301 1.1.1.10.2.1 perseant {
302 1.1.1.10.2.1 perseant print_error ("Mnemonic \"%s\": Concatenated description exceeds max. length\n", mnemonic);
303 1.1.1.10.2.1 perseant return;
304 1.1.1.10.2.1 perseant }
305 1.1.1.10.2.1 perseant
306 1.1.1.10.2.1 perseant insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags, new_description);
307 1.1 christos }
308 1.1 christos return;
309 1.1 christos
310 1.1 christos malformed_mnemonic:
311 1.1.1.10.2.1 perseant print_error ("Malformed mnemonic: %s\n", mnemonic);
312 1.1 christos }
313 1.1 christos
314 1.1.1.2 christos static const char file_header[] =
315 1.1 christos "/* The opcode table. This file was generated by s390-mkopc.\n\n"
316 1.1 christos " The format of the opcode table is:\n\n"
317 1.1 christos " NAME OPCODE MASK OPERANDS\n\n"
318 1.1 christos " Name is the name of the instruction.\n"
319 1.1 christos " OPCODE is the instruction opcode.\n"
320 1.1 christos " MASK is the opcode mask; this is used to tell the disassembler\n"
321 1.1 christos " which bits in the actual opcode must match OPCODE.\n"
322 1.1 christos " OPERANDS is the list of operands.\n\n"
323 1.1 christos " The disassembler reads the table in order and prints the first\n"
324 1.1.1.5 christos " instruction which matches.\n"
325 1.1.1.5 christos " MODE_BITS - zarch or esa\n"
326 1.1.1.5 christos " MIN_CPU - number of the min cpu level required\n"
327 1.1.1.10.2.1 perseant " FLAGS - instruction flags.\n"
328 1.1.1.10.2.1 perseant " DESCRIPTION - description of the instruction. */\n\n"
329 1.1 christos "const struct s390_opcode s390_opcodes[] =\n {\n";
330 1.1 christos
331 1.1 christos /* `dumpTable': write opcode table. */
332 1.1 christos
333 1.1 christos static void
334 1.1 christos dumpTable (void)
335 1.1 christos {
336 1.1 christos char *str;
337 1.1 christos int ix;
338 1.1 christos
339 1.1 christos /* Write hash table entries (slots). */
340 1.1.1.3 christos printf ("%s", file_header);
341 1.1 christos
342 1.1 christos for (ix = 0; ix < no_ops; ix++)
343 1.1 christos {
344 1.1 christos printf (" { \"%s\", ", op_array[ix].mnemonic);
345 1.1 christos for (str = op_array[ix].opcode; *str != 0; str++)
346 1.1 christos if (*str == '?')
347 1.1 christos *str = '0';
348 1.1.1.2 christos printf ("OP%i(0x%sLL), ",
349 1.1 christos op_array[ix].no_nibbles*4, op_array[ix].opcode);
350 1.1 christos printf ("MASK_%s, INSTR_%s, ",
351 1.1 christos op_array[ix].format, op_array[ix].format);
352 1.1 christos printf ("%i, ", op_array[ix].mode_bits);
353 1.1.1.5 christos printf ("%i, ", op_array[ix].min_cpu);
354 1.1.1.10.2.1 perseant printf ("%i, ", op_array[ix].flags);
355 1.1.1.10.2.1 perseant printf ("\"%s\" }", op_array[ix].description);
356 1.1 christos if (ix < no_ops-1)
357 1.1 christos printf (",\n");
358 1.1 christos else
359 1.1 christos printf ("\n");
360 1.1 christos }
361 1.1 christos printf ("};\n\n");
362 1.1 christos printf ("const int s390_num_opcodes =\n");
363 1.1 christos printf (" sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
364 1.1 christos }
365 1.1 christos
366 1.1 christos int
367 1.1 christos main (void)
368 1.1 christos {
369 1.1 christos char currentLine[256];
370 1.1.1.2 christos
371 1.1 christos createTable ();
372 1.1 christos
373 1.1 christos /* Read opcode descriptions from `stdin'. For each mnemonic,
374 1.1 christos make an entry into the opcode table. */
375 1.1 christos while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
376 1.1 christos {
377 1.1.1.10.2.1 perseant char opcode[MAX_OPCODE_LEN + 1];
378 1.1.1.10.2.1 perseant char mnemonic[MAX_MNEMONIC_LEN + 1];
379 1.1.1.10.2.1 perseant char format[MAX_FORMAT_LEN + 1];
380 1.1.1.10.2.1 perseant char description[MAX_DESCRIPTION_LEN + 1];
381 1.1.1.10.2.1 perseant char cpu_string[MAX_CPU_LEN + 1];
382 1.1.1.10.2.1 perseant char modes_string[MAX_MODES_LEN + 1];
383 1.1.1.10.2.1 perseant char flags_string[MAX_FLAGS_LEN + 1];
384 1.1 christos int min_cpu;
385 1.1 christos int mode_bits;
386 1.1.1.5 christos int flag_bits;
387 1.1.1.5 christos int num_matched;
388 1.1 christos char *str;
389 1.1 christos
390 1.1.1.2 christos if (currentLine[0] == '#' || currentLine[0] == '\n')
391 1.1.1.7 christos continue;
392 1.1.1.10.2.1 perseant memset (opcode, '\0', sizeof(opcode));
393 1.1.1.10.2.1 perseant num_matched = sscanf (currentLine,
394 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_OPCODE_LEN) "s "
395 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_MNEMONIC_LEN) "s "
396 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_FORMAT_LEN) "s "
397 1.1.1.10.2.1 perseant "\"%" STRINGIFY (MAX_DESCRIPTION_LEN) "[^\"]\" "
398 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_CPU_LEN) "s "
399 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_MODES_LEN) "s "
400 1.1.1.10.2.1 perseant "%" STRINGIFY (MAX_FLAGS_LEN) "[^\n]",
401 1.1.1.10.2.1 perseant opcode, mnemonic, format, description,
402 1.1.1.10.2.1 perseant cpu_string, modes_string, flags_string);
403 1.1.1.5 christos if (num_matched != 6 && num_matched != 7)
404 1.1 christos {
405 1.1.1.10.2.1 perseant print_error ("Couldn't scan line %s\n", currentLine);
406 1.1.1.10.2.1 perseant exit (EXIT_FAILURE);
407 1.1.1.5 christos }
408 1.1 christos
409 1.1.1.7 christos if (strcmp (cpu_string, "g5") == 0
410 1.1.1.7 christos || strcmp (cpu_string, "arch3") == 0)
411 1.1.1.5 christos min_cpu = S390_OPCODE_G5;
412 1.1.1.5 christos else if (strcmp (cpu_string, "g6") == 0)
413 1.1.1.5 christos min_cpu = S390_OPCODE_G6;
414 1.1.1.7 christos else if (strcmp (cpu_string, "z900") == 0
415 1.1.1.7 christos || strcmp (cpu_string, "arch5") == 0)
416 1.1.1.5 christos min_cpu = S390_OPCODE_Z900;
417 1.1.1.7 christos else if (strcmp (cpu_string, "z990") == 0
418 1.1.1.7 christos || strcmp (cpu_string, "arch6") == 0)
419 1.1.1.5 christos min_cpu = S390_OPCODE_Z990;
420 1.1.1.5 christos else if (strcmp (cpu_string, "z9-109") == 0)
421 1.1.1.5 christos min_cpu = S390_OPCODE_Z9_109;
422 1.1.1.7 christos else if (strcmp (cpu_string, "z9-ec") == 0
423 1.1.1.7 christos || strcmp (cpu_string, "arch7") == 0)
424 1.1.1.5 christos min_cpu = S390_OPCODE_Z9_EC;
425 1.1.1.7 christos else if (strcmp (cpu_string, "z10") == 0
426 1.1.1.7 christos || strcmp (cpu_string, "arch8") == 0)
427 1.1.1.5 christos min_cpu = S390_OPCODE_Z10;
428 1.1.1.7 christos else if (strcmp (cpu_string, "z196") == 0
429 1.1.1.7 christos || strcmp (cpu_string, "arch9") == 0)
430 1.1.1.5 christos min_cpu = S390_OPCODE_Z196;
431 1.1.1.7 christos else if (strcmp (cpu_string, "zEC12") == 0
432 1.1.1.7 christos || strcmp (cpu_string, "arch10") == 0)
433 1.1.1.5 christos min_cpu = S390_OPCODE_ZEC12;
434 1.1.1.7 christos else if (strcmp (cpu_string, "z13") == 0
435 1.1.1.7 christos || strcmp (cpu_string, "arch11") == 0)
436 1.1.1.5 christos min_cpu = S390_OPCODE_Z13;
437 1.1.1.8 christos else if (strcmp (cpu_string, "z14") == 0
438 1.1.1.8 christos || strcmp (cpu_string, "arch12") == 0)
439 1.1.1.7 christos min_cpu = S390_OPCODE_ARCH12;
440 1.1.1.9 christos else if (strcmp (cpu_string, "z15") == 0
441 1.1.1.9 christos || strcmp (cpu_string, "arch13") == 0)
442 1.1.1.8 christos min_cpu = S390_OPCODE_ARCH13;
443 1.1.1.10 christos else if (strcmp (cpu_string, "z16") == 0
444 1.1.1.10 christos || strcmp (cpu_string, "arch14") == 0)
445 1.1.1.10 christos min_cpu = S390_OPCODE_ARCH14;
446 1.1.1.5 christos else {
447 1.1.1.10.2.1 perseant print_error ("Mnemonic \"%s\": Couldn't parse CPU string: %s\n",
448 1.1.1.10.2.1 perseant mnemonic, cpu_string);
449 1.1.1.10.2.1 perseant goto continue_loop;
450 1.1.1.5 christos }
451 1.1.1.5 christos
452 1.1.1.5 christos str = modes_string;
453 1.1.1.5 christos mode_bits = 0;
454 1.1.1.5 christos do {
455 1.1.1.5 christos if (strncmp (str, "esa", 3) == 0
456 1.1.1.5 christos && (str[3] == 0 || str[3] == ',')) {
457 1.1.1.5 christos mode_bits |= 1 << S390_OPCODE_ESA;
458 1.1.1.5 christos str += 3;
459 1.1.1.5 christos } else if (strncmp (str, "zarch", 5) == 0
460 1.1.1.5 christos && (str[5] == 0 || str[5] == ',')) {
461 1.1.1.5 christos mode_bits |= 1 << S390_OPCODE_ZARCH;
462 1.1.1.5 christos str += 5;
463 1.1.1.5 christos } else {
464 1.1.1.10.2.1 perseant print_error ("Mnemonic \"%s\": Couldn't parse modes string: %s\n",
465 1.1.1.10.2.1 perseant mnemonic, modes_string);
466 1.1.1.10.2.1 perseant goto continue_loop;
467 1.1.1.5 christos }
468 1.1.1.5 christos if (*str == ',')
469 1.1.1.5 christos str++;
470 1.1.1.5 christos } while (*str != 0);
471 1.1.1.5 christos
472 1.1.1.5 christos flag_bits = 0;
473 1.1.1.5 christos
474 1.1.1.5 christos if (num_matched == 7)
475 1.1.1.5 christos {
476 1.1.1.5 christos str = flags_string;
477 1.1 christos do {
478 1.1.1.5 christos if (strncmp (str, "optparm", 7) == 0
479 1.1.1.5 christos && (str[7] == 0 || str[7] == ',')) {
480 1.1.1.5 christos flag_bits |= S390_INSTR_FLAG_OPTPARM;
481 1.1.1.5 christos str += 7;
482 1.1.1.8 christos } else if (strncmp (str, "optparm2", 8) == 0
483 1.1.1.8 christos && (str[8] == 0 || str[8] == ',')) {
484 1.1.1.8 christos flag_bits |= S390_INSTR_FLAG_OPTPARM2;
485 1.1.1.8 christos str += 8;
486 1.1.1.6 christos } else if (strncmp (str, "htm", 3) == 0
487 1.1.1.8 christos && (str[3] == 0 || str[3] == ',')) {
488 1.1.1.6 christos flag_bits |= S390_INSTR_FLAG_HTM;
489 1.1.1.6 christos str += 3;
490 1.1.1.6 christos } else if (strncmp (str, "vx", 2) == 0
491 1.1.1.8 christos && (str[2] == 0 || str[2] == ',')) {
492 1.1.1.6 christos flag_bits |= S390_INSTR_FLAG_VX;
493 1.1.1.6 christos str += 2;
494 1.1.1.10.2.1 perseant } else if (strncmp (str, "jump", 4) == 0
495 1.1.1.10.2.1 perseant && (str[4] == 0 || str[4] == ',')) {
496 1.1.1.10.2.1 perseant flag_bits |= S390_INSTR_FLAGS_CLASS_JUMP;
497 1.1.1.10.2.1 perseant str += 4;
498 1.1.1.10.2.1 perseant } else if (strncmp (str, "condjump", 8) == 0
499 1.1.1.10.2.1 perseant && (str[8] == 0 || str[8] == ',')) {
500 1.1.1.10.2.1 perseant flag_bits |= S390_INSTR_FLAGS_CLASS_CONDJUMP;
501 1.1.1.10.2.1 perseant str += 8;
502 1.1.1.10.2.1 perseant } else if (strncmp (str, "jumpsr", 6) == 0
503 1.1.1.10.2.1 perseant && (str[6] == 0 || str[6] == ',')) {
504 1.1.1.10.2.1 perseant flag_bits |= S390_INSTR_FLAGS_CLASS_JUMPSR;
505 1.1.1.10.2.1 perseant str += 6;
506 1.1 christos } else {
507 1.1.1.10.2.1 perseant print_error ("Mnemonic \"%s\": Couldn't parse flags string: %s\n",
508 1.1.1.10.2.1 perseant mnemonic, flags_string);
509 1.1.1.10.2.1 perseant goto continue_loop;
510 1.1 christos }
511 1.1 christos if (*str == ',')
512 1.1 christos str++;
513 1.1 christos } while (*str != 0);
514 1.1 christos }
515 1.1.1.10.2.1 perseant insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits, description);
516 1.1.1.10.2.1 perseant
517 1.1.1.10.2.1 perseant continue_loop:
518 1.1.1.10.2.1 perseant ;
519 1.1 christos }
520 1.1 christos
521 1.1 christos dumpTable ();
522 1.1.1.10.2.1 perseant return return_code;
523 1.1 christos }
524