gas/testsuite/
[binutils.git] / opcodes / i386-gen.c
blob2931bd33dc2f262f572d442228c1e7bfc63e40fd
1 /* Copyright 2007 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
20 #include "sysdep.h"
21 #include <stdio.h>
22 #include <errno.h>
23 #include "getopt.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
27 #include "i386-opc.h"
29 #include <libintl.h>
30 #define _(String) gettext (String)
32 static const char *program_name = NULL;
33 static int debug = 0;
35 typedef struct initializer
37 const char *name;
38 const char *init;
39 } initializer;
41 static initializer cpu_flag_init [] =
43 { "CPU_UNKNOWN_FLAGS",
44 "unknown" },
45 { "CPU_GENERIC32_FLAGS",
46 "Cpu186|Cpu286|Cpu386" },
47 { "CPU_GENERIC64_FLAGS",
48 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
49 { "CPU_NONE_FLAGS",
50 "0" },
51 { "CPU_I186_FLAGS",
52 "Cpu186" },
53 { "CPU_I286_FLAGS",
54 "Cpu186|Cpu286" },
55 { "CPU_I386_FLAGS",
56 "Cpu186|Cpu286|Cpu386" },
57 { "CPU_I486_FLAGS",
58 "Cpu186|Cpu286|Cpu386|Cpu486" },
59 { "CPU_I586_FLAGS",
60 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
61 { "CPU_I686_FLAGS",
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686" },
63 { "CPU_P2_FLAGS",
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX" },
65 { "CPU_P3_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuMMX2|CpuSSE" },
67 { "CPU_P4_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
69 { "CPU_NOCONA_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
71 { "CPU_CORE_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3" },
73 { "CPU_CORE2_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
75 { "CPU_K6_FLAGS",
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX" },
77 { "CPU_K6_2_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow" },
79 { "CPU_ATHLON_FLAGS",
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA" },
81 { "CPU_K8_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
83 { "CPU_AMDFAM10_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
85 { "CPU_MMX_FLAGS",
86 "CpuMMX" },
87 { "CPU_SSE_FLAGS",
88 "CpuMMX|CpuMMX2|CpuSSE" },
89 { "CPU_SSE2_FLAGS",
90 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2" },
91 { "CPU_SSE3_FLAGS",
92 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3" },
93 { "CPU_SSSE3_FLAGS",
94 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
95 { "CPU_SSE4_1_FLAGS",
96 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_1_Or_5" },
97 { "CPU_SSE4_2_FLAGS",
98 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4_1_Or_5" },
99 { "CPU_3DNOW_FLAGS",
100 "CpuMMX|Cpu3dnow" },
101 { "CPU_3DNOWA_FLAGS",
102 "CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA" },
103 { "CPU_PADLOCK_FLAGS",
104 "CpuPadLock" },
105 { "CPU_SVME_FLAGS",
106 "CpuSVME" },
107 { "CPU_SSE4A_FLAGS",
108 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
109 { "CPU_ABM_FLAGS",
110 "CpuABM" },
111 { "CPU_SSE5_FLAGS",
112 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5|CpuSSE4_1_Or_5"}
115 static initializer operand_type_init [] =
117 { "OPERAND_TYPE_NONE",
118 "0" },
119 { "OPERAND_TYPE_REG8",
120 "Reg8" },
121 { "OPERAND_TYPE_REG16",
122 "Reg16" },
123 { "OPERAND_TYPE_REG32",
124 "Reg32" },
125 { "OPERAND_TYPE_REG64",
126 "Reg64" },
127 { "OPERAND_TYPE_IMM1",
128 "Imm1" },
129 { "OPERAND_TYPE_IMM8",
130 "Imm8" },
131 { "OPERAND_TYPE_IMM8S",
132 "Imm8S" },
133 { "OPERAND_TYPE_IMM16",
134 "Imm16" },
135 { "OPERAND_TYPE_IMM32",
136 "Imm32" },
137 { "OPERAND_TYPE_IMM32S",
138 "Imm32S" },
139 { "OPERAND_TYPE_IMM64",
140 "Imm64" },
141 { "OPERAND_TYPE_BASEINDEX",
142 "BaseIndex" },
143 { "OPERAND_TYPE_DISP8",
144 "Disp8" },
145 { "OPERAND_TYPE_DISP16",
146 "Disp16" },
147 { "OPERAND_TYPE_DISP32",
148 "Disp32" },
149 { "OPERAND_TYPE_DISP32S",
150 "Disp32S" },
151 { "OPERAND_TYPE_DISP64",
152 "Disp64" },
153 { "OPERAND_TYPE_INOUTPORTREG",
154 "InOutPortReg" },
155 { "OPERAND_TYPE_SHIFTCOUNT",
156 "ShiftCount" },
157 { "OPERAND_TYPE_CONTROL",
158 "Control" },
159 { "OPERAND_TYPE_TEST",
160 "Test" },
161 { "OPERAND_TYPE_DEBUG",
162 "FloatReg" },
163 { "OPERAND_TYPE_FLOATREG",
164 "FloatReg" },
165 { "OPERAND_TYPE_FLOATACC",
166 "FloatAcc" },
167 { "OPERAND_TYPE_SREG2",
168 "SReg2" },
169 { "OPERAND_TYPE_SREG3",
170 "SReg3" },
171 { "OPERAND_TYPE_ACC",
172 "Acc" },
173 { "OPERAND_TYPE_JUMPABSOLUTE",
174 "JumpAbsolute" },
175 { "OPERAND_TYPE_REGMMX",
176 "RegMMX" },
177 { "OPERAND_TYPE_REGXMM",
178 "RegXMM" },
179 { "OPERAND_TYPE_ESSEG",
180 "EsSeg" },
181 { "OPERAND_TYPE_ACC32",
182 "Reg32|Acc" },
183 { "OPERAND_TYPE_ACC64",
184 "Reg64|Acc" },
185 { "OPERAND_TYPE_REG16_INOUTPORTREG",
186 "Reg16|InOutPortReg" },
187 { "OPERAND_TYPE_DISP16_32",
188 "Disp16|Disp32" },
189 { "OPERAND_TYPE_ANYDISP",
190 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
191 { "OPERAND_TYPE_IMM16_32",
192 "Imm16|Imm32" },
193 { "OPERAND_TYPE_IMM16_32S",
194 "Imm16|Imm32S" },
195 { "OPERAND_TYPE_IMM16_32_32S",
196 "Imm16|Imm32|Imm32S" },
197 { "OPERAND_TYPE_IMM32_32S_DISP32",
198 "Imm32|Imm32S|Disp32" },
199 { "OPERAND_TYPE_IMM64_DISP64",
200 "Imm64|Disp64" },
201 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
202 "Imm32|Imm32S|Imm64|Disp32" },
203 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
204 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
207 typedef struct bitfield
209 int position;
210 int value;
211 const char *name;
212 } bitfield;
214 #define BITFIELD(n) { n, 0, #n }
216 static bitfield cpu_flags[] =
218 BITFIELD (Cpu186),
219 BITFIELD (Cpu286),
220 BITFIELD (Cpu386),
221 BITFIELD (Cpu486),
222 BITFIELD (Cpu586),
223 BITFIELD (Cpu686),
224 BITFIELD (CpuP4),
225 BITFIELD (CpuK6),
226 BITFIELD (CpuK8),
227 BITFIELD (CpuMMX),
228 BITFIELD (CpuMMX2),
229 BITFIELD (CpuSSE),
230 BITFIELD (CpuSSE2),
231 BITFIELD (CpuSSE3),
232 BITFIELD (CpuSSSE3),
233 BITFIELD (CpuSSE4_1),
234 BITFIELD (CpuSSE4_2),
235 BITFIELD (CpuSSE4a),
236 BITFIELD (CpuSSE5),
237 BITFIELD (CpuSSE4_1_Or_5),
238 BITFIELD (Cpu3dnow),
239 BITFIELD (Cpu3dnowA),
240 BITFIELD (CpuPadLock),
241 BITFIELD (CpuSVME),
242 BITFIELD (CpuVMX),
243 BITFIELD (CpuSMX),
244 BITFIELD (CpuABM),
245 BITFIELD (CpuLM),
246 BITFIELD (Cpu64),
247 BITFIELD (CpuNo64),
248 #ifdef CpuUnused
249 BITFIELD (CpuUnused),
250 #endif
253 static bitfield opcode_modifiers[] =
255 BITFIELD (D),
256 BITFIELD (W),
257 BITFIELD (Modrm),
258 BITFIELD (ShortForm),
259 BITFIELD (Jump),
260 BITFIELD (JumpDword),
261 BITFIELD (JumpByte),
262 BITFIELD (JumpInterSegment),
263 BITFIELD (FloatMF),
264 BITFIELD (FloatR),
265 BITFIELD (FloatD),
266 BITFIELD (Size16),
267 BITFIELD (Size32),
268 BITFIELD (Size64),
269 BITFIELD (IgnoreSize),
270 BITFIELD (DefaultSize),
271 BITFIELD (No_bSuf),
272 BITFIELD (No_wSuf),
273 BITFIELD (No_lSuf),
274 BITFIELD (No_sSuf),
275 BITFIELD (No_qSuf),
276 BITFIELD (No_ldSuf),
277 BITFIELD (FWait),
278 BITFIELD (IsString),
279 BITFIELD (RegKludge),
280 BITFIELD (FirstXmm0),
281 BITFIELD (ByteOkIntel),
282 BITFIELD (ToDword),
283 BITFIELD (ToQword),
284 BITFIELD (AddrPrefixOp0),
285 BITFIELD (IsPrefix),
286 BITFIELD (ImmExt),
287 BITFIELD (NoRex64),
288 BITFIELD (Rex64),
289 BITFIELD (Ugh),
290 BITFIELD (Drex),
291 BITFIELD (Drexv),
292 BITFIELD (Drexc),
293 BITFIELD (OldGcc),
294 BITFIELD (ATTMnemonic),
295 BITFIELD (IntelMnemonic),
298 static bitfield operand_types[] =
300 BITFIELD (Reg8),
301 BITFIELD (Reg16),
302 BITFIELD (Reg32),
303 BITFIELD (Reg64),
304 BITFIELD (FloatReg),
305 BITFIELD (RegMMX),
306 BITFIELD (RegXMM),
307 BITFIELD (Imm8),
308 BITFIELD (Imm8S),
309 BITFIELD (Imm16),
310 BITFIELD (Imm32),
311 BITFIELD (Imm32S),
312 BITFIELD (Imm64),
313 BITFIELD (Imm1),
314 BITFIELD (BaseIndex),
315 BITFIELD (Disp8),
316 BITFIELD (Disp16),
317 BITFIELD (Disp32),
318 BITFIELD (Disp32S),
319 BITFIELD (Disp64),
320 BITFIELD (InOutPortReg),
321 BITFIELD (ShiftCount),
322 BITFIELD (Control),
323 BITFIELD (Debug),
324 BITFIELD (Test),
325 BITFIELD (SReg2),
326 BITFIELD (SReg3),
327 BITFIELD (Acc),
328 BITFIELD (FloatAcc),
329 BITFIELD (JumpAbsolute),
330 BITFIELD (EsSeg),
331 BITFIELD (RegMem),
332 #ifdef OTUnused
333 BITFIELD (OTUnused),
334 #endif
337 static int
338 compare (const void *x, const void *y)
340 const bitfield *xp = (const bitfield *) x;
341 const bitfield *yp = (const bitfield *) y;
342 return xp->position - yp->position;
345 static void
346 fail (const char *message, ...)
348 va_list args;
350 va_start (args, message);
351 fprintf (stderr, _("%s: Error: "), program_name);
352 vfprintf (stderr, message, args);
353 va_end (args);
354 xexit (1);
357 static void
358 process_copyright (FILE *fp)
360 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
361 /* Copyright 2007 Free Software Foundation, Inc.\n\
363 This file is part of the GNU opcodes library.\n\
365 This library is free software; you can redistribute it and/or modify\n\
366 it under the terms of the GNU General Public License as published by\n\
367 the Free Software Foundation; either version 3, or (at your option)\n\
368 any later version.\n\
370 It is distributed in the hope that it will be useful, but WITHOUT\n\
371 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
372 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
373 License for more details.\n\
375 You should have received a copy of the GNU General Public License\n\
376 along with this program; if not, write to the Free Software\n\
377 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
378 MA 02110-1301, USA. */\n");
381 /* Remove leading white spaces. */
383 static char *
384 remove_leading_whitespaces (char *str)
386 while (ISSPACE (*str))
387 str++;
388 return str;
391 /* Remove trailing white spaces. */
393 static void
394 remove_trailing_whitespaces (char *str)
396 size_t last = strlen (str);
398 if (last == 0)
399 return;
403 last--;
404 if (ISSPACE (str [last]))
405 str[last] = '\0';
406 else
407 break;
409 while (last != 0);
412 /* Find next field separated by SEP and terminate it. Return a
413 pointer to the one after it. */
415 static char *
416 next_field (char *str, char sep, char **next)
418 char *p;
420 p = remove_leading_whitespaces (str);
421 for (str = p; *str != sep && *str != '\0'; str++);
423 *str = '\0';
424 remove_trailing_whitespaces (p);
426 *next = str + 1;
428 return p;
431 static void
432 set_bitfield (const char *f, bitfield *array, unsigned int size)
434 unsigned int i;
436 if (strcmp (f, "CpuSledgehammer") == 0)
437 f= "CpuK8";
439 for (i = 0; i < size; i++)
440 if (strcasecmp (array[i].name, f) == 0)
442 array[i].value = 1;
443 return;
446 printf ("Unknown bitfield: %s\n", f);
447 abort ();
450 static void
451 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
452 int macro, const char *comma, const char *indent)
454 unsigned int i;
456 fprintf (table, "%s{ { ", indent);
458 for (i = 0; i < size - 1; i++)
460 fprintf (table, "%d, ", flags[i].value);
461 if (((i + 1) % 20) == 0)
463 /* We need \\ for macro. */
464 if (macro)
465 fprintf (table, " \\\n %s", indent);
466 else
467 fprintf (table, "\n %s", indent);
471 fprintf (table, "%d } }%s\n", flags[i].value, comma);
474 static void
475 process_i386_cpu_flag (FILE *table, char *flag, int macro,
476 const char *comma, const char *indent)
478 char *str, *next, *last;
479 bitfield flags [ARRAY_SIZE (cpu_flags)];
481 /* Copy the default cpu flags. */
482 memcpy (flags, cpu_flags, sizeof (cpu_flags));
484 if (strcasecmp (flag, "unknown") == 0)
486 unsigned int i;
488 /* We turn on everything except for cpu64 in case of
489 CPU_UNKNOWN_FLAGS. */
490 for (i = 0; i < ARRAY_SIZE (flags); i++)
491 if (flags[i].position != Cpu64)
492 flags[i].value = 1;
494 else if (strcmp (flag, "0"))
496 last = flag + strlen (flag);
497 for (next = flag; next && next < last; )
499 str = next_field (next, '|', &next);
500 if (str)
501 set_bitfield (str, flags, ARRAY_SIZE (flags));
505 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
506 comma, indent);
509 static void
510 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
512 unsigned int i;
514 fprintf (table, " { ");
516 for (i = 0; i < size - 1; i++)
518 fprintf (table, "%d, ", modifier[i].value);
519 if (((i + 1) % 20) == 0)
520 fprintf (table, "\n ");
523 fprintf (table, "%d },\n", modifier[i].value);
526 static void
527 process_i386_opcode_modifier (FILE *table, char *mod)
529 char *str, *next, *last;
530 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
532 /* Copy the default opcode modifier. */
533 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
535 if (strcmp (mod, "0"))
537 last = mod + strlen (mod);
538 for (next = mod; next && next < last; )
540 str = next_field (next, '|', &next);
541 if (str)
542 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
545 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
548 static void
549 output_operand_type (FILE *table, bitfield *types, unsigned int size,
550 int macro, const char *indent)
552 unsigned int i;
554 fprintf (table, "{ { ");
556 for (i = 0; i < size - 1; i++)
558 fprintf (table, "%d, ", types[i].value);
559 if (((i + 1) % 20) == 0)
561 /* We need \\ for macro. */
562 if (macro)
563 fprintf (table, "\\\n%s", indent);
564 else
565 fprintf (table, "\n%s", indent);
569 fprintf (table, "%d } }", types[i].value);
572 static void
573 process_i386_operand_type (FILE *table, char *op, int macro,
574 const char *indent)
576 char *str, *next, *last;
577 bitfield types [ARRAY_SIZE (operand_types)];
579 /* Copy the default operand type. */
580 memcpy (types, operand_types, sizeof (types));
582 if (strcmp (op, "0"))
584 last = op + strlen (op);
585 for (next = op; next && next < last; )
587 str = next_field (next, '|', &next);
588 if (str)
589 set_bitfield (str, types, ARRAY_SIZE (types));
592 output_operand_type (table, types, ARRAY_SIZE (types), macro,
593 indent);
596 static void
597 process_i386_opcodes (FILE *table)
599 FILE *fp = fopen ("i386-opc.tbl", "r");
600 char buf[2048];
601 unsigned int i;
602 char *str, *p, *last;
603 char *name, *operands, *base_opcode, *extension_opcode;
604 char *opcode_length;
605 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
607 if (fp == NULL)
608 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
609 xstrerror (errno));
611 fprintf (table, "\n/* i386 opcode table. */\n\n");
612 fprintf (table, "const template i386_optab[] =\n{\n");
614 while (!feof (fp))
616 if (fgets (buf, sizeof (buf), fp) == NULL)
617 break;
619 p = remove_leading_whitespaces (buf);
621 /* Skip comments. */
622 str = strstr (p, "//");
623 if (str != NULL)
624 str[0] = '\0';
626 /* Remove trailing white spaces. */
627 remove_trailing_whitespaces (p);
629 switch (p[0])
631 case '#':
632 fprintf (table, "%s\n", p);
633 case '\0':
634 continue;
635 break;
636 default:
637 break;
640 last = p + strlen (p);
642 /* Find name. */
643 name = next_field (p, ',', &str);
645 if (str >= last)
646 abort ();
648 /* Find number of operands. */
649 operands = next_field (str, ',', &str);
651 if (str >= last)
652 abort ();
654 /* Find base_opcode. */
655 base_opcode = next_field (str, ',', &str);
657 if (str >= last)
658 abort ();
660 /* Find extension_opcode. */
661 extension_opcode = next_field (str, ',', &str);
663 if (str >= last)
664 abort ();
666 /* Find opcode_length. */
667 opcode_length = next_field (str, ',', &str);
669 if (str >= last)
670 abort ();
672 /* Find cpu_flags. */
673 cpu_flags = next_field (str, ',', &str);
675 if (str >= last)
676 abort ();
678 /* Find opcode_modifier. */
679 opcode_modifier = next_field (str, ',', &str);
681 if (str >= last)
682 abort ();
684 /* Remove the first {. */
685 str = remove_leading_whitespaces (str);
686 if (*str != '{')
687 abort ();
688 str = remove_leading_whitespaces (str + 1);
690 i = strlen (str);
692 /* There are at least "X}". */
693 if (i < 2)
694 abort ();
696 /* Remove trailing white spaces and }. */
699 i--;
700 if (ISSPACE (str[i]) || str[i] == '}')
701 str[i] = '\0';
702 else
703 break;
705 while (i != 0);
707 last = str + i;
709 /* Find operand_types. */
710 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
712 if (str >= last)
714 operand_types [i] = NULL;
715 break;
718 operand_types [i] = next_field (str, ',', &str);
719 if (*operand_types[i] == '0')
721 if (i != 0)
722 operand_types[i] = NULL;
723 break;
727 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
728 name, operands, base_opcode, extension_opcode,
729 opcode_length);
731 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
733 process_i386_opcode_modifier (table, opcode_modifier);
735 fprintf (table, " { ");
737 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
739 if (operand_types[i] == NULL
740 || *operand_types[i] == '0')
742 if (i == 0)
743 process_i386_operand_type (table, "0", 0, "\t ");
744 break;
747 if (i != 0)
748 fprintf (table, ",\n ");
750 process_i386_operand_type (table, operand_types[i], 0,
751 "\t ");
753 fprintf (table, " } },\n");
756 fclose (fp);
758 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
760 process_i386_cpu_flag (table, "0", 0, ",", " ");
762 process_i386_opcode_modifier (table, "0");
764 fprintf (table, " { ");
765 process_i386_operand_type (table, "0", 0, "\t ");
766 fprintf (table, " } }\n");
768 fprintf (table, "};\n");
771 static void
772 process_i386_registers (FILE *table)
774 FILE *fp = fopen ("i386-reg.tbl", "r");
775 char buf[2048];
776 char *str, *p, *last;
777 char *reg_name, *reg_type, *reg_flags, *reg_num;
779 if (fp == NULL)
780 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
781 xstrerror (errno));
783 fprintf (table, "\n/* i386 register table. */\n\n");
784 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
786 while (!feof (fp))
788 if (fgets (buf, sizeof (buf), fp) == NULL)
789 break;
791 p = remove_leading_whitespaces (buf);
793 /* Skip comments. */
794 str = strstr (p, "//");
795 if (str != NULL)
796 str[0] = '\0';
798 /* Remove trailing white spaces. */
799 remove_trailing_whitespaces (p);
801 switch (p[0])
803 case '#':
804 fprintf (table, "%s\n", p);
805 case '\0':
806 continue;
807 break;
808 default:
809 break;
812 last = p + strlen (p);
814 /* Find reg_name. */
815 reg_name = next_field (p, ',', &str);
817 if (str >= last)
818 abort ();
820 /* Find reg_type. */
821 reg_type = next_field (str, ',', &str);
823 if (str >= last)
824 abort ();
826 /* Find reg_flags. */
827 reg_flags = next_field (str, ',', &str);
829 if (str >= last)
830 abort ();
832 /* Find reg_num. */
833 reg_num = next_field (str, ',', &str);
835 fprintf (table, " { \"%s\",\n ", reg_name);
837 process_i386_operand_type (table, reg_type, 0, "\t");
839 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
842 fclose (fp);
844 fprintf (table, "};\n");
846 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
849 static void
850 process_i386_initializers (void)
852 unsigned int i;
853 FILE *fp = fopen ("i386-init.h", "w");
854 char *init;
856 if (fp == NULL)
857 fail (_("can't create i386-init.h, errno = %s\n"),
858 xstrerror (errno));
860 process_copyright (fp);
862 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
864 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
865 init = xstrdup (cpu_flag_init[i].init);
866 process_i386_cpu_flag (fp, init, 1, "", " ");
867 free (init);
870 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
872 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
873 init = xstrdup (operand_type_init[i].init);
874 process_i386_operand_type (fp, init, 1, " ");
875 free (init);
877 fprintf (fp, "\n");
879 fclose (fp);
882 /* Program options. */
883 #define OPTION_SRCDIR 200
885 struct option long_options[] =
887 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
888 {"debug", no_argument, NULL, 'd'},
889 {"version", no_argument, NULL, 'V'},
890 {"help", no_argument, NULL, 'h'},
891 {0, no_argument, NULL, 0}
894 static void
895 print_version (void)
897 printf ("%s: version 1.0\n", program_name);
898 xexit (0);
901 static void
902 usage (FILE * stream, int status)
904 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
905 program_name);
906 xexit (status);
910 main (int argc, char **argv)
912 extern int chdir (char *);
913 char *srcdir = NULL;
914 int c;
915 FILE *table;
917 program_name = *argv;
918 xmalloc_set_program_name (program_name);
920 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
921 switch (c)
923 case OPTION_SRCDIR:
924 srcdir = optarg;
925 break;
926 case 'V':
927 case 'v':
928 print_version ();
929 break;
930 case 'd':
931 debug = 1;
932 break;
933 case 'h':
934 case '?':
935 usage (stderr, 0);
936 default:
937 case 0:
938 break;
941 if (optind != argc)
942 usage (stdout, 1);
944 if (srcdir != NULL)
945 if (chdir (srcdir) != 0)
946 fail (_("unable to change directory to \"%s\", errno = %s\n"),
947 srcdir, xstrerror (errno));
949 /* Check the unused bitfield in i386_cpu_flags. */
950 #ifndef CpuUnused
951 c = CpuNumOfBits - CpuMax - 1;
952 if (c)
953 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
954 #endif
956 /* Check the unused bitfield in i386_operand_type. */
957 #ifndef OTUnused
958 c = OTNumOfBits - OTMax - 1;
959 if (c)
960 fail (_("%d unused bits in i386_operand_type.\n"), c);
961 #endif
963 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
964 compare);
966 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
967 sizeof (opcode_modifiers [0]), compare);
969 qsort (operand_types, ARRAY_SIZE (operand_types),
970 sizeof (operand_types [0]), compare);
972 table = fopen ("i386-tbl.h", "w");
973 if (table == NULL)
974 fail (_("can't create i386-tbl.h, errno = %s\n"),
975 xstrerror (errno));
977 process_copyright (table);
979 process_i386_opcodes (table);
980 process_i386_registers (table);
981 process_i386_initializers ();
983 fclose (table);
985 exit (0);