Update
[gdb.git] / opcodes / i386-gen.c
blobf7e93697c3ecdf10642ae586b87dd4bf639f3478
1 /* Copyright 2007, 2008 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|CpuSSE|CpuSSE2|CpuLM" },
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|CpuSSE" },
67 { "CPU_P4_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2" },
69 { "CPU_NOCONA_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
71 { "CPU_CORE_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
73 { "CPU_CORE2_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|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|Cpu3dnow|Cpu3dnowA" },
81 { "CPU_K8_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
83 { "CPU_AMDFAM10_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
85 { "CPU_MMX_FLAGS",
86 "CpuMMX" },
87 { "CPU_SSE_FLAGS",
88 "CpuMMX|CpuSSE" },
89 { "CPU_SSE2_FLAGS",
90 "CpuMMX|CpuSSE|CpuSSE2" },
91 { "CPU_SSE3_FLAGS",
92 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
93 { "CPU_SSSE3_FLAGS",
94 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
95 { "CPU_SSE4_1_FLAGS",
96 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
97 { "CPU_SSE4_2_FLAGS",
98 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
99 { "CPU_VMX_FLAGS",
100 "CpuVMX" },
101 { "CPU_SMX_FLAGS",
102 "CpuSMX" },
103 { "CPU_XSAVE_FLAGS",
104 "CpuXsave" },
105 { "CPU_3DNOW_FLAGS",
106 "CpuMMX|Cpu3dnow" },
107 { "CPU_3DNOWA_FLAGS",
108 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
109 { "CPU_PADLOCK_FLAGS",
110 "CpuPadLock" },
111 { "CPU_SVME_FLAGS",
112 "CpuSVME" },
113 { "CPU_SSE4A_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
115 { "CPU_ABM_FLAGS",
116 "CpuABM" },
117 { "CPU_SSE5_FLAGS",
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
121 static initializer operand_type_init [] =
123 { "OPERAND_TYPE_NONE",
124 "0" },
125 { "OPERAND_TYPE_REG8",
126 "Reg8" },
127 { "OPERAND_TYPE_REG16",
128 "Reg16" },
129 { "OPERAND_TYPE_REG32",
130 "Reg32" },
131 { "OPERAND_TYPE_REG64",
132 "Reg64" },
133 { "OPERAND_TYPE_IMM1",
134 "Imm1" },
135 { "OPERAND_TYPE_IMM8",
136 "Imm8" },
137 { "OPERAND_TYPE_IMM8S",
138 "Imm8S" },
139 { "OPERAND_TYPE_IMM16",
140 "Imm16" },
141 { "OPERAND_TYPE_IMM32",
142 "Imm32" },
143 { "OPERAND_TYPE_IMM32S",
144 "Imm32S" },
145 { "OPERAND_TYPE_IMM64",
146 "Imm64" },
147 { "OPERAND_TYPE_BASEINDEX",
148 "BaseIndex" },
149 { "OPERAND_TYPE_DISP8",
150 "Disp8" },
151 { "OPERAND_TYPE_DISP16",
152 "Disp16" },
153 { "OPERAND_TYPE_DISP32",
154 "Disp32" },
155 { "OPERAND_TYPE_DISP32S",
156 "Disp32S" },
157 { "OPERAND_TYPE_DISP64",
158 "Disp64" },
159 { "OPERAND_TYPE_INOUTPORTREG",
160 "InOutPortReg" },
161 { "OPERAND_TYPE_SHIFTCOUNT",
162 "ShiftCount" },
163 { "OPERAND_TYPE_CONTROL",
164 "Control" },
165 { "OPERAND_TYPE_TEST",
166 "Test" },
167 { "OPERAND_TYPE_DEBUG",
168 "FloatReg" },
169 { "OPERAND_TYPE_FLOATREG",
170 "FloatReg" },
171 { "OPERAND_TYPE_FLOATACC",
172 "FloatAcc" },
173 { "OPERAND_TYPE_SREG2",
174 "SReg2" },
175 { "OPERAND_TYPE_SREG3",
176 "SReg3" },
177 { "OPERAND_TYPE_ACC",
178 "Acc" },
179 { "OPERAND_TYPE_JUMPABSOLUTE",
180 "JumpAbsolute" },
181 { "OPERAND_TYPE_REGMMX",
182 "RegMMX" },
183 { "OPERAND_TYPE_REGXMM",
184 "RegXMM" },
185 { "OPERAND_TYPE_ESSEG",
186 "EsSeg" },
187 { "OPERAND_TYPE_ACC32",
188 "Reg32|Acc|Dword" },
189 { "OPERAND_TYPE_ACC64",
190 "Reg64|Acc|Qword" },
191 { "OPERAND_TYPE_INOUTPORTREG",
192 "InOutPortReg" },
193 { "OPERAND_TYPE_REG16_INOUTPORTREG",
194 "Reg16|InOutPortReg" },
195 { "OPERAND_TYPE_DISP16_32",
196 "Disp16|Disp32" },
197 { "OPERAND_TYPE_ANYDISP",
198 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
199 { "OPERAND_TYPE_IMM16_32",
200 "Imm16|Imm32" },
201 { "OPERAND_TYPE_IMM16_32S",
202 "Imm16|Imm32S" },
203 { "OPERAND_TYPE_IMM16_32_32S",
204 "Imm16|Imm32|Imm32S" },
205 { "OPERAND_TYPE_IMM32_32S_DISP32",
206 "Imm32|Imm32S|Disp32" },
207 { "OPERAND_TYPE_IMM64_DISP64",
208 "Imm64|Disp64" },
209 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
210 "Imm32|Imm32S|Imm64|Disp32" },
211 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
212 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
215 typedef struct bitfield
217 int position;
218 int value;
219 const char *name;
220 } bitfield;
222 #define BITFIELD(n) { n, 0, #n }
224 static bitfield cpu_flags[] =
226 BITFIELD (Cpu186),
227 BITFIELD (Cpu286),
228 BITFIELD (Cpu386),
229 BITFIELD (Cpu486),
230 BITFIELD (Cpu586),
231 BITFIELD (Cpu686),
232 BITFIELD (CpuP4),
233 BITFIELD (CpuK6),
234 BITFIELD (CpuK8),
235 BITFIELD (CpuMMX),
236 BITFIELD (CpuSSE),
237 BITFIELD (CpuSSE2),
238 BITFIELD (CpuSSE3),
239 BITFIELD (CpuSSSE3),
240 BITFIELD (CpuSSE4_1),
241 BITFIELD (CpuSSE4_2),
242 BITFIELD (CpuSSE4a),
243 BITFIELD (CpuSSE5),
244 BITFIELD (Cpu3dnow),
245 BITFIELD (Cpu3dnowA),
246 BITFIELD (CpuPadLock),
247 BITFIELD (CpuSVME),
248 BITFIELD (CpuVMX),
249 BITFIELD (CpuSMX),
250 BITFIELD (CpuABM),
251 BITFIELD (CpuLM),
252 BITFIELD (CpuXsave),
253 BITFIELD (Cpu64),
254 BITFIELD (CpuNo64),
255 #ifdef CpuUnused
256 BITFIELD (CpuUnused),
257 #endif
260 static bitfield opcode_modifiers[] =
262 BITFIELD (D),
263 BITFIELD (W),
264 BITFIELD (Modrm),
265 BITFIELD (ShortForm),
266 BITFIELD (Jump),
267 BITFIELD (JumpDword),
268 BITFIELD (JumpByte),
269 BITFIELD (JumpInterSegment),
270 BITFIELD (FloatMF),
271 BITFIELD (FloatR),
272 BITFIELD (FloatD),
273 BITFIELD (Size16),
274 BITFIELD (Size32),
275 BITFIELD (Size64),
276 BITFIELD (IgnoreSize),
277 BITFIELD (DefaultSize),
278 BITFIELD (No_bSuf),
279 BITFIELD (No_wSuf),
280 BITFIELD (No_lSuf),
281 BITFIELD (No_sSuf),
282 BITFIELD (No_qSuf),
283 BITFIELD (No_ldSuf),
284 BITFIELD (FWait),
285 BITFIELD (IsString),
286 BITFIELD (RegKludge),
287 BITFIELD (FirstXmm0),
288 BITFIELD (ByteOkIntel),
289 BITFIELD (ToDword),
290 BITFIELD (ToQword),
291 BITFIELD (AddrPrefixOp0),
292 BITFIELD (IsPrefix),
293 BITFIELD (ImmExt),
294 BITFIELD (NoRex64),
295 BITFIELD (Rex64),
296 BITFIELD (Ugh),
297 BITFIELD (Drex),
298 BITFIELD (Drexv),
299 BITFIELD (Drexc),
300 BITFIELD (OldGcc),
301 BITFIELD (ATTMnemonic),
302 BITFIELD (ATTSyntax),
303 BITFIELD (IntelSyntax),
306 static bitfield operand_types[] =
308 BITFIELD (Reg8),
309 BITFIELD (Reg16),
310 BITFIELD (Reg32),
311 BITFIELD (Reg64),
312 BITFIELD (FloatReg),
313 BITFIELD (RegMMX),
314 BITFIELD (RegXMM),
315 BITFIELD (Imm8),
316 BITFIELD (Imm8S),
317 BITFIELD (Imm16),
318 BITFIELD (Imm32),
319 BITFIELD (Imm32S),
320 BITFIELD (Imm64),
321 BITFIELD (Imm1),
322 BITFIELD (BaseIndex),
323 BITFIELD (Disp8),
324 BITFIELD (Disp16),
325 BITFIELD (Disp32),
326 BITFIELD (Disp32S),
327 BITFIELD (Disp64),
328 BITFIELD (InOutPortReg),
329 BITFIELD (ShiftCount),
330 BITFIELD (Control),
331 BITFIELD (Debug),
332 BITFIELD (Test),
333 BITFIELD (SReg2),
334 BITFIELD (SReg3),
335 BITFIELD (Acc),
336 BITFIELD (FloatAcc),
337 BITFIELD (JumpAbsolute),
338 BITFIELD (EsSeg),
339 BITFIELD (RegMem),
340 BITFIELD (Mem),
341 BITFIELD (Byte),
342 BITFIELD (Word),
343 BITFIELD (Dword),
344 BITFIELD (Fword),
345 BITFIELD (Qword),
346 BITFIELD (Tbyte),
347 BITFIELD (Xmmword),
348 BITFIELD (Unspecified),
349 BITFIELD (Anysize),
350 #ifdef OTUnused
351 BITFIELD (OTUnused),
352 #endif
355 static int lineno;
356 static const char *filename;
358 static int
359 compare (const void *x, const void *y)
361 const bitfield *xp = (const bitfield *) x;
362 const bitfield *yp = (const bitfield *) y;
363 return xp->position - yp->position;
366 static void
367 fail (const char *message, ...)
369 va_list args;
371 va_start (args, message);
372 fprintf (stderr, _("%s: Error: "), program_name);
373 vfprintf (stderr, message, args);
374 va_end (args);
375 xexit (1);
378 static void
379 process_copyright (FILE *fp)
381 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
382 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
384 This file is part of the GNU opcodes library.\n\
386 This library is free software; you can redistribute it and/or modify\n\
387 it under the terms of the GNU General Public License as published by\n\
388 the Free Software Foundation; either version 3, or (at your option)\n\
389 any later version.\n\
391 It is distributed in the hope that it will be useful, but WITHOUT\n\
392 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
393 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
394 License for more details.\n\
396 You should have received a copy of the GNU General Public License\n\
397 along with this program; if not, write to the Free Software\n\
398 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
399 MA 02110-1301, USA. */\n");
402 /* Remove leading white spaces. */
404 static char *
405 remove_leading_whitespaces (char *str)
407 while (ISSPACE (*str))
408 str++;
409 return str;
412 /* Remove trailing white spaces. */
414 static void
415 remove_trailing_whitespaces (char *str)
417 size_t last = strlen (str);
419 if (last == 0)
420 return;
424 last--;
425 if (ISSPACE (str [last]))
426 str[last] = '\0';
427 else
428 break;
430 while (last != 0);
433 /* Find next field separated by SEP and terminate it. Return a
434 pointer to the one after it. */
436 static char *
437 next_field (char *str, char sep, char **next)
439 char *p;
441 p = remove_leading_whitespaces (str);
442 for (str = p; *str != sep && *str != '\0'; str++);
444 *str = '\0';
445 remove_trailing_whitespaces (p);
447 *next = str + 1;
449 return p;
452 static void
453 set_bitfield (const char *f, bitfield *array, unsigned int size)
455 unsigned int i;
457 if (strcmp (f, "CpuSledgehammer") == 0)
458 f= "CpuK8";
459 else if (strcmp (f, "Mmword") == 0)
460 f= "Qword";
461 else if (strcmp (f, "Oword") == 0)
462 f= "Xmmword";
464 for (i = 0; i < size; i++)
465 if (strcasecmp (array[i].name, f) == 0)
467 array[i].value = 1;
468 return;
471 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
474 static void
475 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
476 int macro, const char *comma, const char *indent)
478 unsigned int i;
480 fprintf (table, "%s{ { ", indent);
482 for (i = 0; i < size - 1; i++)
484 fprintf (table, "%d, ", flags[i].value);
485 if (((i + 1) % 20) == 0)
487 /* We need \\ for macro. */
488 if (macro)
489 fprintf (table, " \\\n %s", indent);
490 else
491 fprintf (table, "\n %s", indent);
495 fprintf (table, "%d } }%s\n", flags[i].value, comma);
498 static void
499 process_i386_cpu_flag (FILE *table, char *flag, int macro,
500 const char *comma, const char *indent)
502 char *str, *next, *last;
503 bitfield flags [ARRAY_SIZE (cpu_flags)];
505 /* Copy the default cpu flags. */
506 memcpy (flags, cpu_flags, sizeof (cpu_flags));
508 if (strcasecmp (flag, "unknown") == 0)
510 unsigned int i;
512 /* We turn on everything except for cpu64 in case of
513 CPU_UNKNOWN_FLAGS. */
514 for (i = 0; i < ARRAY_SIZE (flags); i++)
515 if (flags[i].position != Cpu64)
516 flags[i].value = 1;
518 else if (strcmp (flag, "0"))
520 last = flag + strlen (flag);
521 for (next = flag; next && next < last; )
523 str = next_field (next, '|', &next);
524 if (str)
525 set_bitfield (str, flags, ARRAY_SIZE (flags));
529 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
530 comma, indent);
533 static void
534 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
536 unsigned int i;
538 fprintf (table, " { ");
540 for (i = 0; i < size - 1; i++)
542 fprintf (table, "%d, ", modifier[i].value);
543 if (((i + 1) % 20) == 0)
544 fprintf (table, "\n ");
547 fprintf (table, "%d },\n", modifier[i].value);
550 static void
551 process_i386_opcode_modifier (FILE *table, char *mod)
553 char *str, *next, *last;
554 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
556 /* Copy the default opcode modifier. */
557 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
559 if (strcmp (mod, "0"))
561 last = mod + strlen (mod);
562 for (next = mod; next && next < last; )
564 str = next_field (next, '|', &next);
565 if (str)
566 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
569 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
572 static void
573 output_operand_type (FILE *table, bitfield *types, unsigned int size,
574 int macro, const char *indent)
576 unsigned int i;
578 fprintf (table, "{ { ");
580 for (i = 0; i < size - 1; i++)
582 fprintf (table, "%d, ", types[i].value);
583 if (((i + 1) % 20) == 0)
585 /* We need \\ for macro. */
586 if (macro)
587 fprintf (table, "\\\n%s", indent);
588 else
589 fprintf (table, "\n%s", indent);
593 fprintf (table, "%d } }", types[i].value);
596 static void
597 process_i386_operand_type (FILE *table, char *op, int macro,
598 const char *indent)
600 char *str, *next, *last;
601 bitfield types [ARRAY_SIZE (operand_types)];
603 /* Copy the default operand type. */
604 memcpy (types, operand_types, sizeof (types));
606 if (strcmp (op, "0"))
608 last = op + strlen (op);
609 for (next = op; next && next < last; )
611 str = next_field (next, '|', &next);
612 if (str)
613 set_bitfield (str, types, ARRAY_SIZE (types));
616 output_operand_type (table, types, ARRAY_SIZE (types), macro,
617 indent);
620 static void
621 process_i386_opcodes (FILE *table)
623 FILE *fp;
624 char buf[2048];
625 unsigned int i;
626 char *str, *p, *last;
627 char *name, *operands, *base_opcode, *extension_opcode;
628 char *opcode_length;
629 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
631 filename = "i386-opc.tbl";
632 fp = fopen (filename, "r");
634 if (fp == NULL)
635 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
636 xstrerror (errno));
638 fprintf (table, "\n/* i386 opcode table. */\n\n");
639 fprintf (table, "const template i386_optab[] =\n{\n");
641 while (!feof (fp))
643 if (fgets (buf, sizeof (buf), fp) == NULL)
644 break;
646 lineno++;
648 p = remove_leading_whitespaces (buf);
650 /* Skip comments. */
651 str = strstr (p, "//");
652 if (str != NULL)
653 str[0] = '\0';
655 /* Remove trailing white spaces. */
656 remove_trailing_whitespaces (p);
658 switch (p[0])
660 case '#':
661 fprintf (table, "%s\n", p);
662 case '\0':
663 continue;
664 break;
665 default:
666 break;
669 last = p + strlen (p);
671 /* Find name. */
672 name = next_field (p, ',', &str);
674 if (str >= last)
675 abort ();
677 /* Find number of operands. */
678 operands = next_field (str, ',', &str);
680 if (str >= last)
681 abort ();
683 /* Find base_opcode. */
684 base_opcode = next_field (str, ',', &str);
686 if (str >= last)
687 abort ();
689 /* Find extension_opcode. */
690 extension_opcode = next_field (str, ',', &str);
692 if (str >= last)
693 abort ();
695 /* Find opcode_length. */
696 opcode_length = next_field (str, ',', &str);
698 if (str >= last)
699 abort ();
701 /* Find cpu_flags. */
702 cpu_flags = next_field (str, ',', &str);
704 if (str >= last)
705 abort ();
707 /* Find opcode_modifier. */
708 opcode_modifier = next_field (str, ',', &str);
710 if (str >= last)
711 abort ();
713 /* Remove the first {. */
714 str = remove_leading_whitespaces (str);
715 if (*str != '{')
716 abort ();
717 str = remove_leading_whitespaces (str + 1);
719 i = strlen (str);
721 /* There are at least "X}". */
722 if (i < 2)
723 abort ();
725 /* Remove trailing white spaces and }. */
728 i--;
729 if (ISSPACE (str[i]) || str[i] == '}')
730 str[i] = '\0';
731 else
732 break;
734 while (i != 0);
736 last = str + i;
738 /* Find operand_types. */
739 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
741 if (str >= last)
743 operand_types [i] = NULL;
744 break;
747 operand_types [i] = next_field (str, ',', &str);
748 if (*operand_types[i] == '0')
750 if (i != 0)
751 operand_types[i] = NULL;
752 break;
756 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
757 name, operands, base_opcode, extension_opcode,
758 opcode_length);
760 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
762 process_i386_opcode_modifier (table, opcode_modifier);
764 fprintf (table, " { ");
766 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
768 if (operand_types[i] == NULL
769 || *operand_types[i] == '0')
771 if (i == 0)
772 process_i386_operand_type (table, "0", 0, "\t ");
773 break;
776 if (i != 0)
777 fprintf (table, ",\n ");
779 process_i386_operand_type (table, operand_types[i], 0,
780 "\t ");
782 fprintf (table, " } },\n");
785 fclose (fp);
787 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
789 process_i386_cpu_flag (table, "0", 0, ",", " ");
791 process_i386_opcode_modifier (table, "0");
793 fprintf (table, " { ");
794 process_i386_operand_type (table, "0", 0, "\t ");
795 fprintf (table, " } }\n");
797 fprintf (table, "};\n");
800 static void
801 process_i386_registers (FILE *table)
803 FILE *fp;
804 char buf[2048];
805 char *str, *p, *last;
806 char *reg_name, *reg_type, *reg_flags, *reg_num;
807 char *dw2_32_num, *dw2_64_num;
809 filename = "i386-reg.tbl";
810 fp = fopen (filename, "r");
811 if (fp == NULL)
812 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
813 xstrerror (errno));
815 fprintf (table, "\n/* i386 register table. */\n\n");
816 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
818 while (!feof (fp))
820 if (fgets (buf, sizeof (buf), fp) == NULL)
821 break;
823 lineno++;
825 p = remove_leading_whitespaces (buf);
827 /* Skip comments. */
828 str = strstr (p, "//");
829 if (str != NULL)
830 str[0] = '\0';
832 /* Remove trailing white spaces. */
833 remove_trailing_whitespaces (p);
835 switch (p[0])
837 case '#':
838 fprintf (table, "%s\n", p);
839 case '\0':
840 continue;
841 break;
842 default:
843 break;
846 last = p + strlen (p);
848 /* Find reg_name. */
849 reg_name = next_field (p, ',', &str);
851 if (str >= last)
852 abort ();
854 /* Find reg_type. */
855 reg_type = next_field (str, ',', &str);
857 if (str >= last)
858 abort ();
860 /* Find reg_flags. */
861 reg_flags = next_field (str, ',', &str);
863 if (str >= last)
864 abort ();
866 /* Find reg_num. */
867 reg_num = next_field (str, ',', &str);
869 if (str >= last)
870 abort ();
872 fprintf (table, " { \"%s\",\n ", reg_name);
874 process_i386_operand_type (table, reg_type, 0, "\t");
876 /* Find 32-bit Dwarf2 register number. */
877 dw2_32_num = next_field (str, ',', &str);
879 if (str >= last)
880 abort ();
882 /* Find 64-bit Dwarf2 register number. */
883 dw2_64_num = next_field (str, ',', &str);
885 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
886 reg_flags, reg_num, dw2_32_num, dw2_64_num);
889 fclose (fp);
891 fprintf (table, "};\n");
893 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
896 static void
897 process_i386_initializers (void)
899 unsigned int i;
900 FILE *fp = fopen ("i386-init.h", "w");
901 char *init;
903 if (fp == NULL)
904 fail (_("can't create i386-init.h, errno = %s\n"),
905 xstrerror (errno));
907 process_copyright (fp);
909 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
911 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
912 init = xstrdup (cpu_flag_init[i].init);
913 process_i386_cpu_flag (fp, init, 1, "", " ");
914 free (init);
917 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
919 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
920 init = xstrdup (operand_type_init[i].init);
921 process_i386_operand_type (fp, init, 1, " ");
922 free (init);
924 fprintf (fp, "\n");
926 fclose (fp);
929 /* Program options. */
930 #define OPTION_SRCDIR 200
932 struct option long_options[] =
934 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
935 {"debug", no_argument, NULL, 'd'},
936 {"version", no_argument, NULL, 'V'},
937 {"help", no_argument, NULL, 'h'},
938 {0, no_argument, NULL, 0}
941 static void
942 print_version (void)
944 printf ("%s: version 1.0\n", program_name);
945 xexit (0);
948 static void
949 usage (FILE * stream, int status)
951 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
952 program_name);
953 xexit (status);
957 main (int argc, char **argv)
959 extern int chdir (char *);
960 char *srcdir = NULL;
961 int c;
962 FILE *table;
964 program_name = *argv;
965 xmalloc_set_program_name (program_name);
967 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
968 switch (c)
970 case OPTION_SRCDIR:
971 srcdir = optarg;
972 break;
973 case 'V':
974 case 'v':
975 print_version ();
976 break;
977 case 'd':
978 debug = 1;
979 break;
980 case 'h':
981 case '?':
982 usage (stderr, 0);
983 default:
984 case 0:
985 break;
988 if (optind != argc)
989 usage (stdout, 1);
991 if (srcdir != NULL)
992 if (chdir (srcdir) != 0)
993 fail (_("unable to change directory to \"%s\", errno = %s\n"),
994 srcdir, xstrerror (errno));
996 /* Check the unused bitfield in i386_cpu_flags. */
997 #ifndef CpuUnused
998 c = CpuNumOfBits - CpuMax - 1;
999 if (c)
1000 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1001 #endif
1003 /* Check the unused bitfield in i386_operand_type. */
1004 #ifndef OTUnused
1005 c = OTNumOfBits - OTMax - 1;
1006 if (c)
1007 fail (_("%d unused bits in i386_operand_type.\n"), c);
1008 #endif
1010 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1011 compare);
1013 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1014 sizeof (opcode_modifiers [0]), compare);
1016 qsort (operand_types, ARRAY_SIZE (operand_types),
1017 sizeof (operand_types [0]), compare);
1019 table = fopen ("i386-tbl.h", "w");
1020 if (table == NULL)
1021 fail (_("can't create i386-tbl.h, errno = %s\n"),
1022 xstrerror (errno));
1024 process_copyright (table);
1026 process_i386_opcodes (table);
1027 process_i386_registers (table);
1028 process_i386_initializers ();
1030 fclose (table);
1032 exit (0);