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