* config/tc-ppc.c (md_apply_fix): For PPC_TOC16 on XCOFF, uses offset
[binutils.git] / opcodes / i386-gen.c
blobd3ca2a379aed196942bb42aa6ee831439e0eb13f
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_ldSuf),
276 BITFIELD (FWait),
277 BITFIELD (IsString),
278 BITFIELD (RegKludge),
279 BITFIELD (FirstXmm0),
280 BITFIELD (ByteOkIntel),
281 BITFIELD (ToDword),
282 BITFIELD (ToQword),
283 BITFIELD (AddrPrefixOp0),
284 BITFIELD (IsPrefix),
285 BITFIELD (ImmExt),
286 BITFIELD (NoRex64),
287 BITFIELD (Rex64),
288 BITFIELD (Ugh),
289 BITFIELD (Drex),
290 BITFIELD (Drexv),
291 BITFIELD (Drexc),
294 static bitfield operand_types[] =
296 BITFIELD (Reg8),
297 BITFIELD (Reg16),
298 BITFIELD (Reg32),
299 BITFIELD (Reg64),
300 BITFIELD (FloatReg),
301 BITFIELD (RegMMX),
302 BITFIELD (RegXMM),
303 BITFIELD (Imm8),
304 BITFIELD (Imm8S),
305 BITFIELD (Imm16),
306 BITFIELD (Imm32),
307 BITFIELD (Imm32S),
308 BITFIELD (Imm64),
309 BITFIELD (Imm1),
310 BITFIELD (BaseIndex),
311 BITFIELD (Disp8),
312 BITFIELD (Disp16),
313 BITFIELD (Disp32),
314 BITFIELD (Disp32S),
315 BITFIELD (Disp64),
316 BITFIELD (InOutPortReg),
317 BITFIELD (ShiftCount),
318 BITFIELD (Control),
319 BITFIELD (Debug),
320 BITFIELD (Test),
321 BITFIELD (SReg2),
322 BITFIELD (SReg3),
323 BITFIELD (Acc),
324 BITFIELD (FloatAcc),
325 BITFIELD (JumpAbsolute),
326 BITFIELD (EsSeg),
327 BITFIELD (RegMem),
328 #ifdef OTUnused
329 BITFIELD (OTUnused),
330 #endif
333 static int
334 compare (const void *x, const void *y)
336 const bitfield *xp = (const bitfield *) x;
337 const bitfield *yp = (const bitfield *) y;
338 return xp->position - yp->position;
341 static void
342 fail (const char *message, ...)
344 va_list args;
346 va_start (args, message);
347 fprintf (stderr, _("%s: Error: "), program_name);
348 vfprintf (stderr, message, args);
349 va_end (args);
350 xexit (1);
353 static void
354 process_copyright (FILE *fp)
356 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
357 /* Copyright 2007 Free Software Foundation, Inc.\n\
359 This file is part of the GNU opcodes library.\n\
361 This library is free software; you can redistribute it and/or modify\n\
362 it under the terms of the GNU General Public License as published by\n\
363 the Free Software Foundation; either version 3, or (at your option)\n\
364 any later version.\n\
366 It is distributed in the hope that it will be useful, but WITHOUT\n\
367 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
368 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
369 License for more details.\n\
371 You should have received a copy of the GNU General Public License\n\
372 along with this program; if not, write to the Free Software\n\
373 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
374 MA 02110-1301, USA. */\n");
377 /* Remove leading white spaces. */
379 static char *
380 remove_leading_whitespaces (char *str)
382 while (ISSPACE (*str))
383 str++;
384 return str;
387 /* Remove trailing white spaces. */
389 static void
390 remove_trailing_whitespaces (char *str)
392 size_t last = strlen (str);
394 if (last == 0)
395 return;
399 last--;
400 if (ISSPACE (str [last]))
401 str[last] = '\0';
402 else
403 break;
405 while (last != 0);
408 /* Find next field separated by SEP and terminate it. Return a
409 pointer to the one after it. */
411 static char *
412 next_field (char *str, char sep, char **next)
414 char *p;
416 p = remove_leading_whitespaces (str);
417 for (str = p; *str != sep && *str != '\0'; str++);
419 *str = '\0';
420 remove_trailing_whitespaces (p);
422 *next = str + 1;
424 return p;
427 static void
428 set_bitfield (const char *f, bitfield *array, unsigned int size)
430 unsigned int i;
432 if (strcmp (f, "CpuSledgehammer") == 0)
433 f= "CpuK8";
435 for (i = 0; i < size; i++)
436 if (strcasecmp (array[i].name, f) == 0)
438 array[i].value = 1;
439 return;
442 printf ("Unknown bitfield: %s\n", f);
443 abort ();
446 static void
447 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
448 int macro, const char *comma, const char *indent)
450 unsigned int i;
452 fprintf (table, "%s{ { ", indent);
454 for (i = 0; i < size - 1; i++)
456 fprintf (table, "%d, ", flags[i].value);
457 if (((i + 1) % 20) == 0)
459 /* We need \\ for macro. */
460 if (macro)
461 fprintf (table, " \\\n %s", indent);
462 else
463 fprintf (table, "\n %s", indent);
467 fprintf (table, "%d } }%s\n", flags[i].value, comma);
470 static void
471 process_i386_cpu_flag (FILE *table, char *flag, int macro,
472 const char *comma, const char *indent)
474 char *str, *next, *last;
475 bitfield flags [ARRAY_SIZE (cpu_flags)];
477 /* Copy the default cpu flags. */
478 memcpy (flags, cpu_flags, sizeof (cpu_flags));
480 if (strcasecmp (flag, "unknown") == 0)
482 unsigned int i;
484 /* We turn on everything except for cpu64 in case of
485 CPU_UNKNOWN_FLAGS. */
486 for (i = 0; i < ARRAY_SIZE (flags); i++)
487 if (flags[i].position != Cpu64)
488 flags[i].value = 1;
490 else if (strcmp (flag, "0"))
492 last = flag + strlen (flag);
493 for (next = flag; next && next < last; )
495 str = next_field (next, '|', &next);
496 if (str)
497 set_bitfield (str, flags, ARRAY_SIZE (flags));
501 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
502 comma, indent);
505 static void
506 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
508 unsigned int i;
510 fprintf (table, " { ");
512 for (i = 0; i < size - 1; i++)
514 fprintf (table, "%d, ", modifier[i].value);
515 if (((i + 1) % 20) == 0)
516 fprintf (table, "\n ");
519 fprintf (table, "%d },\n", modifier[i].value);
522 static void
523 process_i386_opcode_modifier (FILE *table, char *mod)
525 char *str, *next, *last;
526 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
528 /* Copy the default opcode modifier. */
529 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
531 if (strcmp (mod, "0"))
533 last = mod + strlen (mod);
534 for (next = mod; next && next < last; )
536 str = next_field (next, '|', &next);
537 if (str)
538 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
541 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
544 static void
545 output_operand_type (FILE *table, bitfield *types, unsigned int size,
546 int macro, const char *indent)
548 unsigned int i;
550 fprintf (table, "{ { ");
552 for (i = 0; i < size - 1; i++)
554 fprintf (table, "%d, ", types[i].value);
555 if (((i + 1) % 20) == 0)
557 /* We need \\ for macro. */
558 if (macro)
559 fprintf (table, "\\\n%s", indent);
560 else
561 fprintf (table, "\n%s", indent);
565 fprintf (table, "%d } }", types[i].value);
568 static void
569 process_i386_operand_type (FILE *table, char *op, int macro,
570 const char *indent)
572 char *str, *next, *last;
573 bitfield types [ARRAY_SIZE (operand_types)];
575 /* Copy the default operand type. */
576 memcpy (types, operand_types, sizeof (types));
578 if (strcmp (op, "0"))
580 last = op + strlen (op);
581 for (next = op; next && next < last; )
583 str = next_field (next, '|', &next);
584 if (str)
585 set_bitfield (str, types, ARRAY_SIZE (types));
588 output_operand_type (table, types, ARRAY_SIZE (types), macro,
589 indent);
592 static void
593 process_i386_opcodes (FILE *table)
595 FILE *fp = fopen ("i386-opc.tbl", "r");
596 char buf[2048];
597 unsigned int i;
598 char *str, *p, *last;
599 char *name, *operands, *base_opcode, *extension_opcode;
600 char *opcode_length;
601 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
603 if (fp == NULL)
604 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
605 xstrerror (errno));
607 fprintf (table, "\n/* i386 opcode table. */\n\n");
608 fprintf (table, "const template i386_optab[] =\n{\n");
610 while (!feof (fp))
612 if (fgets (buf, sizeof (buf), fp) == NULL)
613 break;
615 p = remove_leading_whitespaces (buf);
617 /* Skip comments. */
618 str = strstr (p, "//");
619 if (str != NULL)
620 str[0] = '\0';
622 /* Remove trailing white spaces. */
623 remove_trailing_whitespaces (p);
625 switch (p[0])
627 case '#':
628 fprintf (table, "%s\n", p);
629 case '\0':
630 continue;
631 break;
632 default:
633 break;
636 last = p + strlen (p);
638 /* Find name. */
639 name = next_field (p, ',', &str);
641 if (str >= last)
642 abort ();
644 /* Find number of operands. */
645 operands = next_field (str, ',', &str);
647 if (str >= last)
648 abort ();
650 /* Find base_opcode. */
651 base_opcode = next_field (str, ',', &str);
653 if (str >= last)
654 abort ();
656 /* Find extension_opcode. */
657 extension_opcode = next_field (str, ',', &str);
659 if (str >= last)
660 abort ();
662 /* Find opcode_length. */
663 opcode_length = next_field (str, ',', &str);
665 if (str >= last)
666 abort ();
668 /* Find cpu_flags. */
669 cpu_flags = next_field (str, ',', &str);
671 if (str >= last)
672 abort ();
674 /* Find opcode_modifier. */
675 opcode_modifier = next_field (str, ',', &str);
677 if (str >= last)
678 abort ();
680 /* Remove the first {. */
681 str = remove_leading_whitespaces (str);
682 if (*str != '{')
683 abort ();
684 str = remove_leading_whitespaces (str + 1);
686 i = strlen (str);
688 /* There are at least "X}". */
689 if (i < 2)
690 abort ();
692 /* Remove trailing white spaces and }. */
695 i--;
696 if (ISSPACE (str[i]) || str[i] == '}')
697 str[i] = '\0';
698 else
699 break;
701 while (i != 0);
703 last = str + i;
705 /* Find operand_types. */
706 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
708 if (str >= last)
710 operand_types [i] = NULL;
711 break;
714 operand_types [i] = next_field (str, ',', &str);
715 if (*operand_types[i] == '0')
717 if (i != 0)
718 operand_types[i] = NULL;
719 break;
723 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
724 name, operands, base_opcode, extension_opcode,
725 opcode_length);
727 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
729 process_i386_opcode_modifier (table, opcode_modifier);
731 fprintf (table, " { ");
733 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
735 if (operand_types[i] == NULL
736 || *operand_types[i] == '0')
738 if (i == 0)
739 process_i386_operand_type (table, "0", 0, "\t ");
740 break;
743 if (i != 0)
744 fprintf (table, ",\n ");
746 process_i386_operand_type (table, operand_types[i], 0,
747 "\t ");
749 fprintf (table, " } },\n");
752 fclose (fp);
754 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
756 process_i386_cpu_flag (table, "0", 0, ",", " ");
758 process_i386_opcode_modifier (table, "0");
760 fprintf (table, " { ");
761 process_i386_operand_type (table, "0", 0, "\t ");
762 fprintf (table, " } }\n");
764 fprintf (table, "};\n");
767 static void
768 process_i386_registers (FILE *table)
770 FILE *fp = fopen ("i386-reg.tbl", "r");
771 char buf[2048];
772 char *str, *p, *last;
773 char *reg_name, *reg_type, *reg_flags, *reg_num;
775 if (fp == NULL)
776 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
777 xstrerror (errno));
779 fprintf (table, "\n/* i386 register table. */\n\n");
780 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
782 while (!feof (fp))
784 if (fgets (buf, sizeof (buf), fp) == NULL)
785 break;
787 p = remove_leading_whitespaces (buf);
789 /* Skip comments. */
790 str = strstr (p, "//");
791 if (str != NULL)
792 str[0] = '\0';
794 /* Remove trailing white spaces. */
795 remove_trailing_whitespaces (p);
797 switch (p[0])
799 case '#':
800 fprintf (table, "%s\n", p);
801 case '\0':
802 continue;
803 break;
804 default:
805 break;
808 last = p + strlen (p);
810 /* Find reg_name. */
811 reg_name = next_field (p, ',', &str);
813 if (str >= last)
814 abort ();
816 /* Find reg_type. */
817 reg_type = next_field (str, ',', &str);
819 if (str >= last)
820 abort ();
822 /* Find reg_flags. */
823 reg_flags = next_field (str, ',', &str);
825 if (str >= last)
826 abort ();
828 /* Find reg_num. */
829 reg_num = next_field (str, ',', &str);
831 fprintf (table, " { \"%s\",\n ", reg_name);
833 process_i386_operand_type (table, reg_type, 0, "\t");
835 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
838 fclose (fp);
840 fprintf (table, "};\n");
842 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
845 static void
846 process_i386_initializers (void)
848 unsigned int i;
849 FILE *fp = fopen ("i386-init.h", "w");
850 char *init;
852 if (fp == NULL)
853 fail (_("can't create i386-init.h, errno = %s\n"),
854 xstrerror (errno));
856 process_copyright (fp);
858 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
860 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
861 init = xstrdup (cpu_flag_init[i].init);
862 process_i386_cpu_flag (fp, init, 1, "", " ");
863 free (init);
866 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
868 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
869 init = xstrdup (operand_type_init[i].init);
870 process_i386_operand_type (fp, init, 1, " ");
871 free (init);
873 fprintf (fp, "\n");
875 fclose (fp);
878 /* Program options. */
879 #define OPTION_SRCDIR 200
881 struct option long_options[] =
883 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
884 {"debug", no_argument, NULL, 'd'},
885 {"version", no_argument, NULL, 'V'},
886 {"help", no_argument, NULL, 'h'},
887 {0, no_argument, NULL, 0}
890 static void
891 print_version (void)
893 printf ("%s: version 1.0\n", program_name);
894 xexit (0);
897 static void
898 usage (FILE * stream, int status)
900 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
901 program_name);
902 xexit (status);
906 main (int argc, char **argv)
908 extern int chdir (char *);
909 char *srcdir = NULL;
910 int c;
911 FILE *table;
913 program_name = *argv;
914 xmalloc_set_program_name (program_name);
916 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
917 switch (c)
919 case OPTION_SRCDIR:
920 srcdir = optarg;
921 break;
922 case 'V':
923 case 'v':
924 print_version ();
925 break;
926 case 'd':
927 debug = 1;
928 break;
929 case 'h':
930 case '?':
931 usage (stderr, 0);
932 default:
933 case 0:
934 break;
937 if (optind != argc)
938 usage (stdout, 1);
940 if (srcdir != NULL)
941 if (chdir (srcdir) != 0)
942 fail (_("unable to change directory to \"%s\", errno = %s\n"),
943 srcdir, xstrerror (errno));
945 /* Check the unused bitfield in i386_cpu_flags. */
946 #ifndef CpuUnused
947 c = CpuNumOfBits - CpuMax - 1;
948 if (c)
949 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
950 #endif
952 /* Check the unused bitfield in i386_operand_type. */
953 #ifndef OTUnused
954 c = OTNumOfBits - OTMax - 1;
955 if (c)
956 fail (_("%d unused bits in i386_operand_type.\n"), c);
957 #endif
959 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
960 compare);
962 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
963 sizeof (opcode_modifiers [0]), compare);
965 qsort (operand_types, ARRAY_SIZE (operand_types),
966 sizeof (operand_types [0]), compare);
968 table = fopen ("i386-tbl.h", "w");
969 if (table == NULL)
970 fail (_("can't create i386-tbl.h, errno = %s\n"),
971 xstrerror (errno));
973 process_copyright (table);
975 process_i386_opcodes (table);
976 process_i386_registers (table);
977 process_i386_initializers ();
979 fclose (table);
981 exit (0);