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