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