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