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