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