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