PR 5233
[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_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),
292 };
293
294 static bitfield operand_types[] =
295 {
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
331 };
332
333 static int
334 compare (const void *x, const void *y)
335 {
336 const bitfield *xp = (const bitfield *) x;
337 const bitfield *yp = (const bitfield *) y;
338 return xp->position - yp->position;
339 }
340
341 static void
342 fail (const char *message, ...)
343 {
344 va_list args;
345
346 va_start (args, message);
347 fprintf (stderr, _("%s: Error: "), program_name);
348 vfprintf (stderr, message, args);
349 va_end (args);
350 xexit (1);
351 }
352
353 static void
354 process_copyright (FILE *fp)
355 {
356 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
357 /* Copyright 2007 Free Software Foundation, Inc.\n\
358 \n\
359 This file is part of the GNU opcodes library.\n\
360 \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\
365 \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\
370 \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");
375 }
376
377 /* Remove leading white spaces. */
378
379 static char *
380 remove_leading_whitespaces (char *str)
381 {
382 while (ISSPACE (*str))
383 str++;
384 return str;
385 }
386
387 /* Remove trailing white spaces. */
388
389 static void
390 remove_trailing_whitespaces (char *str)
391 {
392 size_t last = strlen (str);
393
394 if (last == 0)
395 return;
396
397 do
398 {
399 last--;
400 if (ISSPACE (str [last]))
401 str[last] = '\0';
402 else
403 break;
404 }
405 while (last != 0);
406 }
407
408 /* Find next field separated by SEP and terminate it. Return a
409 pointer to the one after it. */
410
411 static char *
412 next_field (char *str, char sep, char **next)
413 {
414 char *p;
415
416 p = remove_leading_whitespaces (str);
417 for (str = p; *str != sep && *str != '\0'; str++);
418
419 *str = '\0';
420 remove_trailing_whitespaces (p);
421
422 *next = str + 1;
423
424 return p;
425 }
426
427 static void
428 set_bitfield (const char *f, bitfield *array, unsigned int size)
429 {
430 unsigned int i;
431
432 if (strcmp (f, "CpuSledgehammer") == 0)
433 f= "CpuK8";
434
435 for (i = 0; i < size; i++)
436 if (strcasecmp (array[i].name, f) == 0)
437 {
438 array[i].value = 1;
439 return;
440 }
441
442 printf ("Unknown bitfield: %s\n", f);
443 abort ();
444 }
445
446 static void
447 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
448 int macro, const char *comma, const char *indent)
449 {
450 unsigned int i;
451
452 fprintf (table, "%s{ { ", indent);
453
454 for (i = 0; i < size - 1; i++)
455 {
456 fprintf (table, "%d, ", flags[i].value);
457 if (((i + 1) % 20) == 0)
458 {
459 /* We need \\ for macro. */
460 if (macro)
461 fprintf (table, " \\\n %s", indent);
462 else
463 fprintf (table, "\n %s", indent);
464 }
465 }
466
467 fprintf (table, "%d } }%s\n", flags[i].value, comma);
468 }
469
470 static void
471 process_i386_cpu_flag (FILE *table, char *flag, int macro,
472 const char *comma, const char *indent)
473 {
474 char *str, *next, *last;
475 bitfield flags [ARRAY_SIZE (cpu_flags)];
476
477 /* Copy the default cpu flags. */
478 memcpy (flags, cpu_flags, sizeof (cpu_flags));
479
480 if (strcasecmp (flag, "unknown") == 0)
481 {
482 unsigned int i;
483
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;
489 }
490 else if (strcmp (flag, "0"))
491 {
492 last = flag + strlen (flag);
493 for (next = flag; next && next < last; )
494 {
495 str = next_field (next, '|', &next);
496 if (str)
497 set_bitfield (str, flags, ARRAY_SIZE (flags));
498 }
499 }
500
501 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
502 comma, indent);
503 }
504
505 static void
506 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
507 {
508 unsigned int i;
509
510 fprintf (table, " { ");
511
512 for (i = 0; i < size - 1; i++)
513 {
514 fprintf (table, "%d, ", modifier[i].value);
515 if (((i + 1) % 20) == 0)
516 fprintf (table, "\n ");
517 }
518
519 fprintf (table, "%d },\n", modifier[i].value);
520 }
521
522 static void
523 process_i386_opcode_modifier (FILE *table, char *mod)
524 {
525 char *str, *next, *last;
526 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
527
528 /* Copy the default opcode modifier. */
529 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
530
531 if (strcmp (mod, "0"))
532 {
533 last = mod + strlen (mod);
534 for (next = mod; next && next < last; )
535 {
536 str = next_field (next, '|', &next);
537 if (str)
538 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
539 }
540 }
541 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
542 }
543
544 static void
545 output_operand_type (FILE *table, bitfield *types, unsigned int size,
546 int macro, const char *indent)
547 {
548 unsigned int i;
549
550 fprintf (table, "{ { ");
551
552 for (i = 0; i < size - 1; i++)
553 {
554 fprintf (table, "%d, ", types[i].value);
555 if (((i + 1) % 20) == 0)
556 {
557 /* We need \\ for macro. */
558 if (macro)
559 fprintf (table, "\\\n%s", indent);
560 else
561 fprintf (table, "\n%s", indent);
562 }
563 }
564
565 fprintf (table, "%d } }", types[i].value);
566 }
567
568 static void
569 process_i386_operand_type (FILE *table, char *op, int macro,
570 const char *indent)
571 {
572 char *str, *next, *last;
573 bitfield types [ARRAY_SIZE (operand_types)];
574
575 /* Copy the default operand type. */
576 memcpy (types, operand_types, sizeof (types));
577
578 if (strcmp (op, "0"))
579 {
580 last = op + strlen (op);
581 for (next = op; next && next < last; )
582 {
583 str = next_field (next, '|', &next);
584 if (str)
585 set_bitfield (str, types, ARRAY_SIZE (types));
586 }
587 }
588 output_operand_type (table, types, ARRAY_SIZE (types), macro,
589 indent);
590 }
591
592 static void
593 process_i386_opcodes (FILE *table)
594 {
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];
602
603 if (fp == NULL)
604 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
605 xstrerror (errno));
606
607 fprintf (table, "\n/* i386 opcode table. */\n\n");
608 fprintf (table, "const template i386_optab[] =\n{\n");
609
610 while (!feof (fp))
611 {
612 if (fgets (buf, sizeof (buf), fp) == NULL)
613 break;
614
615 p = remove_leading_whitespaces (buf);
616
617 /* Skip comments. */
618 str = strstr (p, "//");
619 if (str != NULL)
620 str[0] = '\0';
621
622 /* Remove trailing white spaces. */
623 remove_trailing_whitespaces (p);
624
625 switch (p[0])
626 {
627 case '#':
628 fprintf (table, "%s\n", p);
629 case '\0':
630 continue;
631 break;
632 default:
633 break;
634 }
635
636 last = p + strlen (p);
637
638 /* Find name. */
639 name = next_field (p, ',', &str);
640
641 if (str >= last)
642 abort ();
643
644 /* Find number of operands. */
645 operands = next_field (str, ',', &str);
646
647 if (str >= last)
648 abort ();
649
650 /* Find base_opcode. */
651 base_opcode = next_field (str, ',', &str);
652
653 if (str >= last)
654 abort ();
655
656 /* Find extension_opcode. */
657 extension_opcode = next_field (str, ',', &str);
658
659 if (str >= last)
660 abort ();
661
662 /* Find opcode_length. */
663 opcode_length = next_field (str, ',', &str);
664
665 if (str >= last)
666 abort ();
667
668 /* Find cpu_flags. */
669 cpu_flags = next_field (str, ',', &str);
670
671 if (str >= last)
672 abort ();
673
674 /* Find opcode_modifier. */
675 opcode_modifier = next_field (str, ',', &str);
676
677 if (str >= last)
678 abort ();
679
680 /* Remove the first {. */
681 str = remove_leading_whitespaces (str);
682 if (*str != '{')
683 abort ();
684 str = remove_leading_whitespaces (str + 1);
685
686 i = strlen (str);
687
688 /* There are at least "X}". */
689 if (i < 2)
690 abort ();
691
692 /* Remove trailing white spaces and }. */
693 do
694 {
695 i--;
696 if (ISSPACE (str[i]) || str[i] == '}')
697 str[i] = '\0';
698 else
699 break;
700 }
701 while (i != 0);
702
703 last = str + i;
704
705 /* Find operand_types. */
706 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
707 {
708 if (str >= last)
709 {
710 operand_types [i] = NULL;
711 break;
712 }
713
714 operand_types [i] = next_field (str, ',', &str);
715 if (*operand_types[i] == '0')
716 {
717 if (i != 0)
718 operand_types[i] = NULL;
719 break;
720 }
721 }
722
723 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
724 name, operands, base_opcode, extension_opcode,
725 opcode_length);
726
727 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
728
729 process_i386_opcode_modifier (table, opcode_modifier);
730
731 fprintf (table, " { ");
732
733 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
734 {
735 if (operand_types[i] == NULL
736 || *operand_types[i] == '0')
737 {
738 if (i == 0)
739 process_i386_operand_type (table, "0", 0, "\t ");
740 break;
741 }
742
743 if (i != 0)
744 fprintf (table, ",\n ");
745
746 process_i386_operand_type (table, operand_types[i], 0,
747 "\t ");
748 }
749 fprintf (table, " } },\n");
750 }
751
752 fclose (fp);
753
754 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
755
756 process_i386_cpu_flag (table, "0", 0, ",", " ");
757
758 process_i386_opcode_modifier (table, "0");
759
760 fprintf (table, " { ");
761 process_i386_operand_type (table, "0", 0, "\t ");
762 fprintf (table, " } }\n");
763
764 fprintf (table, "};\n");
765 }
766
767 static void
768 process_i386_registers (FILE *table)
769 {
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;
774
775 if (fp == NULL)
776 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
777 xstrerror (errno));
778
779 fprintf (table, "\n/* i386 register table. */\n\n");
780 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
781
782 while (!feof (fp))
783 {
784 if (fgets (buf, sizeof (buf), fp) == NULL)
785 break;
786
787 p = remove_leading_whitespaces (buf);
788
789 /* Skip comments. */
790 str = strstr (p, "//");
791 if (str != NULL)
792 str[0] = '\0';
793
794 /* Remove trailing white spaces. */
795 remove_trailing_whitespaces (p);
796
797 switch (p[0])
798 {
799 case '#':
800 fprintf (table, "%s\n", p);
801 case '\0':
802 continue;
803 break;
804 default:
805 break;
806 }
807
808 last = p + strlen (p);
809
810 /* Find reg_name. */
811 reg_name = next_field (p, ',', &str);
812
813 if (str >= last)
814 abort ();
815
816 /* Find reg_type. */
817 reg_type = next_field (str, ',', &str);
818
819 if (str >= last)
820 abort ();
821
822 /* Find reg_flags. */
823 reg_flags = next_field (str, ',', &str);
824
825 if (str >= last)
826 abort ();
827
828 /* Find reg_num. */
829 reg_num = next_field (str, ',', &str);
830
831 fprintf (table, " { \"%s\",\n ", reg_name);
832
833 process_i386_operand_type (table, reg_type, 0, "\t");
834
835 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
836 }
837
838 fclose (fp);
839
840 fprintf (table, "};\n");
841
842 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
843 }
844
845 static void
846 process_i386_initializers (void)
847 {
848 unsigned int i;
849 FILE *fp = fopen ("i386-init.h", "w");
850 char *init;
851
852 if (fp == NULL)
853 fail (_("can't create i386-init.h, errno = %s\n"),
854 xstrerror (errno));
855
856 process_copyright (fp);
857
858 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
859 {
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);
864 }
865
866 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
867 {
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);
872 }
873 fprintf (fp, "\n");
874
875 fclose (fp);
876 }
877
878 /* Program options. */
879 #define OPTION_SRCDIR 200
880
881 struct option long_options[] =
882 {
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}
888 };
889
890 static void
891 print_version (void)
892 {
893 printf ("%s: version 1.0\n", program_name);
894 xexit (0);
895 }
896
897 static void
898 usage (FILE * stream, int status)
899 {
900 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
901 program_name);
902 xexit (status);
903 }
904
905 int
906 main (int argc, char **argv)
907 {
908 extern int chdir (char *);
909 char *srcdir = NULL;
910 int c;
911 FILE *table;
912
913 program_name = *argv;
914 xmalloc_set_program_name (program_name);
915
916 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
917 switch (c)
918 {
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;
935 }
936
937 if (optind != argc)
938 usage (stdout, 1);
939
940 if (srcdir != NULL)
941 if (chdir (srcdir) != 0)
942 fail (_("unable to change directory to \"%s\", errno = %s\n"),
943 srcdir, xstrerror (errno));
944
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
951
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
958
959 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
960 compare);
961
962 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
963 sizeof (opcode_modifiers [0]), compare);
964
965 qsort (operand_types, ARRAY_SIZE (operand_types),
966 sizeof (operand_types [0]), compare);
967
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));
972
973 process_copyright (table);
974
975 process_i386_opcodes (table);
976 process_i386_registers (table);
977 process_i386_initializers ();
978
979 fclose (table);
980
981 exit (0);
982 }