opcodes/
[binutils.git] / opcodes / i386-gen.c
bloba2afa3d1eca5f5671e44f4222bb6618685256987
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" },
97 { "CPU_SSE4_2_FLAGS",
98 "CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
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"}
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 (Cpu3dnow),
238 BITFIELD (Cpu3dnowA),
239 BITFIELD (CpuPadLock),
240 BITFIELD (CpuSVME),
241 BITFIELD (CpuVMX),
242 BITFIELD (CpuSMX),
243 BITFIELD (CpuABM),
244 BITFIELD (CpuLM),
245 BITFIELD (Cpu64),
246 BITFIELD (CpuNo64),
247 #ifdef CpuUnused
248 BITFIELD (CpuUnused),
249 #endif
252 static bitfield opcode_modifiers[] =
254 BITFIELD (D),
255 BITFIELD (W),
256 BITFIELD (Modrm),
257 BITFIELD (ShortForm),
258 BITFIELD (Jump),
259 BITFIELD (JumpDword),
260 BITFIELD (JumpByte),
261 BITFIELD (JumpInterSegment),
262 BITFIELD (FloatMF),
263 BITFIELD (FloatR),
264 BITFIELD (FloatD),
265 BITFIELD (Size16),
266 BITFIELD (Size32),
267 BITFIELD (Size64),
268 BITFIELD (IgnoreSize),
269 BITFIELD (DefaultSize),
270 BITFIELD (No_bSuf),
271 BITFIELD (No_wSuf),
272 BITFIELD (No_lSuf),
273 BITFIELD (No_sSuf),
274 BITFIELD (No_qSuf),
275 BITFIELD (No_xSuf),
276 BITFIELD (FWait),
277 BITFIELD (IsString),
278 BITFIELD (RegKludge),
279 BITFIELD (FirstXmm0),
280 BITFIELD (IsPrefix),
281 BITFIELD (ImmExt),
282 BITFIELD (NoRex64),
283 BITFIELD (Rex64),
284 BITFIELD (Ugh),
285 BITFIELD (Drex),
286 BITFIELD (Drexv),
287 BITFIELD (Drexc),
290 static bitfield operand_types[] =
292 BITFIELD (Reg8),
293 BITFIELD (Reg16),
294 BITFIELD (Reg32),
295 BITFIELD (Reg64),
296 BITFIELD (FloatReg),
297 BITFIELD (RegMMX),
298 BITFIELD (RegXMM),
299 BITFIELD (Imm8),
300 BITFIELD (Imm8S),
301 BITFIELD (Imm16),
302 BITFIELD (Imm32),
303 BITFIELD (Imm32S),
304 BITFIELD (Imm64),
305 BITFIELD (Imm1),
306 BITFIELD (BaseIndex),
307 BITFIELD (Disp8),
308 BITFIELD (Disp16),
309 BITFIELD (Disp32),
310 BITFIELD (Disp32S),
311 BITFIELD (Disp64),
312 BITFIELD (InOutPortReg),
313 BITFIELD (ShiftCount),
314 BITFIELD (Control),
315 BITFIELD (Debug),
316 BITFIELD (Test),
317 BITFIELD (SReg2),
318 BITFIELD (SReg3),
319 BITFIELD (Acc),
320 BITFIELD (FloatAcc),
321 BITFIELD (JumpAbsolute),
322 BITFIELD (EsSeg),
323 BITFIELD (RegMem),
324 #ifdef OTUnused
325 BITFIELD (OTUnused),
326 #endif
329 static int
330 compare (const void *x, const void *y)
332 const bitfield *xp = (const bitfield *) x;
333 const bitfield *yp = (const bitfield *) y;
334 return xp->position - yp->position;
337 static void
338 fail (const char *message, ...)
340 va_list args;
342 va_start (args, message);
343 fprintf (stderr, _("%s: Error: "), program_name);
344 vfprintf (stderr, message, args);
345 va_end (args);
346 xexit (1);
349 static void
350 process_copyright (FILE *fp)
352 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
353 /* Copyright 2007 Free Software Foundation, Inc.\n\
355 This file is part of the GNU opcodes library.\n\
357 This library is free software; you can redistribute it and/or modify\n\
358 it under the terms of the GNU General Public License as published by\n\
359 the Free Software Foundation; either version 3, or (at your option)\n\
360 any later version.\n\
362 It is distributed in the hope that it will be useful, but WITHOUT\n\
363 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
364 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
365 License for more details.\n\
367 You should have received a copy of the GNU General Public License\n\
368 along with this program; if not, write to the Free Software\n\
369 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
370 MA 02110-1301, USA. */\n");
373 /* Remove leading white spaces. */
375 static char *
376 remove_leading_whitespaces (char *str)
378 while (ISSPACE (*str))
379 str++;
380 return str;
383 /* Remove trailing white spaces. */
385 static void
386 remove_trailing_whitespaces (char *str)
388 size_t last = strlen (str);
390 if (last == 0)
391 return;
395 last--;
396 if (ISSPACE (str [last]))
397 str[last] = '\0';
398 else
399 break;
401 while (last != 0);
404 /* Find next field separated by SEP and terminate it. Return a
405 pointer to the one after it. */
407 static char *
408 next_field (char *str, char sep, char **next)
410 char *p;
412 p = remove_leading_whitespaces (str);
413 for (str = p; *str != sep && *str != '\0'; str++);
415 *str = '\0';
416 remove_trailing_whitespaces (p);
418 *next = str + 1;
420 return p;
423 static void
424 set_bitfield (const char *f, bitfield *array, unsigned int size)
426 unsigned int i;
428 if (strcmp (f, "CpuSledgehammer") == 0)
429 f= "CpuK8";
431 for (i = 0; i < size; i++)
432 if (strcasecmp (array[i].name, f) == 0)
434 array[i].value = 1;
435 return;
438 printf ("Unknown bitfield: %s\n", f);
439 abort ();
442 static void
443 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
444 int macro, const char *comma, const char *indent)
446 unsigned int i;
448 fprintf (table, "%s{ { ", indent);
450 for (i = 0; i < size - 1; i++)
452 fprintf (table, "%d, ", flags[i].value);
453 if (((i + 1) % 20) == 0)
455 /* We need \\ for macro. */
456 if (macro)
457 fprintf (table, " \\\n %s", indent);
458 else
459 fprintf (table, "\n %s", indent);
463 fprintf (table, "%d } }%s\n", flags[i].value, comma);
466 static void
467 process_i386_cpu_flag (FILE *table, char *flag, int macro,
468 const char *comma, const char *indent)
470 char *str, *next, *last;
471 bitfield flags [ARRAY_SIZE (cpu_flags)];
473 /* Copy the default cpu flags. */
474 memcpy (flags, cpu_flags, sizeof (cpu_flags));
476 if (strcasecmp (flag, "unknown") == 0)
478 unsigned int i;
480 /* We turn on everything except for cpu64 in case of
481 CPU_UNKNOWN_FLAGS. */
482 for (i = 0; i < ARRAY_SIZE (flags); i++)
483 if (flags[i].position != Cpu64)
484 flags[i].value = 1;
486 else if (strcmp (flag, "0"))
488 last = flag + strlen (flag);
489 for (next = flag; next && next < last; )
491 str = next_field (next, '|', &next);
492 if (str)
493 set_bitfield (str, flags, ARRAY_SIZE (flags));
497 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
498 comma, indent);
501 static void
502 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
504 unsigned int i;
506 fprintf (table, " { ");
508 for (i = 0; i < size - 1; i++)
510 fprintf (table, "%d, ", modifier[i].value);
511 if (((i + 1) % 20) == 0)
512 fprintf (table, "\n ");
515 fprintf (table, "%d },\n", modifier[i].value);
518 static void
519 process_i386_opcode_modifier (FILE *table, char *mod)
521 char *str, *next, *last;
522 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
524 /* Copy the default opcode modifier. */
525 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
527 if (strcmp (mod, "0"))
529 last = mod + strlen (mod);
530 for (next = mod; next && next < last; )
532 str = next_field (next, '|', &next);
533 if (str)
534 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
537 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
540 static void
541 output_operand_type (FILE *table, bitfield *types, unsigned int size,
542 int macro, const char *indent)
544 unsigned int i;
546 fprintf (table, "{ { ");
548 for (i = 0; i < size - 1; i++)
550 fprintf (table, "%d, ", types[i].value);
551 if (((i + 1) % 20) == 0)
553 /* We need \\ for macro. */
554 if (macro)
555 fprintf (table, "\\\n%s", indent);
556 else
557 fprintf (table, "\n%s", indent);
561 fprintf (table, "%d } }", types[i].value);
564 static void
565 process_i386_operand_type (FILE *table, char *op, int macro,
566 const char *indent)
568 char *str, *next, *last;
569 bitfield types [ARRAY_SIZE (operand_types)];
571 /* Copy the default operand type. */
572 memcpy (types, operand_types, sizeof (types));
574 if (strcmp (op, "0"))
576 last = op + strlen (op);
577 for (next = op; next && next < last; )
579 str = next_field (next, '|', &next);
580 if (str)
581 set_bitfield (str, types, ARRAY_SIZE (types));
584 output_operand_type (table, types, ARRAY_SIZE (types), macro,
585 indent);
588 static void
589 process_i386_opcodes (FILE *table)
591 FILE *fp = fopen ("i386-opc.tbl", "r");
592 char buf[2048];
593 unsigned int i;
594 char *str, *p, *last;
595 char *name, *operands, *base_opcode, *extension_opcode;
596 char *opcode_length;
597 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
599 if (fp == NULL)
600 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
601 xstrerror (errno));
603 fprintf (table, "\n/* i386 opcode table. */\n\n");
604 fprintf (table, "const template i386_optab[] =\n{\n");
606 while (!feof (fp))
608 if (fgets (buf, sizeof (buf), fp) == NULL)
609 break;
611 p = remove_leading_whitespaces (buf);
613 /* Skip comments. */
614 str = strstr (p, "//");
615 if (str != NULL)
616 str[0] = '\0';
618 /* Remove trailing white spaces. */
619 remove_trailing_whitespaces (p);
621 switch (p[0])
623 case '#':
624 fprintf (table, "%s\n", p);
625 case '\0':
626 continue;
627 break;
628 default:
629 break;
632 last = p + strlen (p);
634 /* Find name. */
635 name = next_field (p, ',', &str);
637 if (str >= last)
638 abort ();
640 /* Find number of operands. */
641 operands = next_field (str, ',', &str);
643 if (str >= last)
644 abort ();
646 /* Find base_opcode. */
647 base_opcode = next_field (str, ',', &str);
649 if (str >= last)
650 abort ();
652 /* Find extension_opcode. */
653 extension_opcode = next_field (str, ',', &str);
655 if (str >= last)
656 abort ();
658 /* Find opcode_length. */
659 opcode_length = next_field (str, ',', &str);
661 if (str >= last)
662 abort ();
664 /* Find cpu_flags. */
665 cpu_flags = next_field (str, ',', &str);
667 if (str >= last)
668 abort ();
670 /* Find opcode_modifier. */
671 opcode_modifier = next_field (str, ',', &str);
673 if (str >= last)
674 abort ();
676 /* Remove the first {. */
677 str = remove_leading_whitespaces (str);
678 if (*str != '{')
679 abort ();
680 str = remove_leading_whitespaces (str + 1);
682 i = strlen (str);
684 /* There are at least "X}". */
685 if (i < 2)
686 abort ();
688 /* Remove trailing white spaces and }. */
691 i--;
692 if (ISSPACE (str[i]) || str[i] == '}')
693 str[i] = '\0';
694 else
695 break;
697 while (i != 0);
699 last = str + i;
701 /* Find operand_types. */
702 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
704 if (str >= last)
706 operand_types [i] = NULL;
707 break;
710 operand_types [i] = next_field (str, ',', &str);
711 if (*operand_types[i] == '0')
713 if (i != 0)
714 operand_types[i] = NULL;
715 break;
719 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
720 name, operands, base_opcode, extension_opcode,
721 opcode_length);
723 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
725 process_i386_opcode_modifier (table, opcode_modifier);
727 fprintf (table, " { ");
729 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
731 if (operand_types[i] == NULL
732 || *operand_types[i] == '0')
734 if (i == 0)
735 process_i386_operand_type (table, "0", 0, "\t ");
736 break;
739 if (i != 0)
740 fprintf (table, ",\n ");
742 process_i386_operand_type (table, operand_types[i], 0,
743 "\t ");
745 fprintf (table, " } },\n");
748 fclose (fp);
750 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
752 process_i386_cpu_flag (table, "0", 0, ",", " ");
754 process_i386_opcode_modifier (table, "0");
756 fprintf (table, " { ");
757 process_i386_operand_type (table, "0", 0, "\t ");
758 fprintf (table, " } }\n");
760 fprintf (table, "};\n");
763 static void
764 process_i386_registers (FILE *table)
766 FILE *fp = fopen ("i386-reg.tbl", "r");
767 char buf[2048];
768 char *str, *p, *last;
769 char *reg_name, *reg_type, *reg_flags, *reg_num;
771 if (fp == NULL)
772 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
773 xstrerror (errno));
775 fprintf (table, "\n/* i386 register table. */\n\n");
776 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
778 while (!feof (fp))
780 if (fgets (buf, sizeof (buf), fp) == NULL)
781 break;
783 p = remove_leading_whitespaces (buf);
785 /* Skip comments. */
786 str = strstr (p, "//");
787 if (str != NULL)
788 str[0] = '\0';
790 /* Remove trailing white spaces. */
791 remove_trailing_whitespaces (p);
793 switch (p[0])
795 case '#':
796 fprintf (table, "%s\n", p);
797 case '\0':
798 continue;
799 break;
800 default:
801 break;
804 last = p + strlen (p);
806 /* Find reg_name. */
807 reg_name = next_field (p, ',', &str);
809 if (str >= last)
810 abort ();
812 /* Find reg_type. */
813 reg_type = next_field (str, ',', &str);
815 if (str >= last)
816 abort ();
818 /* Find reg_flags. */
819 reg_flags = next_field (str, ',', &str);
821 if (str >= last)
822 abort ();
824 /* Find reg_num. */
825 reg_num = next_field (str, ',', &str);
827 fprintf (table, " { \"%s\",\n ", reg_name);
829 process_i386_operand_type (table, reg_type, 0, "\t");
831 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
834 fclose (fp);
836 fprintf (table, "};\n");
838 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
841 static void
842 process_i386_initializers (void)
844 unsigned int i;
845 FILE *fp = fopen ("i386-init.h", "w");
846 char *init;
848 if (fp == NULL)
849 fail (_("can't create i386-init.h, errno = %s\n"),
850 xstrerror (errno));
852 process_copyright (fp);
854 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
856 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
857 init = xstrdup (cpu_flag_init[i].init);
858 process_i386_cpu_flag (fp, init, 1, "", " ");
859 free (init);
862 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
864 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
865 init = xstrdup (operand_type_init[i].init);
866 process_i386_operand_type (fp, init, 1, " ");
867 free (init);
869 fprintf (fp, "\n");
871 fclose (fp);
874 /* Program options. */
875 #define OPTION_SRCDIR 200
877 struct option long_options[] =
879 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
880 {"debug", no_argument, NULL, 'd'},
881 {"version", no_argument, NULL, 'V'},
882 {"help", no_argument, NULL, 'h'},
883 {0, no_argument, NULL, 0}
886 static void
887 print_version (void)
889 printf ("%s: version 1.0\n", program_name);
890 xexit (0);
893 static void
894 usage (FILE * stream, int status)
896 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
897 program_name);
898 xexit (status);
902 main (int argc, char **argv)
904 extern int chdir (char *);
905 char *srcdir = NULL;
906 int c;
907 FILE *table;
909 program_name = *argv;
910 xmalloc_set_program_name (program_name);
912 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
913 switch (c)
915 case OPTION_SRCDIR:
916 srcdir = optarg;
917 break;
918 case 'V':
919 case 'v':
920 print_version ();
921 break;
922 case 'd':
923 debug = 1;
924 break;
925 case 'h':
926 case '?':
927 usage (stderr, 0);
928 default:
929 case 0:
930 break;
933 if (optind != argc)
934 usage (stdout, 1);
936 if (srcdir != NULL)
937 if (chdir (srcdir) != 0)
938 fail (_("unable to change directory to \"%s\", errno = %s\n"),
939 srcdir, xstrerror (errno));
941 /* Check the unused bitfield in i386_cpu_flags. */
942 #ifndef CpuUnused
943 c = CpuNumOfBits - CpuMax - 1;
944 if (c)
945 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
946 #endif
948 /* Check the unused bitfield in i386_operand_type. */
949 #ifndef OTUnused
950 c = OTNumOfBits - OTMax - 1;
951 if (c)
952 fail (_("%d unused bits in i386_operand_type.\n"), c);
953 #endif
955 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
956 compare);
958 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
959 sizeof (opcode_modifiers [0]), compare);
961 qsort (operand_types, ARRAY_SIZE (operand_types),
962 sizeof (operand_types [0]), compare);
964 table = fopen ("i386-tbl.h", "w");
965 if (table == NULL)
966 fail (_("can't create i386-tbl.h, errno = %s\n"),
967 xstrerror (errno));
969 process_copyright (table);
971 process_i386_opcodes (table);
972 process_i386_registers (table);
973 process_i386_initializers ();
975 fclose (table);
977 exit (0);