gas/
[binutils.git] / opcodes / i386-gen.c
blob44bf052e99c75e142c55b14a934cde7645f1b653
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" }
113 static initializer operand_type_init [] =
115 { "OPERAND_TYPE_NONE",
116 "0" },
117 { "OPERAND_TYPE_REG8",
118 "Reg8" },
119 { "OPERAND_TYPE_REG16",
120 "Reg16" },
121 { "OPERAND_TYPE_REG32",
122 "Reg32" },
123 { "OPERAND_TYPE_REG64",
124 "Reg64" },
125 { "OPERAND_TYPE_IMM1",
126 "Imm1" },
127 { "OPERAND_TYPE_IMM8",
128 "Imm8" },
129 { "OPERAND_TYPE_IMM8S",
130 "Imm8S" },
131 { "OPERAND_TYPE_IMM16",
132 "Imm16" },
133 { "OPERAND_TYPE_IMM32",
134 "Imm32" },
135 { "OPERAND_TYPE_IMM32S",
136 "Imm32S" },
137 { "OPERAND_TYPE_IMM64",
138 "Imm64" },
139 { "OPERAND_TYPE_BASEINDEX",
140 "BaseIndex" },
141 { "OPERAND_TYPE_DISP8",
142 "Disp8" },
143 { "OPERAND_TYPE_DISP16",
144 "Disp16" },
145 { "OPERAND_TYPE_DISP32",
146 "Disp32" },
147 { "OPERAND_TYPE_DISP32S",
148 "Disp32S" },
149 { "OPERAND_TYPE_DISP64",
150 "Disp64" },
151 { "OPERAND_TYPE_INOUTPORTREG",
152 "InOutPortReg" },
153 { "OPERAND_TYPE_SHIFTCOUNT",
154 "ShiftCount" },
155 { "OPERAND_TYPE_CONTROL",
156 "Control" },
157 { "OPERAND_TYPE_TEST",
158 "Test" },
159 { "OPERAND_TYPE_DEBUG",
160 "FloatReg" },
161 { "OPERAND_TYPE_FLOATREG",
162 "FloatReg" },
163 { "OPERAND_TYPE_FLOATACC",
164 "FloatAcc" },
165 { "OPERAND_TYPE_SREG2",
166 "SReg2" },
167 { "OPERAND_TYPE_SREG3",
168 "SReg3" },
169 { "OPERAND_TYPE_ACC",
170 "Acc" },
171 { "OPERAND_TYPE_JUMPABSOLUTE",
172 "JumpAbsolute" },
173 { "OPERAND_TYPE_REGMMX",
174 "RegMMX" },
175 { "OPERAND_TYPE_REGXMM",
176 "RegXMM" },
177 { "OPERAND_TYPE_ESSEG",
178 "EsSeg" },
179 { "OPERAND_TYPE_ACC32",
180 "Reg32|Acc" },
181 { "OPERAND_TYPE_ACC64",
182 "Reg64|Acc" },
183 { "OPERAND_TYPE_REG16_INOUTPORTREG",
184 "Reg16|InOutPortReg" },
185 { "OPERAND_TYPE_DISP16_32",
186 "Disp16|Disp32" },
187 { "OPERAND_TYPE_ANYDISP",
188 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
189 { "OPERAND_TYPE_IMM16_32",
190 "Imm16|Imm32" },
191 { "OPERAND_TYPE_IMM16_32S",
192 "Imm16|Imm32S" },
193 { "OPERAND_TYPE_IMM16_32_32S",
194 "Imm16|Imm32|Imm32S" },
195 { "OPERAND_TYPE_IMM32_32S_DISP32",
196 "Imm32|Imm32S|Disp32" },
197 { "OPERAND_TYPE_IMM64_DISP64",
198 "Imm64|Disp64" },
199 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
200 "Imm32|Imm32S|Imm64|Disp32" },
201 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
202 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
205 typedef struct bitfield
207 int position;
208 int value;
209 const char *name;
210 } bitfield;
212 #define BITFIELD(n) { n, 0, #n }
214 static bitfield cpu_flags[] =
216 BITFIELD (Cpu186),
217 BITFIELD (Cpu286),
218 BITFIELD (Cpu386),
219 BITFIELD (Cpu486),
220 BITFIELD (Cpu586),
221 BITFIELD (Cpu686),
222 BITFIELD (CpuP4),
223 BITFIELD (CpuK6),
224 BITFIELD (CpuK8),
225 BITFIELD (CpuMMX),
226 BITFIELD (CpuMMX2),
227 BITFIELD (CpuSSE),
228 BITFIELD (CpuSSE2),
229 BITFIELD (CpuSSE3),
230 BITFIELD (CpuSSSE3),
231 BITFIELD (CpuSSE4_1),
232 BITFIELD (CpuSSE4_2),
233 BITFIELD (CpuSSE4a),
234 BITFIELD (Cpu3dnow),
235 BITFIELD (Cpu3dnowA),
236 BITFIELD (CpuPadLock),
237 BITFIELD (CpuSVME),
238 BITFIELD (CpuVMX),
239 BITFIELD (CpuABM),
240 BITFIELD (CpuLM),
241 BITFIELD (Cpu64),
242 BITFIELD (CpuNo64),
243 #ifdef CpuUnused
244 BITFIELD (CpuUnused),
245 #endif
248 static bitfield opcode_modifiers[] =
250 BITFIELD (D),
251 BITFIELD (W),
252 BITFIELD (Modrm),
253 BITFIELD (ShortForm),
254 BITFIELD (Jump),
255 BITFIELD (JumpDword),
256 BITFIELD (JumpByte),
257 BITFIELD (JumpInterSegment),
258 BITFIELD (FloatMF),
259 BITFIELD (FloatR),
260 BITFIELD (FloatD),
261 BITFIELD (Size16),
262 BITFIELD (Size32),
263 BITFIELD (Size64),
264 BITFIELD (IgnoreSize),
265 BITFIELD (DefaultSize),
266 BITFIELD (No_bSuf),
267 BITFIELD (No_wSuf),
268 BITFIELD (No_lSuf),
269 BITFIELD (No_sSuf),
270 BITFIELD (No_qSuf),
271 BITFIELD (No_xSuf),
272 BITFIELD (FWait),
273 BITFIELD (IsString),
274 BITFIELD (RegKludge),
275 BITFIELD (IsPrefix),
276 BITFIELD (ImmExt),
277 BITFIELD (NoRex64),
278 BITFIELD (Rex64),
279 BITFIELD (Ugh),
282 static bitfield operand_types[] =
284 BITFIELD (Reg8),
285 BITFIELD (Reg16),
286 BITFIELD (Reg32),
287 BITFIELD (Reg64),
288 BITFIELD (FloatReg),
289 BITFIELD (RegMMX),
290 BITFIELD (RegXMM),
291 BITFIELD (Imm8),
292 BITFIELD (Imm8S),
293 BITFIELD (Imm16),
294 BITFIELD (Imm32),
295 BITFIELD (Imm32S),
296 BITFIELD (Imm64),
297 BITFIELD (Imm1),
298 BITFIELD (BaseIndex),
299 BITFIELD (Disp8),
300 BITFIELD (Disp16),
301 BITFIELD (Disp32),
302 BITFIELD (Disp32S),
303 BITFIELD (Disp64),
304 BITFIELD (InOutPortReg),
305 BITFIELD (ShiftCount),
306 BITFIELD (Control),
307 BITFIELD (Debug),
308 BITFIELD (Test),
309 BITFIELD (SReg2),
310 BITFIELD (SReg3),
311 BITFIELD (Acc),
312 BITFIELD (FloatAcc),
313 BITFIELD (JumpAbsolute),
314 BITFIELD (EsSeg),
315 BITFIELD (RegMem),
316 #ifdef OTUnused
317 BITFIELD (OTUnused),
318 #endif
321 static int
322 compare (const void *x, const void *y)
324 const bitfield *xp = (const bitfield *) x;
325 const bitfield *yp = (const bitfield *) y;
326 return xp->position - yp->position;
329 static void
330 fail (const char *message, ...)
332 va_list args;
334 va_start (args, message);
335 fprintf (stderr, _("%s: Error: "), program_name);
336 vfprintf (stderr, message, args);
337 va_end (args);
338 xexit (1);
341 static void
342 process_copyright (FILE *fp)
344 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
345 /* Copyright 2007 Free Software Foundation, Inc.\n\
347 This file is part of the GNU opcodes library.\n\
349 This library is free software; you can redistribute it and/or modify\n\
350 it under the terms of the GNU General Public License as published by\n\
351 the Free Software Foundation; either version 3, or (at your option)\n\
352 any later version.\n\
354 It is distributed in the hope that it will be useful, but WITHOUT\n\
355 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
356 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
357 License for more details.\n\
359 You should have received a copy of the GNU General Public License\n\
360 along with this program; if not, write to the Free Software\n\
361 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
362 MA 02110-1301, USA. */\n");
365 /* Remove leading white spaces. */
367 static char *
368 remove_leading_whitespaces (char *str)
370 while (ISSPACE (*str))
371 str++;
372 return str;
375 /* Remove trailing white spaces. */
377 static void
378 remove_trailing_whitespaces (char *str)
380 size_t last = strlen (str);
382 if (last == 0)
383 return;
387 last--;
388 if (ISSPACE (str [last]))
389 str[last] = '\0';
390 else
391 break;
393 while (last != 0);
396 /* Find next field separated by SEP and terminate it. Return a
397 pointer to the one after it. */
399 static char *
400 next_field (char *str, char sep, char **next)
402 char *p;
404 p = remove_leading_whitespaces (str);
405 for (str = p; *str != sep && *str != '\0'; str++);
407 *str = '\0';
408 remove_trailing_whitespaces (p);
410 *next = str + 1;
412 return p;
415 static void
416 set_bitfield (const char *f, bitfield *array, unsigned int size)
418 unsigned int i;
420 if (strcmp (f, "CpuSledgehammer") == 0)
421 f= "CpuK8";
423 for (i = 0; i < size; i++)
424 if (strcasecmp (array[i].name, f) == 0)
426 array[i].value = 1;
427 return;
430 printf ("Unknown bitfield: %s\n", f);
431 abort ();
434 static void
435 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
436 int macro, const char *comma, const char *indent)
438 unsigned int i;
440 fprintf (table, "%s{ { ", indent);
442 for (i = 0; i < size - 1; i++)
444 fprintf (table, "%d, ", flags[i].value);
445 if (((i + 1) % 20) == 0)
447 /* We need \\ for macro. */
448 if (macro)
449 fprintf (table, " \\\n %s", indent);
450 else
451 fprintf (table, "\n %s", indent);
455 fprintf (table, "%d } }%s\n", flags[i].value, comma);
458 static void
459 process_i386_cpu_flag (FILE *table, char *flag, int macro,
460 const char *comma, const char *indent)
462 char *str, *next, *last;
463 bitfield flags [ARRAY_SIZE (cpu_flags)];
465 /* Copy the default cpu flags. */
466 memcpy (flags, cpu_flags, sizeof (cpu_flags));
468 if (strcasecmp (flag, "unknown") == 0)
470 unsigned int i;
472 /* We turn on everything except for cpu64 in case of
473 CPU_UNKNOWN_FLAGS. */
474 for (i = 0; i < ARRAY_SIZE (flags); i++)
475 if (flags[i].position != Cpu64)
476 flags[i].value = 1;
478 else if (strcmp (flag, "0"))
480 last = flag + strlen (flag);
481 for (next = flag; next && next < last; )
483 str = next_field (next, '|', &next);
484 if (str)
485 set_bitfield (str, flags, ARRAY_SIZE (flags));
489 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
490 comma, indent);
493 static void
494 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
496 unsigned int i;
498 fprintf (table, " { ");
500 for (i = 0; i < size - 1; i++)
502 fprintf (table, "%d, ", modifier[i].value);
503 if (((i + 1) % 20) == 0)
504 fprintf (table, "\n ");
507 fprintf (table, "%d },\n", modifier[i].value);
510 static void
511 process_i386_opcode_modifier (FILE *table, char *mod)
513 char *str, *next, *last;
514 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
516 /* Copy the default opcode modifier. */
517 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
519 if (strcmp (mod, "0"))
521 last = mod + strlen (mod);
522 for (next = mod; next && next < last; )
524 str = next_field (next, '|', &next);
525 if (str)
526 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
529 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
532 static void
533 output_operand_type (FILE *table, bitfield *types, unsigned int size,
534 int macro, const char *indent)
536 unsigned int i;
538 fprintf (table, "{ { ");
540 for (i = 0; i < size - 1; i++)
542 fprintf (table, "%d, ", types[i].value);
543 if (((i + 1) % 20) == 0)
545 /* We need \\ for macro. */
546 if (macro)
547 fprintf (table, "\\\n%s", indent);
548 else
549 fprintf (table, "\n%s", indent);
553 fprintf (table, "%d } }", types[i].value);
556 static void
557 process_i386_operand_type (FILE *table, char *op, int macro,
558 const char *indent)
560 char *str, *next, *last;
561 bitfield types [ARRAY_SIZE (operand_types)];
563 /* Copy the default operand type. */
564 memcpy (types, operand_types, sizeof (types));
566 if (strcmp (op, "0"))
568 last = op + strlen (op);
569 for (next = op; next && next < last; )
571 str = next_field (next, '|', &next);
572 if (str)
573 set_bitfield (str, types, ARRAY_SIZE (types));
576 output_operand_type (table, types, ARRAY_SIZE (types), macro,
577 indent);
580 static void
581 process_i386_opcodes (FILE *table)
583 FILE *fp = fopen ("i386-opc.tbl", "r");
584 char buf[2048];
585 unsigned int i;
586 char *str, *p, *last;
587 char *name, *operands, *base_opcode, *extension_opcode;
588 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
590 if (fp == NULL)
591 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
592 xstrerror (errno));
594 fprintf (table, "\n/* i386 opcode table. */\n\n");
595 fprintf (table, "const template i386_optab[] =\n{\n");
597 while (!feof (fp))
599 if (fgets (buf, sizeof (buf), fp) == NULL)
600 break;
602 p = remove_leading_whitespaces (buf);
604 /* Skip comments. */
605 str = strstr (p, "//");
606 if (str != NULL)
607 str[0] = '\0';
609 /* Remove trailing white spaces. */
610 remove_trailing_whitespaces (p);
612 switch (p[0])
614 case '#':
615 fprintf (table, "%s\n", p);
616 case '\0':
617 continue;
618 break;
619 default:
620 break;
623 last = p + strlen (p);
625 /* Find name. */
626 name = next_field (p, ',', &str);
628 if (str >= last)
629 abort ();
631 /* Find number of operands. */
632 operands = next_field (str, ',', &str);
634 if (str >= last)
635 abort ();
637 /* Find base_opcode. */
638 base_opcode = next_field (str, ',', &str);
640 if (str >= last)
641 abort ();
643 /* Find extension_opcode. */
644 extension_opcode = next_field (str, ',', &str);
646 if (str >= last)
647 abort ();
649 /* Find cpu_flags. */
650 cpu_flags = next_field (str, ',', &str);
652 if (str >= last)
653 abort ();
655 /* Find opcode_modifier. */
656 opcode_modifier = next_field (str, ',', &str);
658 if (str >= last)
659 abort ();
661 /* Remove the first {. */
662 str = remove_leading_whitespaces (str);
663 if (*str != '{')
664 abort ();
665 str = remove_leading_whitespaces (str + 1);
667 i = strlen (str);
669 /* There are at least "X}". */
670 if (i < 2)
671 abort ();
673 /* Remove trailing white spaces and }. */
676 i--;
677 if (ISSPACE (str[i]) || str[i] == '}')
678 str[i] = '\0';
679 else
680 break;
682 while (i != 0);
684 last = str + i;
686 /* Find operand_types. */
687 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
689 if (str >= last)
691 operand_types [i] = NULL;
692 break;
695 operand_types [i] = next_field (str, ',', &str);
696 if (*operand_types[i] == '0')
698 if (i != 0)
699 operand_types[i] = NULL;
700 break;
704 fprintf (table, " { \"%s\", %s, %s, %s,\n",
705 name, operands, base_opcode, extension_opcode);
707 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
709 process_i386_opcode_modifier (table, opcode_modifier);
711 fprintf (table, " { ");
713 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
715 if (operand_types[i] == NULL
716 || *operand_types[i] == '0')
718 if (i == 0)
719 process_i386_operand_type (table, "0", 0, "\t ");
720 break;
723 if (i != 0)
724 fprintf (table, ",\n ");
726 process_i386_operand_type (table, operand_types[i], 0,
727 "\t ");
729 fprintf (table, " } },\n");
732 fclose (fp);
734 fprintf (table, " { NULL, 0, 0, 0,\n");
736 process_i386_cpu_flag (table, "0", 0, ",", " ");
738 process_i386_opcode_modifier (table, "0");
740 fprintf (table, " { ");
741 process_i386_operand_type (table, "0", 0, "\t ");
742 fprintf (table, " } }\n");
744 fprintf (table, "};\n");
747 static void
748 process_i386_registers (FILE *table)
750 FILE *fp = fopen ("i386-reg.tbl", "r");
751 char buf[2048];
752 char *str, *p, *last;
753 char *reg_name, *reg_type, *reg_flags, *reg_num;
755 if (fp == NULL)
756 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
757 xstrerror (errno));
759 fprintf (table, "\n/* i386 register table. */\n\n");
760 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
762 while (!feof (fp))
764 if (fgets (buf, sizeof (buf), fp) == NULL)
765 break;
767 p = remove_leading_whitespaces (buf);
769 /* Skip comments. */
770 str = strstr (p, "//");
771 if (str != NULL)
772 str[0] = '\0';
774 /* Remove trailing white spaces. */
775 remove_trailing_whitespaces (p);
777 switch (p[0])
779 case '#':
780 fprintf (table, "%s\n", p);
781 case '\0':
782 continue;
783 break;
784 default:
785 break;
788 last = p + strlen (p);
790 /* Find reg_name. */
791 reg_name = next_field (p, ',', &str);
793 if (str >= last)
794 abort ();
796 /* Find reg_type. */
797 reg_type = next_field (str, ',', &str);
799 if (str >= last)
800 abort ();
802 /* Find reg_flags. */
803 reg_flags = next_field (str, ',', &str);
805 if (str >= last)
806 abort ();
808 /* Find reg_num. */
809 reg_num = next_field (str, ',', &str);
811 fprintf (table, " { \"%s\",\n ", reg_name);
813 process_i386_operand_type (table, reg_type, 0, "\t");
815 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
818 fclose (fp);
820 fprintf (table, "};\n");
822 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
825 static void
826 process_i386_initializers (void)
828 unsigned int i;
829 FILE *fp = fopen ("i386-init.h", "w");
830 char *init;
832 if (fp == NULL)
833 fail (_("can't create i386-init.h, errno = %s\n"),
834 xstrerror (errno));
836 process_copyright (fp);
838 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
840 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
841 init = xstrdup (cpu_flag_init[i].init);
842 process_i386_cpu_flag (fp, init, 1, "", " ");
843 free (init);
846 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
848 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
849 init = xstrdup (operand_type_init[i].init);
850 process_i386_operand_type (fp, init, 1, " ");
851 free (init);
853 fprintf (fp, "\n");
855 fclose (fp);
858 /* Program options. */
859 #define OPTION_SRCDIR 200
861 struct option long_options[] =
863 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
864 {"debug", no_argument, NULL, 'd'},
865 {"version", no_argument, NULL, 'V'},
866 {"help", no_argument, NULL, 'h'},
867 {0, no_argument, NULL, 0}
870 static void
871 print_version (void)
873 printf ("%s: version 1.0\n", program_name);
874 xexit (0);
877 static void
878 usage (FILE * stream, int status)
880 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
881 program_name);
882 xexit (status);
886 main (int argc, char **argv)
888 extern int chdir (char *);
889 char *srcdir = NULL;
890 int c, unused;
891 FILE *table;
893 program_name = *argv;
894 xmalloc_set_program_name (program_name);
896 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
897 switch (c)
899 case OPTION_SRCDIR:
900 srcdir = optarg;
901 break;
902 case 'V':
903 case 'v':
904 print_version ();
905 break;
906 case 'd':
907 debug = 1;
908 break;
909 case 'h':
910 case '?':
911 usage (stderr, 0);
912 default:
913 case 0:
914 break;
917 if (optind != argc)
918 usage (stdout, 1);
920 if (srcdir != NULL)
921 if (chdir (srcdir) != 0)
922 fail (_("unable to change directory to \"%s\", errno = %s\n"),
923 srcdir, xstrerror (errno));
925 /* Check the unused bitfield in i386_cpu_flags. */
926 #ifndef CpuUnused
927 unused = CpuNumOfBits - CpuMax - 1;
928 if (unused)
929 fail (_("%d unused bits in i386_cpu_flags.\n"), unused);
930 #endif
932 /* Check the unused bitfield in i386_operand_type. */
933 #ifndef OTUnused
934 unused = OTNumOfBits - OTMax - 1;
935 if (unused)
936 fail (_("%d unused bits in i386_operand_type.\n"), unused);
937 #endif
939 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
940 compare);
942 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
943 sizeof (opcode_modifiers [0]), compare);
945 qsort (operand_types, ARRAY_SIZE (operand_types),
946 sizeof (operand_types [0]), compare);
948 table = fopen ("i386-tbl.h", "w");
949 if (table == NULL)
950 fail (_("can't create i386-tbl.h, errno = %s\n"),
951 xstrerror (errno));
953 process_copyright (table);
955 process_i386_opcodes (table);
956 process_i386_registers (table);
957 process_i386_initializers ();
959 fclose (table);
961 exit (0);