gas/
[binutils.git] / opcodes / i386-gen.c
blob515e2f7753102d8a7b833cae15b4da6fdfccc0fb
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_3DNOW_FLAGS",
104 "CpuMMX|Cpu3dnow" },
105 { "CPU_3DNOWA_FLAGS",
106 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
107 { "CPU_PADLOCK_FLAGS",
108 "CpuPadLock" },
109 { "CPU_SVME_FLAGS",
110 "CpuSVME" },
111 { "CPU_SSE4A_FLAGS",
112 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
113 { "CPU_ABM_FLAGS",
114 "CpuABM" },
115 { "CPU_SSE5_FLAGS",
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
119 static initializer operand_type_init [] =
121 { "OPERAND_TYPE_NONE",
122 "0" },
123 { "OPERAND_TYPE_REG8",
124 "Reg8" },
125 { "OPERAND_TYPE_REG16",
126 "Reg16" },
127 { "OPERAND_TYPE_REG32",
128 "Reg32" },
129 { "OPERAND_TYPE_REG64",
130 "Reg64" },
131 { "OPERAND_TYPE_IMM1",
132 "Imm1" },
133 { "OPERAND_TYPE_IMM8",
134 "Imm8" },
135 { "OPERAND_TYPE_IMM8S",
136 "Imm8S" },
137 { "OPERAND_TYPE_IMM16",
138 "Imm16" },
139 { "OPERAND_TYPE_IMM32",
140 "Imm32" },
141 { "OPERAND_TYPE_IMM32S",
142 "Imm32S" },
143 { "OPERAND_TYPE_IMM64",
144 "Imm64" },
145 { "OPERAND_TYPE_BASEINDEX",
146 "BaseIndex" },
147 { "OPERAND_TYPE_DISP8",
148 "Disp8" },
149 { "OPERAND_TYPE_DISP16",
150 "Disp16" },
151 { "OPERAND_TYPE_DISP32",
152 "Disp32" },
153 { "OPERAND_TYPE_DISP32S",
154 "Disp32S" },
155 { "OPERAND_TYPE_DISP64",
156 "Disp64" },
157 { "OPERAND_TYPE_INOUTPORTREG",
158 "InOutPortReg" },
159 { "OPERAND_TYPE_SHIFTCOUNT",
160 "ShiftCount" },
161 { "OPERAND_TYPE_CONTROL",
162 "Control" },
163 { "OPERAND_TYPE_TEST",
164 "Test" },
165 { "OPERAND_TYPE_DEBUG",
166 "FloatReg" },
167 { "OPERAND_TYPE_FLOATREG",
168 "FloatReg" },
169 { "OPERAND_TYPE_FLOATACC",
170 "FloatAcc" },
171 { "OPERAND_TYPE_SREG2",
172 "SReg2" },
173 { "OPERAND_TYPE_SREG3",
174 "SReg3" },
175 { "OPERAND_TYPE_ACC",
176 "Acc" },
177 { "OPERAND_TYPE_JUMPABSOLUTE",
178 "JumpAbsolute" },
179 { "OPERAND_TYPE_REGMMX",
180 "RegMMX" },
181 { "OPERAND_TYPE_REGXMM",
182 "RegXMM" },
183 { "OPERAND_TYPE_ESSEG",
184 "EsSeg" },
185 { "OPERAND_TYPE_ACC32",
186 "Reg32|Acc|Dword" },
187 { "OPERAND_TYPE_ACC64",
188 "Reg64|Acc|Qword" },
189 { "OPERAND_TYPE_REG16_INOUTPORTREG",
190 "Reg16|InOutPortReg" },
191 { "OPERAND_TYPE_DISP16_32",
192 "Disp16|Disp32" },
193 { "OPERAND_TYPE_ANYDISP",
194 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
195 { "OPERAND_TYPE_IMM16_32",
196 "Imm16|Imm32" },
197 { "OPERAND_TYPE_IMM16_32S",
198 "Imm16|Imm32S" },
199 { "OPERAND_TYPE_IMM16_32_32S",
200 "Imm16|Imm32|Imm32S" },
201 { "OPERAND_TYPE_IMM32_32S_DISP32",
202 "Imm32|Imm32S|Disp32" },
203 { "OPERAND_TYPE_IMM64_DISP64",
204 "Imm64|Disp64" },
205 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
206 "Imm32|Imm32S|Imm64|Disp32" },
207 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
208 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
211 typedef struct bitfield
213 int position;
214 int value;
215 const char *name;
216 } bitfield;
218 #define BITFIELD(n) { n, 0, #n }
220 static bitfield cpu_flags[] =
222 BITFIELD (Cpu186),
223 BITFIELD (Cpu286),
224 BITFIELD (Cpu386),
225 BITFIELD (Cpu486),
226 BITFIELD (Cpu586),
227 BITFIELD (Cpu686),
228 BITFIELD (CpuP4),
229 BITFIELD (CpuK6),
230 BITFIELD (CpuK8),
231 BITFIELD (CpuMMX),
232 BITFIELD (CpuSSE),
233 BITFIELD (CpuSSE2),
234 BITFIELD (CpuSSE3),
235 BITFIELD (CpuSSSE3),
236 BITFIELD (CpuSSE4_1),
237 BITFIELD (CpuSSE4_2),
238 BITFIELD (CpuSSE4a),
239 BITFIELD (CpuSSE5),
240 BITFIELD (Cpu3dnow),
241 BITFIELD (Cpu3dnowA),
242 BITFIELD (CpuPadLock),
243 BITFIELD (CpuSVME),
244 BITFIELD (CpuVMX),
245 BITFIELD (CpuSMX),
246 BITFIELD (CpuABM),
247 BITFIELD (CpuLM),
248 BITFIELD (Cpu64),
249 BITFIELD (CpuNo64),
250 #ifdef CpuUnused
251 BITFIELD (CpuUnused),
252 #endif
255 static bitfield opcode_modifiers[] =
257 BITFIELD (D),
258 BITFIELD (W),
259 BITFIELD (Modrm),
260 BITFIELD (ShortForm),
261 BITFIELD (Jump),
262 BITFIELD (JumpDword),
263 BITFIELD (JumpByte),
264 BITFIELD (JumpInterSegment),
265 BITFIELD (FloatMF),
266 BITFIELD (FloatR),
267 BITFIELD (FloatD),
268 BITFIELD (Size16),
269 BITFIELD (Size32),
270 BITFIELD (Size64),
271 BITFIELD (IgnoreSize),
272 BITFIELD (DefaultSize),
273 BITFIELD (No_bSuf),
274 BITFIELD (No_wSuf),
275 BITFIELD (No_lSuf),
276 BITFIELD (No_sSuf),
277 BITFIELD (No_qSuf),
278 BITFIELD (No_ldSuf),
279 BITFIELD (FWait),
280 BITFIELD (IsString),
281 BITFIELD (RegKludge),
282 BITFIELD (FirstXmm0),
283 BITFIELD (ByteOkIntel),
284 BITFIELD (ToDword),
285 BITFIELD (ToQword),
286 BITFIELD (AddrPrefixOp0),
287 BITFIELD (IsPrefix),
288 BITFIELD (ImmExt),
289 BITFIELD (NoRex64),
290 BITFIELD (Rex64),
291 BITFIELD (Ugh),
292 BITFIELD (Drex),
293 BITFIELD (Drexv),
294 BITFIELD (Drexc),
295 BITFIELD (OldGcc),
296 BITFIELD (ATTMnemonic),
297 BITFIELD (ATTSyntax),
298 BITFIELD (IntelSyntax),
301 static bitfield operand_types[] =
303 BITFIELD (Reg8),
304 BITFIELD (Reg16),
305 BITFIELD (Reg32),
306 BITFIELD (Reg64),
307 BITFIELD (FloatReg),
308 BITFIELD (RegMMX),
309 BITFIELD (RegXMM),
310 BITFIELD (Imm8),
311 BITFIELD (Imm8S),
312 BITFIELD (Imm16),
313 BITFIELD (Imm32),
314 BITFIELD (Imm32S),
315 BITFIELD (Imm64),
316 BITFIELD (Imm1),
317 BITFIELD (BaseIndex),
318 BITFIELD (Disp8),
319 BITFIELD (Disp16),
320 BITFIELD (Disp32),
321 BITFIELD (Disp32S),
322 BITFIELD (Disp64),
323 BITFIELD (InOutPortReg),
324 BITFIELD (ShiftCount),
325 BITFIELD (Control),
326 BITFIELD (Debug),
327 BITFIELD (Test),
328 BITFIELD (SReg2),
329 BITFIELD (SReg3),
330 BITFIELD (Acc),
331 BITFIELD (FloatAcc),
332 BITFIELD (JumpAbsolute),
333 BITFIELD (EsSeg),
334 BITFIELD (RegMem),
335 BITFIELD (Mem),
336 BITFIELD (Byte),
337 BITFIELD (Word),
338 BITFIELD (Dword),
339 BITFIELD (Fword),
340 BITFIELD (Qword),
341 BITFIELD (Tbyte),
342 BITFIELD (Xmmword),
343 BITFIELD (Unspecified),
344 BITFIELD (Anysize),
345 #ifdef OTUnused
346 BITFIELD (OTUnused),
347 #endif
350 static int lineno;
351 static const char *filename;
353 static int
354 compare (const void *x, const void *y)
356 const bitfield *xp = (const bitfield *) x;
357 const bitfield *yp = (const bitfield *) y;
358 return xp->position - yp->position;
361 static void
362 fail (const char *message, ...)
364 va_list args;
366 va_start (args, message);
367 fprintf (stderr, _("%s: Error: "), program_name);
368 vfprintf (stderr, message, args);
369 va_end (args);
370 xexit (1);
373 static void
374 process_copyright (FILE *fp)
376 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
377 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
379 This file is part of the GNU opcodes library.\n\
381 This library is free software; you can redistribute it and/or modify\n\
382 it under the terms of the GNU General Public License as published by\n\
383 the Free Software Foundation; either version 3, or (at your option)\n\
384 any later version.\n\
386 It is distributed in the hope that it will be useful, but WITHOUT\n\
387 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
388 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
389 License for more details.\n\
391 You should have received a copy of the GNU General Public License\n\
392 along with this program; if not, write to the Free Software\n\
393 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
394 MA 02110-1301, USA. */\n");
397 /* Remove leading white spaces. */
399 static char *
400 remove_leading_whitespaces (char *str)
402 while (ISSPACE (*str))
403 str++;
404 return str;
407 /* Remove trailing white spaces. */
409 static void
410 remove_trailing_whitespaces (char *str)
412 size_t last = strlen (str);
414 if (last == 0)
415 return;
419 last--;
420 if (ISSPACE (str [last]))
421 str[last] = '\0';
422 else
423 break;
425 while (last != 0);
428 /* Find next field separated by SEP and terminate it. Return a
429 pointer to the one after it. */
431 static char *
432 next_field (char *str, char sep, char **next)
434 char *p;
436 p = remove_leading_whitespaces (str);
437 for (str = p; *str != sep && *str != '\0'; str++);
439 *str = '\0';
440 remove_trailing_whitespaces (p);
442 *next = str + 1;
444 return p;
447 static void
448 set_bitfield (const char *f, bitfield *array, unsigned int size)
450 unsigned int i;
452 if (strcmp (f, "CpuSledgehammer") == 0)
453 f= "CpuK8";
454 else if (strcmp (f, "Mmword") == 0)
455 f= "Qword";
456 else if (strcmp (f, "Oword") == 0)
457 f= "Xmmword";
459 for (i = 0; i < size; i++)
460 if (strcasecmp (array[i].name, f) == 0)
462 array[i].value = 1;
463 return;
466 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
469 static void
470 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
471 int macro, const char *comma, const char *indent)
473 unsigned int i;
475 fprintf (table, "%s{ { ", indent);
477 for (i = 0; i < size - 1; i++)
479 fprintf (table, "%d, ", flags[i].value);
480 if (((i + 1) % 20) == 0)
482 /* We need \\ for macro. */
483 if (macro)
484 fprintf (table, " \\\n %s", indent);
485 else
486 fprintf (table, "\n %s", indent);
490 fprintf (table, "%d } }%s\n", flags[i].value, comma);
493 static void
494 process_i386_cpu_flag (FILE *table, char *flag, int macro,
495 const char *comma, const char *indent)
497 char *str, *next, *last;
498 bitfield flags [ARRAY_SIZE (cpu_flags)];
500 /* Copy the default cpu flags. */
501 memcpy (flags, cpu_flags, sizeof (cpu_flags));
503 if (strcasecmp (flag, "unknown") == 0)
505 unsigned int i;
507 /* We turn on everything except for cpu64 in case of
508 CPU_UNKNOWN_FLAGS. */
509 for (i = 0; i < ARRAY_SIZE (flags); i++)
510 if (flags[i].position != Cpu64)
511 flags[i].value = 1;
513 else if (strcmp (flag, "0"))
515 last = flag + strlen (flag);
516 for (next = flag; next && next < last; )
518 str = next_field (next, '|', &next);
519 if (str)
520 set_bitfield (str, flags, ARRAY_SIZE (flags));
524 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
525 comma, indent);
528 static void
529 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
531 unsigned int i;
533 fprintf (table, " { ");
535 for (i = 0; i < size - 1; i++)
537 fprintf (table, "%d, ", modifier[i].value);
538 if (((i + 1) % 20) == 0)
539 fprintf (table, "\n ");
542 fprintf (table, "%d },\n", modifier[i].value);
545 static void
546 process_i386_opcode_modifier (FILE *table, char *mod)
548 char *str, *next, *last;
549 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
551 /* Copy the default opcode modifier. */
552 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
554 if (strcmp (mod, "0"))
556 last = mod + strlen (mod);
557 for (next = mod; next && next < last; )
559 str = next_field (next, '|', &next);
560 if (str)
561 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
564 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
567 static void
568 output_operand_type (FILE *table, bitfield *types, unsigned int size,
569 int macro, const char *indent)
571 unsigned int i;
573 fprintf (table, "{ { ");
575 for (i = 0; i < size - 1; i++)
577 fprintf (table, "%d, ", types[i].value);
578 if (((i + 1) % 20) == 0)
580 /* We need \\ for macro. */
581 if (macro)
582 fprintf (table, "\\\n%s", indent);
583 else
584 fprintf (table, "\n%s", indent);
588 fprintf (table, "%d } }", types[i].value);
591 static void
592 process_i386_operand_type (FILE *table, char *op, int macro,
593 const char *indent)
595 char *str, *next, *last;
596 bitfield types [ARRAY_SIZE (operand_types)];
598 /* Copy the default operand type. */
599 memcpy (types, operand_types, sizeof (types));
601 if (strcmp (op, "0"))
603 last = op + strlen (op);
604 for (next = op; next && next < last; )
606 str = next_field (next, '|', &next);
607 if (str)
608 set_bitfield (str, types, ARRAY_SIZE (types));
611 output_operand_type (table, types, ARRAY_SIZE (types), macro,
612 indent);
615 static void
616 process_i386_opcodes (FILE *table)
618 FILE *fp;
619 char buf[2048];
620 unsigned int i;
621 char *str, *p, *last;
622 char *name, *operands, *base_opcode, *extension_opcode;
623 char *opcode_length;
624 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
626 filename = "i386-opc.tbl";
627 fp = fopen (filename, "r");
629 if (fp == NULL)
630 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
631 xstrerror (errno));
633 fprintf (table, "\n/* i386 opcode table. */\n\n");
634 fprintf (table, "const template i386_optab[] =\n{\n");
636 while (!feof (fp))
638 if (fgets (buf, sizeof (buf), fp) == NULL)
639 break;
641 lineno++;
643 p = remove_leading_whitespaces (buf);
645 /* Skip comments. */
646 str = strstr (p, "//");
647 if (str != NULL)
648 str[0] = '\0';
650 /* Remove trailing white spaces. */
651 remove_trailing_whitespaces (p);
653 switch (p[0])
655 case '#':
656 fprintf (table, "%s\n", p);
657 case '\0':
658 continue;
659 break;
660 default:
661 break;
664 last = p + strlen (p);
666 /* Find name. */
667 name = next_field (p, ',', &str);
669 if (str >= last)
670 abort ();
672 /* Find number of operands. */
673 operands = next_field (str, ',', &str);
675 if (str >= last)
676 abort ();
678 /* Find base_opcode. */
679 base_opcode = next_field (str, ',', &str);
681 if (str >= last)
682 abort ();
684 /* Find extension_opcode. */
685 extension_opcode = next_field (str, ',', &str);
687 if (str >= last)
688 abort ();
690 /* Find opcode_length. */
691 opcode_length = next_field (str, ',', &str);
693 if (str >= last)
694 abort ();
696 /* Find cpu_flags. */
697 cpu_flags = next_field (str, ',', &str);
699 if (str >= last)
700 abort ();
702 /* Find opcode_modifier. */
703 opcode_modifier = next_field (str, ',', &str);
705 if (str >= last)
706 abort ();
708 /* Remove the first {. */
709 str = remove_leading_whitespaces (str);
710 if (*str != '{')
711 abort ();
712 str = remove_leading_whitespaces (str + 1);
714 i = strlen (str);
716 /* There are at least "X}". */
717 if (i < 2)
718 abort ();
720 /* Remove trailing white spaces and }. */
723 i--;
724 if (ISSPACE (str[i]) || str[i] == '}')
725 str[i] = '\0';
726 else
727 break;
729 while (i != 0);
731 last = str + i;
733 /* Find operand_types. */
734 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
736 if (str >= last)
738 operand_types [i] = NULL;
739 break;
742 operand_types [i] = next_field (str, ',', &str);
743 if (*operand_types[i] == '0')
745 if (i != 0)
746 operand_types[i] = NULL;
747 break;
751 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
752 name, operands, base_opcode, extension_opcode,
753 opcode_length);
755 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
757 process_i386_opcode_modifier (table, opcode_modifier);
759 fprintf (table, " { ");
761 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
763 if (operand_types[i] == NULL
764 || *operand_types[i] == '0')
766 if (i == 0)
767 process_i386_operand_type (table, "0", 0, "\t ");
768 break;
771 if (i != 0)
772 fprintf (table, ",\n ");
774 process_i386_operand_type (table, operand_types[i], 0,
775 "\t ");
777 fprintf (table, " } },\n");
780 fclose (fp);
782 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
784 process_i386_cpu_flag (table, "0", 0, ",", " ");
786 process_i386_opcode_modifier (table, "0");
788 fprintf (table, " { ");
789 process_i386_operand_type (table, "0", 0, "\t ");
790 fprintf (table, " } }\n");
792 fprintf (table, "};\n");
795 static void
796 process_i386_registers (FILE *table)
798 FILE *fp;
799 char buf[2048];
800 char *str, *p, *last;
801 char *reg_name, *reg_type, *reg_flags, *reg_num;
803 filename = "i386-reg.tbl";
804 fp = fopen (filename, "r");
805 if (fp == NULL)
806 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
807 xstrerror (errno));
809 fprintf (table, "\n/* i386 register table. */\n\n");
810 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
812 while (!feof (fp))
814 if (fgets (buf, sizeof (buf), fp) == NULL)
815 break;
817 lineno++;
819 p = remove_leading_whitespaces (buf);
821 /* Skip comments. */
822 str = strstr (p, "//");
823 if (str != NULL)
824 str[0] = '\0';
826 /* Remove trailing white spaces. */
827 remove_trailing_whitespaces (p);
829 switch (p[0])
831 case '#':
832 fprintf (table, "%s\n", p);
833 case '\0':
834 continue;
835 break;
836 default:
837 break;
840 last = p + strlen (p);
842 /* Find reg_name. */
843 reg_name = next_field (p, ',', &str);
845 if (str >= last)
846 abort ();
848 /* Find reg_type. */
849 reg_type = next_field (str, ',', &str);
851 if (str >= last)
852 abort ();
854 /* Find reg_flags. */
855 reg_flags = next_field (str, ',', &str);
857 if (str >= last)
858 abort ();
860 /* Find reg_num. */
861 reg_num = next_field (str, ',', &str);
863 fprintf (table, " { \"%s\",\n ", reg_name);
865 process_i386_operand_type (table, reg_type, 0, "\t");
867 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
870 fclose (fp);
872 fprintf (table, "};\n");
874 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
877 static void
878 process_i386_initializers (void)
880 unsigned int i;
881 FILE *fp = fopen ("i386-init.h", "w");
882 char *init;
884 if (fp == NULL)
885 fail (_("can't create i386-init.h, errno = %s\n"),
886 xstrerror (errno));
888 process_copyright (fp);
890 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
892 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
893 init = xstrdup (cpu_flag_init[i].init);
894 process_i386_cpu_flag (fp, init, 1, "", " ");
895 free (init);
898 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
900 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
901 init = xstrdup (operand_type_init[i].init);
902 process_i386_operand_type (fp, init, 1, " ");
903 free (init);
905 fprintf (fp, "\n");
907 fclose (fp);
910 /* Program options. */
911 #define OPTION_SRCDIR 200
913 struct option long_options[] =
915 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
916 {"debug", no_argument, NULL, 'd'},
917 {"version", no_argument, NULL, 'V'},
918 {"help", no_argument, NULL, 'h'},
919 {0, no_argument, NULL, 0}
922 static void
923 print_version (void)
925 printf ("%s: version 1.0\n", program_name);
926 xexit (0);
929 static void
930 usage (FILE * stream, int status)
932 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
933 program_name);
934 xexit (status);
938 main (int argc, char **argv)
940 extern int chdir (char *);
941 char *srcdir = NULL;
942 int c;
943 FILE *table;
945 program_name = *argv;
946 xmalloc_set_program_name (program_name);
948 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
949 switch (c)
951 case OPTION_SRCDIR:
952 srcdir = optarg;
953 break;
954 case 'V':
955 case 'v':
956 print_version ();
957 break;
958 case 'd':
959 debug = 1;
960 break;
961 case 'h':
962 case '?':
963 usage (stderr, 0);
964 default:
965 case 0:
966 break;
969 if (optind != argc)
970 usage (stdout, 1);
972 if (srcdir != NULL)
973 if (chdir (srcdir) != 0)
974 fail (_("unable to change directory to \"%s\", errno = %s\n"),
975 srcdir, xstrerror (errno));
977 /* Check the unused bitfield in i386_cpu_flags. */
978 #ifndef CpuUnused
979 c = CpuNumOfBits - CpuMax - 1;
980 if (c)
981 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
982 #endif
984 /* Check the unused bitfield in i386_operand_type. */
985 #ifndef OTUnused
986 c = OTNumOfBits - OTMax - 1;
987 if (c)
988 fail (_("%d unused bits in i386_operand_type.\n"), c);
989 #endif
991 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
992 compare);
994 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
995 sizeof (opcode_modifiers [0]), compare);
997 qsort (operand_types, ARRAY_SIZE (operand_types),
998 sizeof (operand_types [0]), compare);
1000 table = fopen ("i386-tbl.h", "w");
1001 if (table == NULL)
1002 fail (_("can't create i386-tbl.h, errno = %s\n"),
1003 xstrerror (errno));
1005 process_copyright (table);
1007 process_i386_opcodes (table);
1008 process_i386_registers (table);
1009 process_i386_initializers ();
1011 fclose (table);
1013 exit (0);