2008-01-08 H.J. Lu <hongjiu.lu@intel.com>
[binutils-gdb.git] / opcodes / i386-gen.c
1 /* Copyright 2007, 2008 Free Software Foundation, Inc.
2
3 This file is part of the GNU opcodes library.
4
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.
9
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.
14
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. */
19
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"
26
27 #include "i386-opc.h"
28
29 #include <libintl.h>
30 #define _(String) gettext (String)
31
32 static const char *program_name = NULL;
33 static int debug = 0;
34
35 typedef struct initializer
36 {
37 const char *name;
38 const char *init;
39 } initializer;
40
41 static initializer cpu_flag_init [] =
42 {
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"},
113 };
114
115 static initializer operand_type_init [] =
116 {
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" },
205 };
206
207 typedef struct bitfield
208 {
209 int position;
210 int value;
211 const char *name;
212 } bitfield;
213
214 #define BITFIELD(n) { n, 0, #n }
215
216 static bitfield cpu_flags[] =
217 {
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
250 };
251
252 static bitfield opcode_modifiers[] =
253 {
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 (CheckSize),
277 BITFIELD (Byte),
278 BITFIELD (Word),
279 BITFIELD (Dword),
280 BITFIELD (Qword),
281 BITFIELD (Xmmword),
282 BITFIELD (FWait),
283 BITFIELD (IsString),
284 BITFIELD (RegKludge),
285 BITFIELD (FirstXmm0),
286 BITFIELD (ByteOkIntel),
287 BITFIELD (ToDword),
288 BITFIELD (ToQword),
289 BITFIELD (AddrPrefixOp0),
290 BITFIELD (IsPrefix),
291 BITFIELD (ImmExt),
292 BITFIELD (NoRex64),
293 BITFIELD (Rex64),
294 BITFIELD (Ugh),
295 BITFIELD (Drex),
296 BITFIELD (Drexv),
297 BITFIELD (Drexc),
298 BITFIELD (OldGcc),
299 BITFIELD (ATTMnemonic),
300 BITFIELD (ATTSyntax),
301 };
302
303 static bitfield operand_types[] =
304 {
305 BITFIELD (Reg8),
306 BITFIELD (Reg16),
307 BITFIELD (Reg32),
308 BITFIELD (Reg64),
309 BITFIELD (FloatReg),
310 BITFIELD (RegMMX),
311 BITFIELD (RegXMM),
312 BITFIELD (Imm8),
313 BITFIELD (Imm8S),
314 BITFIELD (Imm16),
315 BITFIELD (Imm32),
316 BITFIELD (Imm32S),
317 BITFIELD (Imm64),
318 BITFIELD (Imm1),
319 BITFIELD (BaseIndex),
320 BITFIELD (Disp8),
321 BITFIELD (Disp16),
322 BITFIELD (Disp32),
323 BITFIELD (Disp32S),
324 BITFIELD (Disp64),
325 BITFIELD (InOutPortReg),
326 BITFIELD (ShiftCount),
327 BITFIELD (Control),
328 BITFIELD (Debug),
329 BITFIELD (Test),
330 BITFIELD (SReg2),
331 BITFIELD (SReg3),
332 BITFIELD (Acc),
333 BITFIELD (FloatAcc),
334 BITFIELD (JumpAbsolute),
335 BITFIELD (EsSeg),
336 BITFIELD (RegMem),
337 #ifdef OTUnused
338 BITFIELD (OTUnused),
339 #endif
340 };
341
342 static int lineno;
343 static const char *filename;
344
345 static int
346 compare (const void *x, const void *y)
347 {
348 const bitfield *xp = (const bitfield *) x;
349 const bitfield *yp = (const bitfield *) y;
350 return xp->position - yp->position;
351 }
352
353 static void
354 fail (const char *message, ...)
355 {
356 va_list args;
357
358 va_start (args, message);
359 fprintf (stderr, _("%s: Error: "), program_name);
360 vfprintf (stderr, message, args);
361 va_end (args);
362 xexit (1);
363 }
364
365 static void
366 process_copyright (FILE *fp)
367 {
368 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
369 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
370 \n\
371 This file is part of the GNU opcodes library.\n\
372 \n\
373 This library is free software; you can redistribute it and/or modify\n\
374 it under the terms of the GNU General Public License as published by\n\
375 the Free Software Foundation; either version 3, or (at your option)\n\
376 any later version.\n\
377 \n\
378 It is distributed in the hope that it will be useful, but WITHOUT\n\
379 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
380 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
381 License for more details.\n\
382 \n\
383 You should have received a copy of the GNU General Public License\n\
384 along with this program; if not, write to the Free Software\n\
385 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
386 MA 02110-1301, USA. */\n");
387 }
388
389 /* Remove leading white spaces. */
390
391 static char *
392 remove_leading_whitespaces (char *str)
393 {
394 while (ISSPACE (*str))
395 str++;
396 return str;
397 }
398
399 /* Remove trailing white spaces. */
400
401 static void
402 remove_trailing_whitespaces (char *str)
403 {
404 size_t last = strlen (str);
405
406 if (last == 0)
407 return;
408
409 do
410 {
411 last--;
412 if (ISSPACE (str [last]))
413 str[last] = '\0';
414 else
415 break;
416 }
417 while (last != 0);
418 }
419
420 /* Find next field separated by SEP and terminate it. Return a
421 pointer to the one after it. */
422
423 static char *
424 next_field (char *str, char sep, char **next)
425 {
426 char *p;
427
428 p = remove_leading_whitespaces (str);
429 for (str = p; *str != sep && *str != '\0'; str++);
430
431 *str = '\0';
432 remove_trailing_whitespaces (p);
433
434 *next = str + 1;
435
436 return p;
437 }
438
439 static void
440 set_bitfield (const char *f, bitfield *array, unsigned int size)
441 {
442 unsigned int i;
443
444 if (strcmp (f, "CpuSledgehammer") == 0)
445 f= "CpuK8";
446
447 for (i = 0; i < size; i++)
448 if (strcasecmp (array[i].name, f) == 0)
449 {
450 array[i].value = 1;
451 return;
452 }
453
454 printf ("%s: %d: Unknown bitfield: %s\n",
455 filename, lineno, f);
456 abort ();
457 }
458
459 static void
460 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
461 int macro, const char *comma, const char *indent)
462 {
463 unsigned int i;
464
465 fprintf (table, "%s{ { ", indent);
466
467 for (i = 0; i < size - 1; i++)
468 {
469 fprintf (table, "%d, ", flags[i].value);
470 if (((i + 1) % 20) == 0)
471 {
472 /* We need \\ for macro. */
473 if (macro)
474 fprintf (table, " \\\n %s", indent);
475 else
476 fprintf (table, "\n %s", indent);
477 }
478 }
479
480 fprintf (table, "%d } }%s\n", flags[i].value, comma);
481 }
482
483 static void
484 process_i386_cpu_flag (FILE *table, char *flag, int macro,
485 const char *comma, const char *indent)
486 {
487 char *str, *next, *last;
488 bitfield flags [ARRAY_SIZE (cpu_flags)];
489
490 /* Copy the default cpu flags. */
491 memcpy (flags, cpu_flags, sizeof (cpu_flags));
492
493 if (strcasecmp (flag, "unknown") == 0)
494 {
495 unsigned int i;
496
497 /* We turn on everything except for cpu64 in case of
498 CPU_UNKNOWN_FLAGS. */
499 for (i = 0; i < ARRAY_SIZE (flags); i++)
500 if (flags[i].position != Cpu64)
501 flags[i].value = 1;
502 }
503 else if (strcmp (flag, "0"))
504 {
505 last = flag + strlen (flag);
506 for (next = flag; next && next < last; )
507 {
508 str = next_field (next, '|', &next);
509 if (str)
510 set_bitfield (str, flags, ARRAY_SIZE (flags));
511 }
512 }
513
514 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
515 comma, indent);
516 }
517
518 static void
519 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
520 {
521 unsigned int i;
522
523 fprintf (table, " { ");
524
525 for (i = 0; i < size - 1; i++)
526 {
527 fprintf (table, "%d, ", modifier[i].value);
528 if (((i + 1) % 20) == 0)
529 fprintf (table, "\n ");
530 }
531
532 fprintf (table, "%d },\n", modifier[i].value);
533 }
534
535 static void
536 process_i386_opcode_modifier (FILE *table, char *mod)
537 {
538 char *str, *next, *last;
539 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
540
541 /* Copy the default opcode modifier. */
542 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
543
544 if (strcmp (mod, "0"))
545 {
546 last = mod + strlen (mod);
547 for (next = mod; next && next < last; )
548 {
549 str = next_field (next, '|', &next);
550 if (str)
551 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
552 }
553 }
554 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
555 }
556
557 static void
558 output_operand_type (FILE *table, bitfield *types, unsigned int size,
559 int macro, const char *indent)
560 {
561 unsigned int i;
562
563 fprintf (table, "{ { ");
564
565 for (i = 0; i < size - 1; i++)
566 {
567 fprintf (table, "%d, ", types[i].value);
568 if (((i + 1) % 20) == 0)
569 {
570 /* We need \\ for macro. */
571 if (macro)
572 fprintf (table, "\\\n%s", indent);
573 else
574 fprintf (table, "\n%s", indent);
575 }
576 }
577
578 fprintf (table, "%d } }", types[i].value);
579 }
580
581 static void
582 process_i386_operand_type (FILE *table, char *op, int macro,
583 const char *indent)
584 {
585 char *str, *next, *last;
586 bitfield types [ARRAY_SIZE (operand_types)];
587
588 /* Copy the default operand type. */
589 memcpy (types, operand_types, sizeof (types));
590
591 if (strcmp (op, "0"))
592 {
593 last = op + strlen (op);
594 for (next = op; next && next < last; )
595 {
596 str = next_field (next, '|', &next);
597 if (str)
598 set_bitfield (str, types, ARRAY_SIZE (types));
599 }
600 }
601 output_operand_type (table, types, ARRAY_SIZE (types), macro,
602 indent);
603 }
604
605 static void
606 process_i386_opcodes (FILE *table)
607 {
608 FILE *fp;
609 char buf[2048];
610 unsigned int i;
611 char *str, *p, *last;
612 char *name, *operands, *base_opcode, *extension_opcode;
613 char *opcode_length;
614 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
615
616 filename = "i386-opc.tbl";
617 fp = fopen (filename, "r");
618
619 if (fp == NULL)
620 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
621 xstrerror (errno));
622
623 fprintf (table, "\n/* i386 opcode table. */\n\n");
624 fprintf (table, "const template i386_optab[] =\n{\n");
625
626 while (!feof (fp))
627 {
628 if (fgets (buf, sizeof (buf), fp) == NULL)
629 break;
630
631 lineno++;
632
633 p = remove_leading_whitespaces (buf);
634
635 /* Skip comments. */
636 str = strstr (p, "//");
637 if (str != NULL)
638 str[0] = '\0';
639
640 /* Remove trailing white spaces. */
641 remove_trailing_whitespaces (p);
642
643 switch (p[0])
644 {
645 case '#':
646 fprintf (table, "%s\n", p);
647 case '\0':
648 continue;
649 break;
650 default:
651 break;
652 }
653
654 last = p + strlen (p);
655
656 /* Find name. */
657 name = next_field (p, ',', &str);
658
659 if (str >= last)
660 abort ();
661
662 /* Find number of operands. */
663 operands = next_field (str, ',', &str);
664
665 if (str >= last)
666 abort ();
667
668 /* Find base_opcode. */
669 base_opcode = next_field (str, ',', &str);
670
671 if (str >= last)
672 abort ();
673
674 /* Find extension_opcode. */
675 extension_opcode = next_field (str, ',', &str);
676
677 if (str >= last)
678 abort ();
679
680 /* Find opcode_length. */
681 opcode_length = next_field (str, ',', &str);
682
683 if (str >= last)
684 abort ();
685
686 /* Find cpu_flags. */
687 cpu_flags = next_field (str, ',', &str);
688
689 if (str >= last)
690 abort ();
691
692 /* Find opcode_modifier. */
693 opcode_modifier = next_field (str, ',', &str);
694
695 if (str >= last)
696 abort ();
697
698 /* Remove the first {. */
699 str = remove_leading_whitespaces (str);
700 if (*str != '{')
701 abort ();
702 str = remove_leading_whitespaces (str + 1);
703
704 i = strlen (str);
705
706 /* There are at least "X}". */
707 if (i < 2)
708 abort ();
709
710 /* Remove trailing white spaces and }. */
711 do
712 {
713 i--;
714 if (ISSPACE (str[i]) || str[i] == '}')
715 str[i] = '\0';
716 else
717 break;
718 }
719 while (i != 0);
720
721 last = str + i;
722
723 /* Find operand_types. */
724 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
725 {
726 if (str >= last)
727 {
728 operand_types [i] = NULL;
729 break;
730 }
731
732 operand_types [i] = next_field (str, ',', &str);
733 if (*operand_types[i] == '0')
734 {
735 if (i != 0)
736 operand_types[i] = NULL;
737 break;
738 }
739 }
740
741 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
742 name, operands, base_opcode, extension_opcode,
743 opcode_length);
744
745 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
746
747 process_i386_opcode_modifier (table, opcode_modifier);
748
749 fprintf (table, " { ");
750
751 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
752 {
753 if (operand_types[i] == NULL
754 || *operand_types[i] == '0')
755 {
756 if (i == 0)
757 process_i386_operand_type (table, "0", 0, "\t ");
758 break;
759 }
760
761 if (i != 0)
762 fprintf (table, ",\n ");
763
764 process_i386_operand_type (table, operand_types[i], 0,
765 "\t ");
766 }
767 fprintf (table, " } },\n");
768 }
769
770 fclose (fp);
771
772 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
773
774 process_i386_cpu_flag (table, "0", 0, ",", " ");
775
776 process_i386_opcode_modifier (table, "0");
777
778 fprintf (table, " { ");
779 process_i386_operand_type (table, "0", 0, "\t ");
780 fprintf (table, " } }\n");
781
782 fprintf (table, "};\n");
783 }
784
785 static void
786 process_i386_registers (FILE *table)
787 {
788 FILE *fp;
789 char buf[2048];
790 char *str, *p, *last;
791 char *reg_name, *reg_type, *reg_flags, *reg_num;
792
793 filename = "i386-reg.tbl";
794 fp = fopen (filename, "r");
795 if (fp == NULL)
796 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
797 xstrerror (errno));
798
799 fprintf (table, "\n/* i386 register table. */\n\n");
800 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
801
802 while (!feof (fp))
803 {
804 if (fgets (buf, sizeof (buf), fp) == NULL)
805 break;
806
807 lineno++;
808
809 p = remove_leading_whitespaces (buf);
810
811 /* Skip comments. */
812 str = strstr (p, "//");
813 if (str != NULL)
814 str[0] = '\0';
815
816 /* Remove trailing white spaces. */
817 remove_trailing_whitespaces (p);
818
819 switch (p[0])
820 {
821 case '#':
822 fprintf (table, "%s\n", p);
823 case '\0':
824 continue;
825 break;
826 default:
827 break;
828 }
829
830 last = p + strlen (p);
831
832 /* Find reg_name. */
833 reg_name = next_field (p, ',', &str);
834
835 if (str >= last)
836 abort ();
837
838 /* Find reg_type. */
839 reg_type = next_field (str, ',', &str);
840
841 if (str >= last)
842 abort ();
843
844 /* Find reg_flags. */
845 reg_flags = next_field (str, ',', &str);
846
847 if (str >= last)
848 abort ();
849
850 /* Find reg_num. */
851 reg_num = next_field (str, ',', &str);
852
853 fprintf (table, " { \"%s\",\n ", reg_name);
854
855 process_i386_operand_type (table, reg_type, 0, "\t");
856
857 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
858 }
859
860 fclose (fp);
861
862 fprintf (table, "};\n");
863
864 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
865 }
866
867 static void
868 process_i386_initializers (void)
869 {
870 unsigned int i;
871 FILE *fp = fopen ("i386-init.h", "w");
872 char *init;
873
874 if (fp == NULL)
875 fail (_("can't create i386-init.h, errno = %s\n"),
876 xstrerror (errno));
877
878 process_copyright (fp);
879
880 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
881 {
882 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
883 init = xstrdup (cpu_flag_init[i].init);
884 process_i386_cpu_flag (fp, init, 1, "", " ");
885 free (init);
886 }
887
888 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
889 {
890 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
891 init = xstrdup (operand_type_init[i].init);
892 process_i386_operand_type (fp, init, 1, " ");
893 free (init);
894 }
895 fprintf (fp, "\n");
896
897 fclose (fp);
898 }
899
900 /* Program options. */
901 #define OPTION_SRCDIR 200
902
903 struct option long_options[] =
904 {
905 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
906 {"debug", no_argument, NULL, 'd'},
907 {"version", no_argument, NULL, 'V'},
908 {"help", no_argument, NULL, 'h'},
909 {0, no_argument, NULL, 0}
910 };
911
912 static void
913 print_version (void)
914 {
915 printf ("%s: version 1.0\n", program_name);
916 xexit (0);
917 }
918
919 static void
920 usage (FILE * stream, int status)
921 {
922 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
923 program_name);
924 xexit (status);
925 }
926
927 int
928 main (int argc, char **argv)
929 {
930 extern int chdir (char *);
931 char *srcdir = NULL;
932 int c;
933 FILE *table;
934
935 program_name = *argv;
936 xmalloc_set_program_name (program_name);
937
938 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
939 switch (c)
940 {
941 case OPTION_SRCDIR:
942 srcdir = optarg;
943 break;
944 case 'V':
945 case 'v':
946 print_version ();
947 break;
948 case 'd':
949 debug = 1;
950 break;
951 case 'h':
952 case '?':
953 usage (stderr, 0);
954 default:
955 case 0:
956 break;
957 }
958
959 if (optind != argc)
960 usage (stdout, 1);
961
962 if (srcdir != NULL)
963 if (chdir (srcdir) != 0)
964 fail (_("unable to change directory to \"%s\", errno = %s\n"),
965 srcdir, xstrerror (errno));
966
967 /* Check the unused bitfield in i386_cpu_flags. */
968 #ifndef CpuUnused
969 c = CpuNumOfBits - CpuMax - 1;
970 if (c)
971 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
972 #endif
973
974 /* Check the unused bitfield in i386_operand_type. */
975 #ifndef OTUnused
976 c = OTNumOfBits - OTMax - 1;
977 if (c)
978 fail (_("%d unused bits in i386_operand_type.\n"), c);
979 #endif
980
981 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
982 compare);
983
984 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
985 sizeof (opcode_modifiers [0]), compare);
986
987 qsort (operand_types, ARRAY_SIZE (operand_types),
988 sizeof (operand_types [0]), compare);
989
990 table = fopen ("i386-tbl.h", "w");
991 if (table == NULL)
992 fail (_("can't create i386-tbl.h, errno = %s\n"),
993 xstrerror (errno));
994
995 process_copyright (table);
996
997 process_i386_opcodes (table);
998 process_i386_registers (table);
999 process_i386_initializers ();
1000
1001 fclose (table);
1002
1003 exit (0);
1004 }