gas/
[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|CpuSSE|CpuSSE2|CpuLM" },
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|CpuSSE" },
67 { "CPU_P4_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2" },
69 { "CPU_NOCONA_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
71 { "CPU_CORE_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
73 { "CPU_CORE2_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|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|Cpu3dnow|Cpu3dnowA" },
81 { "CPU_K8_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
83 { "CPU_AMDFAM10_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuK8|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
85 { "CPU_MMX_FLAGS",
86 "CpuMMX" },
87 { "CPU_SSE_FLAGS",
88 "CpuMMX|CpuSSE" },
89 { "CPU_SSE2_FLAGS",
90 "CpuMMX|CpuSSE|CpuSSE2" },
91 { "CPU_SSE3_FLAGS",
92 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
93 { "CPU_SSSE3_FLAGS",
94 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
95 { "CPU_SSE4_1_FLAGS",
96 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
97 { "CPU_SSE4_2_FLAGS",
98 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
99 { "CPU_VMX_FLAGS",
100 "CpuVMX" },
101 { "CPU_SMX_FLAGS",
102 "CpuSMX" },
103 { "CPU_XSAVE_FLAGS",
104 "CpuXsave" },
105 { "CPU_3DNOW_FLAGS",
106 "CpuMMX|Cpu3dnow" },
107 { "CPU_3DNOWA_FLAGS",
108 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
109 { "CPU_PADLOCK_FLAGS",
110 "CpuPadLock" },
111 { "CPU_SVME_FLAGS",
112 "CpuSVME" },
113 { "CPU_SSE4A_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
115 { "CPU_ABM_FLAGS",
116 "CpuABM" },
117 { "CPU_SSE5_FLAGS",
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
119 };
120
121 static initializer operand_type_init [] =
122 {
123 { "OPERAND_TYPE_NONE",
124 "0" },
125 { "OPERAND_TYPE_REG8",
126 "Reg8" },
127 { "OPERAND_TYPE_REG16",
128 "Reg16" },
129 { "OPERAND_TYPE_REG32",
130 "Reg32" },
131 { "OPERAND_TYPE_REG64",
132 "Reg64" },
133 { "OPERAND_TYPE_IMM1",
134 "Imm1" },
135 { "OPERAND_TYPE_IMM8",
136 "Imm8" },
137 { "OPERAND_TYPE_IMM8S",
138 "Imm8S" },
139 { "OPERAND_TYPE_IMM16",
140 "Imm16" },
141 { "OPERAND_TYPE_IMM32",
142 "Imm32" },
143 { "OPERAND_TYPE_IMM32S",
144 "Imm32S" },
145 { "OPERAND_TYPE_IMM64",
146 "Imm64" },
147 { "OPERAND_TYPE_BASEINDEX",
148 "BaseIndex" },
149 { "OPERAND_TYPE_DISP8",
150 "Disp8" },
151 { "OPERAND_TYPE_DISP16",
152 "Disp16" },
153 { "OPERAND_TYPE_DISP32",
154 "Disp32" },
155 { "OPERAND_TYPE_DISP32S",
156 "Disp32S" },
157 { "OPERAND_TYPE_DISP64",
158 "Disp64" },
159 { "OPERAND_TYPE_INOUTPORTREG",
160 "InOutPortReg" },
161 { "OPERAND_TYPE_SHIFTCOUNT",
162 "ShiftCount" },
163 { "OPERAND_TYPE_CONTROL",
164 "Control" },
165 { "OPERAND_TYPE_TEST",
166 "Test" },
167 { "OPERAND_TYPE_DEBUG",
168 "FloatReg" },
169 { "OPERAND_TYPE_FLOATREG",
170 "FloatReg" },
171 { "OPERAND_TYPE_FLOATACC",
172 "FloatAcc" },
173 { "OPERAND_TYPE_SREG2",
174 "SReg2" },
175 { "OPERAND_TYPE_SREG3",
176 "SReg3" },
177 { "OPERAND_TYPE_ACC",
178 "Acc" },
179 { "OPERAND_TYPE_JUMPABSOLUTE",
180 "JumpAbsolute" },
181 { "OPERAND_TYPE_REGMMX",
182 "RegMMX" },
183 { "OPERAND_TYPE_REGXMM",
184 "RegXMM" },
185 { "OPERAND_TYPE_ESSEG",
186 "EsSeg" },
187 { "OPERAND_TYPE_ACC32",
188 "Reg32|Acc|Dword" },
189 { "OPERAND_TYPE_ACC64",
190 "Reg64|Acc|Qword" },
191 { "OPERAND_TYPE_REG16_INOUTPORTREG",
192 "Reg16|InOutPortReg" },
193 { "OPERAND_TYPE_DISP16_32",
194 "Disp16|Disp32" },
195 { "OPERAND_TYPE_ANYDISP",
196 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
197 { "OPERAND_TYPE_IMM16_32",
198 "Imm16|Imm32" },
199 { "OPERAND_TYPE_IMM16_32S",
200 "Imm16|Imm32S" },
201 { "OPERAND_TYPE_IMM16_32_32S",
202 "Imm16|Imm32|Imm32S" },
203 { "OPERAND_TYPE_IMM32_32S_DISP32",
204 "Imm32|Imm32S|Disp32" },
205 { "OPERAND_TYPE_IMM64_DISP64",
206 "Imm64|Disp64" },
207 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
208 "Imm32|Imm32S|Imm64|Disp32" },
209 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
210 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
211 };
212
213 typedef struct bitfield
214 {
215 int position;
216 int value;
217 const char *name;
218 } bitfield;
219
220 #define BITFIELD(n) { n, 0, #n }
221
222 static bitfield cpu_flags[] =
223 {
224 BITFIELD (Cpu186),
225 BITFIELD (Cpu286),
226 BITFIELD (Cpu386),
227 BITFIELD (Cpu486),
228 BITFIELD (Cpu586),
229 BITFIELD (Cpu686),
230 BITFIELD (CpuP4),
231 BITFIELD (CpuK6),
232 BITFIELD (CpuK8),
233 BITFIELD (CpuMMX),
234 BITFIELD (CpuSSE),
235 BITFIELD (CpuSSE2),
236 BITFIELD (CpuSSE3),
237 BITFIELD (CpuSSSE3),
238 BITFIELD (CpuSSE4_1),
239 BITFIELD (CpuSSE4_2),
240 BITFIELD (CpuSSE4a),
241 BITFIELD (CpuSSE5),
242 BITFIELD (Cpu3dnow),
243 BITFIELD (Cpu3dnowA),
244 BITFIELD (CpuPadLock),
245 BITFIELD (CpuSVME),
246 BITFIELD (CpuVMX),
247 BITFIELD (CpuSMX),
248 BITFIELD (CpuABM),
249 BITFIELD (CpuLM),
250 BITFIELD (CpuXsave),
251 BITFIELD (Cpu64),
252 BITFIELD (CpuNo64),
253 #ifdef CpuUnused
254 BITFIELD (CpuUnused),
255 #endif
256 };
257
258 static bitfield opcode_modifiers[] =
259 {
260 BITFIELD (D),
261 BITFIELD (W),
262 BITFIELD (Modrm),
263 BITFIELD (ShortForm),
264 BITFIELD (Jump),
265 BITFIELD (JumpDword),
266 BITFIELD (JumpByte),
267 BITFIELD (JumpInterSegment),
268 BITFIELD (FloatMF),
269 BITFIELD (FloatR),
270 BITFIELD (FloatD),
271 BITFIELD (Size16),
272 BITFIELD (Size32),
273 BITFIELD (Size64),
274 BITFIELD (IgnoreSize),
275 BITFIELD (DefaultSize),
276 BITFIELD (No_bSuf),
277 BITFIELD (No_wSuf),
278 BITFIELD (No_lSuf),
279 BITFIELD (No_sSuf),
280 BITFIELD (No_qSuf),
281 BITFIELD (No_ldSuf),
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 BITFIELD (IntelSyntax),
302 };
303
304 static bitfield operand_types[] =
305 {
306 BITFIELD (Reg8),
307 BITFIELD (Reg16),
308 BITFIELD (Reg32),
309 BITFIELD (Reg64),
310 BITFIELD (FloatReg),
311 BITFIELD (RegMMX),
312 BITFIELD (RegXMM),
313 BITFIELD (Imm8),
314 BITFIELD (Imm8S),
315 BITFIELD (Imm16),
316 BITFIELD (Imm32),
317 BITFIELD (Imm32S),
318 BITFIELD (Imm64),
319 BITFIELD (Imm1),
320 BITFIELD (BaseIndex),
321 BITFIELD (Disp8),
322 BITFIELD (Disp16),
323 BITFIELD (Disp32),
324 BITFIELD (Disp32S),
325 BITFIELD (Disp64),
326 BITFIELD (InOutPortReg),
327 BITFIELD (ShiftCount),
328 BITFIELD (Control),
329 BITFIELD (Debug),
330 BITFIELD (Test),
331 BITFIELD (SReg2),
332 BITFIELD (SReg3),
333 BITFIELD (Acc),
334 BITFIELD (FloatAcc),
335 BITFIELD (JumpAbsolute),
336 BITFIELD (EsSeg),
337 BITFIELD (RegMem),
338 BITFIELD (Mem),
339 BITFIELD (Byte),
340 BITFIELD (Word),
341 BITFIELD (Dword),
342 BITFIELD (Fword),
343 BITFIELD (Qword),
344 BITFIELD (Tbyte),
345 BITFIELD (Xmmword),
346 BITFIELD (Unspecified),
347 BITFIELD (Anysize),
348 #ifdef OTUnused
349 BITFIELD (OTUnused),
350 #endif
351 };
352
353 static int lineno;
354 static const char *filename;
355
356 static int
357 compare (const void *x, const void *y)
358 {
359 const bitfield *xp = (const bitfield *) x;
360 const bitfield *yp = (const bitfield *) y;
361 return xp->position - yp->position;
362 }
363
364 static void
365 fail (const char *message, ...)
366 {
367 va_list args;
368
369 va_start (args, message);
370 fprintf (stderr, _("%s: Error: "), program_name);
371 vfprintf (stderr, message, args);
372 va_end (args);
373 xexit (1);
374 }
375
376 static void
377 process_copyright (FILE *fp)
378 {
379 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
380 /* Copyright 2007, 2008 Free Software Foundation, Inc.\n\
381 \n\
382 This file is part of the GNU opcodes library.\n\
383 \n\
384 This library is free software; you can redistribute it and/or modify\n\
385 it under the terms of the GNU General Public License as published by\n\
386 the Free Software Foundation; either version 3, or (at your option)\n\
387 any later version.\n\
388 \n\
389 It is distributed in the hope that it will be useful, but WITHOUT\n\
390 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
391 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
392 License for more details.\n\
393 \n\
394 You should have received a copy of the GNU General Public License\n\
395 along with this program; if not, write to the Free Software\n\
396 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
397 MA 02110-1301, USA. */\n");
398 }
399
400 /* Remove leading white spaces. */
401
402 static char *
403 remove_leading_whitespaces (char *str)
404 {
405 while (ISSPACE (*str))
406 str++;
407 return str;
408 }
409
410 /* Remove trailing white spaces. */
411
412 static void
413 remove_trailing_whitespaces (char *str)
414 {
415 size_t last = strlen (str);
416
417 if (last == 0)
418 return;
419
420 do
421 {
422 last--;
423 if (ISSPACE (str [last]))
424 str[last] = '\0';
425 else
426 break;
427 }
428 while (last != 0);
429 }
430
431 /* Find next field separated by SEP and terminate it. Return a
432 pointer to the one after it. */
433
434 static char *
435 next_field (char *str, char sep, char **next)
436 {
437 char *p;
438
439 p = remove_leading_whitespaces (str);
440 for (str = p; *str != sep && *str != '\0'; str++);
441
442 *str = '\0';
443 remove_trailing_whitespaces (p);
444
445 *next = str + 1;
446
447 return p;
448 }
449
450 static void
451 set_bitfield (const char *f, bitfield *array, unsigned int size)
452 {
453 unsigned int i;
454
455 if (strcmp (f, "CpuSledgehammer") == 0)
456 f= "CpuK8";
457 else if (strcmp (f, "Mmword") == 0)
458 f= "Qword";
459 else if (strcmp (f, "Oword") == 0)
460 f= "Xmmword";
461
462 for (i = 0; i < size; i++)
463 if (strcasecmp (array[i].name, f) == 0)
464 {
465 array[i].value = 1;
466 return;
467 }
468
469 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
470 }
471
472 static void
473 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
474 int macro, const char *comma, const char *indent)
475 {
476 unsigned int i;
477
478 fprintf (table, "%s{ { ", indent);
479
480 for (i = 0; i < size - 1; i++)
481 {
482 fprintf (table, "%d, ", flags[i].value);
483 if (((i + 1) % 20) == 0)
484 {
485 /* We need \\ for macro. */
486 if (macro)
487 fprintf (table, " \\\n %s", indent);
488 else
489 fprintf (table, "\n %s", indent);
490 }
491 }
492
493 fprintf (table, "%d } }%s\n", flags[i].value, comma);
494 }
495
496 static void
497 process_i386_cpu_flag (FILE *table, char *flag, int macro,
498 const char *comma, const char *indent)
499 {
500 char *str, *next, *last;
501 bitfield flags [ARRAY_SIZE (cpu_flags)];
502
503 /* Copy the default cpu flags. */
504 memcpy (flags, cpu_flags, sizeof (cpu_flags));
505
506 if (strcasecmp (flag, "unknown") == 0)
507 {
508 unsigned int i;
509
510 /* We turn on everything except for cpu64 in case of
511 CPU_UNKNOWN_FLAGS. */
512 for (i = 0; i < ARRAY_SIZE (flags); i++)
513 if (flags[i].position != Cpu64)
514 flags[i].value = 1;
515 }
516 else if (strcmp (flag, "0"))
517 {
518 last = flag + strlen (flag);
519 for (next = flag; next && next < last; )
520 {
521 str = next_field (next, '|', &next);
522 if (str)
523 set_bitfield (str, flags, ARRAY_SIZE (flags));
524 }
525 }
526
527 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
528 comma, indent);
529 }
530
531 static void
532 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
533 {
534 unsigned int i;
535
536 fprintf (table, " { ");
537
538 for (i = 0; i < size - 1; i++)
539 {
540 fprintf (table, "%d, ", modifier[i].value);
541 if (((i + 1) % 20) == 0)
542 fprintf (table, "\n ");
543 }
544
545 fprintf (table, "%d },\n", modifier[i].value);
546 }
547
548 static void
549 process_i386_opcode_modifier (FILE *table, char *mod)
550 {
551 char *str, *next, *last;
552 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
553
554 /* Copy the default opcode modifier. */
555 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
556
557 if (strcmp (mod, "0"))
558 {
559 last = mod + strlen (mod);
560 for (next = mod; next && next < last; )
561 {
562 str = next_field (next, '|', &next);
563 if (str)
564 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
565 }
566 }
567 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
568 }
569
570 static void
571 output_operand_type (FILE *table, bitfield *types, unsigned int size,
572 int macro, const char *indent)
573 {
574 unsigned int i;
575
576 fprintf (table, "{ { ");
577
578 for (i = 0; i < size - 1; i++)
579 {
580 fprintf (table, "%d, ", types[i].value);
581 if (((i + 1) % 20) == 0)
582 {
583 /* We need \\ for macro. */
584 if (macro)
585 fprintf (table, "\\\n%s", indent);
586 else
587 fprintf (table, "\n%s", indent);
588 }
589 }
590
591 fprintf (table, "%d } }", types[i].value);
592 }
593
594 static void
595 process_i386_operand_type (FILE *table, char *op, int macro,
596 const char *indent)
597 {
598 char *str, *next, *last;
599 bitfield types [ARRAY_SIZE (operand_types)];
600
601 /* Copy the default operand type. */
602 memcpy (types, operand_types, sizeof (types));
603
604 if (strcmp (op, "0"))
605 {
606 last = op + strlen (op);
607 for (next = op; next && next < last; )
608 {
609 str = next_field (next, '|', &next);
610 if (str)
611 set_bitfield (str, types, ARRAY_SIZE (types));
612 }
613 }
614 output_operand_type (table, types, ARRAY_SIZE (types), macro,
615 indent);
616 }
617
618 static void
619 process_i386_opcodes (FILE *table)
620 {
621 FILE *fp;
622 char buf[2048];
623 unsigned int i;
624 char *str, *p, *last;
625 char *name, *operands, *base_opcode, *extension_opcode;
626 char *opcode_length;
627 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
628
629 filename = "i386-opc.tbl";
630 fp = fopen (filename, "r");
631
632 if (fp == NULL)
633 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
634 xstrerror (errno));
635
636 fprintf (table, "\n/* i386 opcode table. */\n\n");
637 fprintf (table, "const template i386_optab[] =\n{\n");
638
639 while (!feof (fp))
640 {
641 if (fgets (buf, sizeof (buf), fp) == NULL)
642 break;
643
644 lineno++;
645
646 p = remove_leading_whitespaces (buf);
647
648 /* Skip comments. */
649 str = strstr (p, "//");
650 if (str != NULL)
651 str[0] = '\0';
652
653 /* Remove trailing white spaces. */
654 remove_trailing_whitespaces (p);
655
656 switch (p[0])
657 {
658 case '#':
659 fprintf (table, "%s\n", p);
660 case '\0':
661 continue;
662 break;
663 default:
664 break;
665 }
666
667 last = p + strlen (p);
668
669 /* Find name. */
670 name = next_field (p, ',', &str);
671
672 if (str >= last)
673 abort ();
674
675 /* Find number of operands. */
676 operands = next_field (str, ',', &str);
677
678 if (str >= last)
679 abort ();
680
681 /* Find base_opcode. */
682 base_opcode = next_field (str, ',', &str);
683
684 if (str >= last)
685 abort ();
686
687 /* Find extension_opcode. */
688 extension_opcode = next_field (str, ',', &str);
689
690 if (str >= last)
691 abort ();
692
693 /* Find opcode_length. */
694 opcode_length = next_field (str, ',', &str);
695
696 if (str >= last)
697 abort ();
698
699 /* Find cpu_flags. */
700 cpu_flags = next_field (str, ',', &str);
701
702 if (str >= last)
703 abort ();
704
705 /* Find opcode_modifier. */
706 opcode_modifier = next_field (str, ',', &str);
707
708 if (str >= last)
709 abort ();
710
711 /* Remove the first {. */
712 str = remove_leading_whitespaces (str);
713 if (*str != '{')
714 abort ();
715 str = remove_leading_whitespaces (str + 1);
716
717 i = strlen (str);
718
719 /* There are at least "X}". */
720 if (i < 2)
721 abort ();
722
723 /* Remove trailing white spaces and }. */
724 do
725 {
726 i--;
727 if (ISSPACE (str[i]) || str[i] == '}')
728 str[i] = '\0';
729 else
730 break;
731 }
732 while (i != 0);
733
734 last = str + i;
735
736 /* Find operand_types. */
737 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
738 {
739 if (str >= last)
740 {
741 operand_types [i] = NULL;
742 break;
743 }
744
745 operand_types [i] = next_field (str, ',', &str);
746 if (*operand_types[i] == '0')
747 {
748 if (i != 0)
749 operand_types[i] = NULL;
750 break;
751 }
752 }
753
754 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
755 name, operands, base_opcode, extension_opcode,
756 opcode_length);
757
758 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
759
760 process_i386_opcode_modifier (table, opcode_modifier);
761
762 fprintf (table, " { ");
763
764 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
765 {
766 if (operand_types[i] == NULL
767 || *operand_types[i] == '0')
768 {
769 if (i == 0)
770 process_i386_operand_type (table, "0", 0, "\t ");
771 break;
772 }
773
774 if (i != 0)
775 fprintf (table, ",\n ");
776
777 process_i386_operand_type (table, operand_types[i], 0,
778 "\t ");
779 }
780 fprintf (table, " } },\n");
781 }
782
783 fclose (fp);
784
785 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
786
787 process_i386_cpu_flag (table, "0", 0, ",", " ");
788
789 process_i386_opcode_modifier (table, "0");
790
791 fprintf (table, " { ");
792 process_i386_operand_type (table, "0", 0, "\t ");
793 fprintf (table, " } }\n");
794
795 fprintf (table, "};\n");
796 }
797
798 static void
799 process_i386_registers (FILE *table)
800 {
801 FILE *fp;
802 char buf[2048];
803 char *str, *p, *last;
804 char *reg_name, *reg_type, *reg_flags, *reg_num;
805
806 filename = "i386-reg.tbl";
807 fp = fopen (filename, "r");
808 if (fp == NULL)
809 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
810 xstrerror (errno));
811
812 fprintf (table, "\n/* i386 register table. */\n\n");
813 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
814
815 while (!feof (fp))
816 {
817 if (fgets (buf, sizeof (buf), fp) == NULL)
818 break;
819
820 lineno++;
821
822 p = remove_leading_whitespaces (buf);
823
824 /* Skip comments. */
825 str = strstr (p, "//");
826 if (str != NULL)
827 str[0] = '\0';
828
829 /* Remove trailing white spaces. */
830 remove_trailing_whitespaces (p);
831
832 switch (p[0])
833 {
834 case '#':
835 fprintf (table, "%s\n", p);
836 case '\0':
837 continue;
838 break;
839 default:
840 break;
841 }
842
843 last = p + strlen (p);
844
845 /* Find reg_name. */
846 reg_name = next_field (p, ',', &str);
847
848 if (str >= last)
849 abort ();
850
851 /* Find reg_type. */
852 reg_type = next_field (str, ',', &str);
853
854 if (str >= last)
855 abort ();
856
857 /* Find reg_flags. */
858 reg_flags = next_field (str, ',', &str);
859
860 if (str >= last)
861 abort ();
862
863 /* Find reg_num. */
864 reg_num = next_field (str, ',', &str);
865
866 fprintf (table, " { \"%s\",\n ", reg_name);
867
868 process_i386_operand_type (table, reg_type, 0, "\t");
869
870 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
871 }
872
873 fclose (fp);
874
875 fprintf (table, "};\n");
876
877 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
878 }
879
880 static void
881 process_i386_initializers (void)
882 {
883 unsigned int i;
884 FILE *fp = fopen ("i386-init.h", "w");
885 char *init;
886
887 if (fp == NULL)
888 fail (_("can't create i386-init.h, errno = %s\n"),
889 xstrerror (errno));
890
891 process_copyright (fp);
892
893 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
894 {
895 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
896 init = xstrdup (cpu_flag_init[i].init);
897 process_i386_cpu_flag (fp, init, 1, "", " ");
898 free (init);
899 }
900
901 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
902 {
903 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
904 init = xstrdup (operand_type_init[i].init);
905 process_i386_operand_type (fp, init, 1, " ");
906 free (init);
907 }
908 fprintf (fp, "\n");
909
910 fclose (fp);
911 }
912
913 /* Program options. */
914 #define OPTION_SRCDIR 200
915
916 struct option long_options[] =
917 {
918 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
919 {"debug", no_argument, NULL, 'd'},
920 {"version", no_argument, NULL, 'V'},
921 {"help", no_argument, NULL, 'h'},
922 {0, no_argument, NULL, 0}
923 };
924
925 static void
926 print_version (void)
927 {
928 printf ("%s: version 1.0\n", program_name);
929 xexit (0);
930 }
931
932 static void
933 usage (FILE * stream, int status)
934 {
935 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
936 program_name);
937 xexit (status);
938 }
939
940 int
941 main (int argc, char **argv)
942 {
943 extern int chdir (char *);
944 char *srcdir = NULL;
945 int c;
946 FILE *table;
947
948 program_name = *argv;
949 xmalloc_set_program_name (program_name);
950
951 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
952 switch (c)
953 {
954 case OPTION_SRCDIR:
955 srcdir = optarg;
956 break;
957 case 'V':
958 case 'v':
959 print_version ();
960 break;
961 case 'd':
962 debug = 1;
963 break;
964 case 'h':
965 case '?':
966 usage (stderr, 0);
967 default:
968 case 0:
969 break;
970 }
971
972 if (optind != argc)
973 usage (stdout, 1);
974
975 if (srcdir != NULL)
976 if (chdir (srcdir) != 0)
977 fail (_("unable to change directory to \"%s\", errno = %s\n"),
978 srcdir, xstrerror (errno));
979
980 /* Check the unused bitfield in i386_cpu_flags. */
981 #ifndef CpuUnused
982 c = CpuNumOfBits - CpuMax - 1;
983 if (c)
984 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
985 #endif
986
987 /* Check the unused bitfield in i386_operand_type. */
988 #ifndef OTUnused
989 c = OTNumOfBits - OTMax - 1;
990 if (c)
991 fail (_("%d unused bits in i386_operand_type.\n"), c);
992 #endif
993
994 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
995 compare);
996
997 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
998 sizeof (opcode_modifiers [0]), compare);
999
1000 qsort (operand_types, ARRAY_SIZE (operand_types),
1001 sizeof (operand_types [0]), compare);
1002
1003 table = fopen ("i386-tbl.h", "w");
1004 if (table == NULL)
1005 fail (_("can't create i386-tbl.h, errno = %s\n"),
1006 xstrerror (errno));
1007
1008 process_copyright (table);
1009
1010 process_i386_opcodes (table);
1011 process_i386_registers (table);
1012 process_i386_initializers ();
1013
1014 fclose (table);
1015
1016 exit (0);
1017 }