gas/testsuite/
[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 (No_xSuf),
279 BITFIELD (CheckSize),
280 BITFIELD (Byte),
281 BITFIELD (Word),
282 BITFIELD (Dword),
283 BITFIELD (Qword),
284 BITFIELD (Xmmword),
285 BITFIELD (FWait),
286 BITFIELD (IsString),
287 BITFIELD (RegKludge),
288 BITFIELD (FirstXmm0),
289 BITFIELD (ByteOkIntel),
290 BITFIELD (ToDword),
291 BITFIELD (ToQword),
292 BITFIELD (AddrPrefixOp0),
293 BITFIELD (IsPrefix),
294 BITFIELD (ImmExt),
295 BITFIELD (NoRex64),
296 BITFIELD (Rex64),
297 BITFIELD (Ugh),
298 BITFIELD (Drex),
299 BITFIELD (Drexv),
300 BITFIELD (Drexc),
301 BITFIELD (OldGcc),
302 BITFIELD (ATTMnemonic),
303 BITFIELD (IntelMnemonic),
304 };
305
306 static bitfield operand_types[] =
307 {
308 BITFIELD (Reg8),
309 BITFIELD (Reg16),
310 BITFIELD (Reg32),
311 BITFIELD (Reg64),
312 BITFIELD (FloatReg),
313 BITFIELD (RegMMX),
314 BITFIELD (RegXMM),
315 BITFIELD (Imm8),
316 BITFIELD (Imm8S),
317 BITFIELD (Imm16),
318 BITFIELD (Imm32),
319 BITFIELD (Imm32S),
320 BITFIELD (Imm64),
321 BITFIELD (Imm1),
322 BITFIELD (BaseIndex),
323 BITFIELD (Disp8),
324 BITFIELD (Disp16),
325 BITFIELD (Disp32),
326 BITFIELD (Disp32S),
327 BITFIELD (Disp64),
328 BITFIELD (InOutPortReg),
329 BITFIELD (ShiftCount),
330 BITFIELD (Control),
331 BITFIELD (Debug),
332 BITFIELD (Test),
333 BITFIELD (SReg2),
334 BITFIELD (SReg3),
335 BITFIELD (Acc),
336 BITFIELD (FloatAcc),
337 BITFIELD (JumpAbsolute),
338 BITFIELD (EsSeg),
339 BITFIELD (RegMem),
340 #ifdef OTUnused
341 BITFIELD (OTUnused),
342 #endif
343 };
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 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 printf ("Unknown bitfield: %s\n", f);
455 abort ();
456 }
457
458 static void
459 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
460 int macro, const char *comma, const char *indent)
461 {
462 unsigned int i;
463
464 fprintf (table, "%s{ { ", indent);
465
466 for (i = 0; i < size - 1; i++)
467 {
468 fprintf (table, "%d, ", flags[i].value);
469 if (((i + 1) % 20) == 0)
470 {
471 /* We need \\ for macro. */
472 if (macro)
473 fprintf (table, " \\\n %s", indent);
474 else
475 fprintf (table, "\n %s", indent);
476 }
477 }
478
479 fprintf (table, "%d } }%s\n", flags[i].value, comma);
480 }
481
482 static void
483 process_i386_cpu_flag (FILE *table, char *flag, int macro,
484 const char *comma, const char *indent)
485 {
486 char *str, *next, *last;
487 bitfield flags [ARRAY_SIZE (cpu_flags)];
488
489 /* Copy the default cpu flags. */
490 memcpy (flags, cpu_flags, sizeof (cpu_flags));
491
492 if (strcasecmp (flag, "unknown") == 0)
493 {
494 unsigned int i;
495
496 /* We turn on everything except for cpu64 in case of
497 CPU_UNKNOWN_FLAGS. */
498 for (i = 0; i < ARRAY_SIZE (flags); i++)
499 if (flags[i].position != Cpu64)
500 flags[i].value = 1;
501 }
502 else if (strcmp (flag, "0"))
503 {
504 last = flag + strlen (flag);
505 for (next = flag; next && next < last; )
506 {
507 str = next_field (next, '|', &next);
508 if (str)
509 set_bitfield (str, flags, ARRAY_SIZE (flags));
510 }
511 }
512
513 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
514 comma, indent);
515 }
516
517 static void
518 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
519 {
520 unsigned int i;
521
522 fprintf (table, " { ");
523
524 for (i = 0; i < size - 1; i++)
525 {
526 fprintf (table, "%d, ", modifier[i].value);
527 if (((i + 1) % 20) == 0)
528 fprintf (table, "\n ");
529 }
530
531 fprintf (table, "%d },\n", modifier[i].value);
532 }
533
534 static void
535 process_i386_opcode_modifier (FILE *table, char *mod)
536 {
537 char *str, *next, *last;
538 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
539
540 /* Copy the default opcode modifier. */
541 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
542
543 if (strcmp (mod, "0"))
544 {
545 last = mod + strlen (mod);
546 for (next = mod; next && next < last; )
547 {
548 str = next_field (next, '|', &next);
549 if (str)
550 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
551 }
552 }
553 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
554 }
555
556 static void
557 output_operand_type (FILE *table, bitfield *types, unsigned int size,
558 int macro, const char *indent)
559 {
560 unsigned int i;
561
562 fprintf (table, "{ { ");
563
564 for (i = 0; i < size - 1; i++)
565 {
566 fprintf (table, "%d, ", types[i].value);
567 if (((i + 1) % 20) == 0)
568 {
569 /* We need \\ for macro. */
570 if (macro)
571 fprintf (table, "\\\n%s", indent);
572 else
573 fprintf (table, "\n%s", indent);
574 }
575 }
576
577 fprintf (table, "%d } }", types[i].value);
578 }
579
580 static void
581 process_i386_operand_type (FILE *table, char *op, int macro,
582 const char *indent)
583 {
584 char *str, *next, *last;
585 bitfield types [ARRAY_SIZE (operand_types)];
586
587 /* Copy the default operand type. */
588 memcpy (types, operand_types, sizeof (types));
589
590 if (strcmp (op, "0"))
591 {
592 last = op + strlen (op);
593 for (next = op; next && next < last; )
594 {
595 str = next_field (next, '|', &next);
596 if (str)
597 set_bitfield (str, types, ARRAY_SIZE (types));
598 }
599 }
600 output_operand_type (table, types, ARRAY_SIZE (types), macro,
601 indent);
602 }
603
604 static void
605 process_i386_opcodes (FILE *table)
606 {
607 FILE *fp = fopen ("i386-opc.tbl", "r");
608 char buf[2048];
609 unsigned int i;
610 char *str, *p, *last;
611 char *name, *operands, *base_opcode, *extension_opcode;
612 char *opcode_length;
613 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
614
615 if (fp == NULL)
616 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
617 xstrerror (errno));
618
619 fprintf (table, "\n/* i386 opcode table. */\n\n");
620 fprintf (table, "const template i386_optab[] =\n{\n");
621
622 while (!feof (fp))
623 {
624 if (fgets (buf, sizeof (buf), fp) == NULL)
625 break;
626
627 p = remove_leading_whitespaces (buf);
628
629 /* Skip comments. */
630 str = strstr (p, "//");
631 if (str != NULL)
632 str[0] = '\0';
633
634 /* Remove trailing white spaces. */
635 remove_trailing_whitespaces (p);
636
637 switch (p[0])
638 {
639 case '#':
640 fprintf (table, "%s\n", p);
641 case '\0':
642 continue;
643 break;
644 default:
645 break;
646 }
647
648 last = p + strlen (p);
649
650 /* Find name. */
651 name = next_field (p, ',', &str);
652
653 if (str >= last)
654 abort ();
655
656 /* Find number of operands. */
657 operands = next_field (str, ',', &str);
658
659 if (str >= last)
660 abort ();
661
662 /* Find base_opcode. */
663 base_opcode = next_field (str, ',', &str);
664
665 if (str >= last)
666 abort ();
667
668 /* Find extension_opcode. */
669 extension_opcode = next_field (str, ',', &str);
670
671 if (str >= last)
672 abort ();
673
674 /* Find opcode_length. */
675 opcode_length = next_field (str, ',', &str);
676
677 if (str >= last)
678 abort ();
679
680 /* Find cpu_flags. */
681 cpu_flags = next_field (str, ',', &str);
682
683 if (str >= last)
684 abort ();
685
686 /* Find opcode_modifier. */
687 opcode_modifier = next_field (str, ',', &str);
688
689 if (str >= last)
690 abort ();
691
692 /* Remove the first {. */
693 str = remove_leading_whitespaces (str);
694 if (*str != '{')
695 abort ();
696 str = remove_leading_whitespaces (str + 1);
697
698 i = strlen (str);
699
700 /* There are at least "X}". */
701 if (i < 2)
702 abort ();
703
704 /* Remove trailing white spaces and }. */
705 do
706 {
707 i--;
708 if (ISSPACE (str[i]) || str[i] == '}')
709 str[i] = '\0';
710 else
711 break;
712 }
713 while (i != 0);
714
715 last = str + i;
716
717 /* Find operand_types. */
718 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
719 {
720 if (str >= last)
721 {
722 operand_types [i] = NULL;
723 break;
724 }
725
726 operand_types [i] = next_field (str, ',', &str);
727 if (*operand_types[i] == '0')
728 {
729 if (i != 0)
730 operand_types[i] = NULL;
731 break;
732 }
733 }
734
735 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
736 name, operands, base_opcode, extension_opcode,
737 opcode_length);
738
739 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ");
740
741 process_i386_opcode_modifier (table, opcode_modifier);
742
743 fprintf (table, " { ");
744
745 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
746 {
747 if (operand_types[i] == NULL
748 || *operand_types[i] == '0')
749 {
750 if (i == 0)
751 process_i386_operand_type (table, "0", 0, "\t ");
752 break;
753 }
754
755 if (i != 0)
756 fprintf (table, ",\n ");
757
758 process_i386_operand_type (table, operand_types[i], 0,
759 "\t ");
760 }
761 fprintf (table, " } },\n");
762 }
763
764 fclose (fp);
765
766 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
767
768 process_i386_cpu_flag (table, "0", 0, ",", " ");
769
770 process_i386_opcode_modifier (table, "0");
771
772 fprintf (table, " { ");
773 process_i386_operand_type (table, "0", 0, "\t ");
774 fprintf (table, " } }\n");
775
776 fprintf (table, "};\n");
777 }
778
779 static void
780 process_i386_registers (FILE *table)
781 {
782 FILE *fp = fopen ("i386-reg.tbl", "r");
783 char buf[2048];
784 char *str, *p, *last;
785 char *reg_name, *reg_type, *reg_flags, *reg_num;
786
787 if (fp == NULL)
788 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
789 xstrerror (errno));
790
791 fprintf (table, "\n/* i386 register table. */\n\n");
792 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
793
794 while (!feof (fp))
795 {
796 if (fgets (buf, sizeof (buf), fp) == NULL)
797 break;
798
799 p = remove_leading_whitespaces (buf);
800
801 /* Skip comments. */
802 str = strstr (p, "//");
803 if (str != NULL)
804 str[0] = '\0';
805
806 /* Remove trailing white spaces. */
807 remove_trailing_whitespaces (p);
808
809 switch (p[0])
810 {
811 case '#':
812 fprintf (table, "%s\n", p);
813 case '\0':
814 continue;
815 break;
816 default:
817 break;
818 }
819
820 last = p + strlen (p);
821
822 /* Find reg_name. */
823 reg_name = next_field (p, ',', &str);
824
825 if (str >= last)
826 abort ();
827
828 /* Find reg_type. */
829 reg_type = next_field (str, ',', &str);
830
831 if (str >= last)
832 abort ();
833
834 /* Find reg_flags. */
835 reg_flags = next_field (str, ',', &str);
836
837 if (str >= last)
838 abort ();
839
840 /* Find reg_num. */
841 reg_num = next_field (str, ',', &str);
842
843 fprintf (table, " { \"%s\",\n ", reg_name);
844
845 process_i386_operand_type (table, reg_type, 0, "\t");
846
847 fprintf (table, ",\n %s, %s },\n", reg_flags, reg_num);
848 }
849
850 fclose (fp);
851
852 fprintf (table, "};\n");
853
854 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
855 }
856
857 static void
858 process_i386_initializers (void)
859 {
860 unsigned int i;
861 FILE *fp = fopen ("i386-init.h", "w");
862 char *init;
863
864 if (fp == NULL)
865 fail (_("can't create i386-init.h, errno = %s\n"),
866 xstrerror (errno));
867
868 process_copyright (fp);
869
870 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
871 {
872 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
873 init = xstrdup (cpu_flag_init[i].init);
874 process_i386_cpu_flag (fp, init, 1, "", " ");
875 free (init);
876 }
877
878 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
879 {
880 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
881 init = xstrdup (operand_type_init[i].init);
882 process_i386_operand_type (fp, init, 1, " ");
883 free (init);
884 }
885 fprintf (fp, "\n");
886
887 fclose (fp);
888 }
889
890 /* Program options. */
891 #define OPTION_SRCDIR 200
892
893 struct option long_options[] =
894 {
895 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
896 {"debug", no_argument, NULL, 'd'},
897 {"version", no_argument, NULL, 'V'},
898 {"help", no_argument, NULL, 'h'},
899 {0, no_argument, NULL, 0}
900 };
901
902 static void
903 print_version (void)
904 {
905 printf ("%s: version 1.0\n", program_name);
906 xexit (0);
907 }
908
909 static void
910 usage (FILE * stream, int status)
911 {
912 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
913 program_name);
914 xexit (status);
915 }
916
917 int
918 main (int argc, char **argv)
919 {
920 extern int chdir (char *);
921 char *srcdir = NULL;
922 int c;
923 FILE *table;
924
925 program_name = *argv;
926 xmalloc_set_program_name (program_name);
927
928 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
929 switch (c)
930 {
931 case OPTION_SRCDIR:
932 srcdir = optarg;
933 break;
934 case 'V':
935 case 'v':
936 print_version ();
937 break;
938 case 'd':
939 debug = 1;
940 break;
941 case 'h':
942 case '?':
943 usage (stderr, 0);
944 default:
945 case 0:
946 break;
947 }
948
949 if (optind != argc)
950 usage (stdout, 1);
951
952 if (srcdir != NULL)
953 if (chdir (srcdir) != 0)
954 fail (_("unable to change directory to \"%s\", errno = %s\n"),
955 srcdir, xstrerror (errno));
956
957 /* Check the unused bitfield in i386_cpu_flags. */
958 #ifndef CpuUnused
959 c = CpuNumOfBits - CpuMax - 1;
960 if (c)
961 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
962 #endif
963
964 /* Check the unused bitfield in i386_operand_type. */
965 #ifndef OTUnused
966 c = OTNumOfBits - OTMax - 1;
967 if (c)
968 fail (_("%d unused bits in i386_operand_type.\n"), c);
969 #endif
970
971 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
972 compare);
973
974 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
975 sizeof (opcode_modifiers [0]), compare);
976
977 qsort (operand_types, ARRAY_SIZE (operand_types),
978 sizeof (operand_types [0]), compare);
979
980 table = fopen ("i386-tbl.h", "w");
981 if (table == NULL)
982 fail (_("can't create i386-tbl.h, errno = %s\n"),
983 xstrerror (errno));
984
985 process_copyright (table);
986
987 process_i386_opcodes (table);
988 process_i386_registers (table);
989 process_i386_initializers ();
990
991 fclose (table);
992
993 exit (0);
994 }