1 /* Copyright 2007, 2008, 2009, 2010
2 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "libiberty.h"
27 #include "safe-ctype.h"
32 #define _(String) gettext (String)
34 static const char *program_name
= NULL
;
37 typedef struct initializer
43 static initializer cpu_flag_init
[] =
45 { "CPU_UNKNOWN_FLAGS",
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
58 "Cpu186|Cpu286|Cpu386" },
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu387" },
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuMMX" },
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuMMX|CpuSSE" },
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuMMX|CpuSSE|CpuSSE2" },
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX|Cpu3dnow" },
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuMMX|Cpu3dnow|Cpu3dnowA" },
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
87 { "CPU_AMDFAM10_FLAGS",
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP" },
98 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
99 { "CPU_CLFLUSH_FLAGS",
101 { "CPU_SYSCALL_FLAGS",
108 "CpuMMX|CpuSSE|CpuSSE2" },
110 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
112 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
113 { "CPU_SSE4_1_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
115 { "CPU_SSE4_2_FLAGS",
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
117 { "CPU_ANY_SSE_FLAGS",
118 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX" },
125 { "CPU_XSAVEOPT_FLAGS",
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
129 { "CPU_PCLMUL_FLAGS",
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
136 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
141 { "CPU_RDTSCP_FLAGS",
145 { "CPU_FSGSBASE_FLAGS",
153 { "CPU_3DNOWA_FLAGS",
154 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
155 { "CPU_PADLOCK_FLAGS",
160 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
164 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
165 { "CPU_ANY_AVX_FLAGS",
171 static initializer operand_type_init
[] =
173 { "OPERAND_TYPE_NONE",
175 { "OPERAND_TYPE_REG8",
177 { "OPERAND_TYPE_REG16",
179 { "OPERAND_TYPE_REG32",
181 { "OPERAND_TYPE_REG64",
183 { "OPERAND_TYPE_IMM1",
185 { "OPERAND_TYPE_IMM8",
187 { "OPERAND_TYPE_IMM8S",
189 { "OPERAND_TYPE_IMM16",
191 { "OPERAND_TYPE_IMM32",
193 { "OPERAND_TYPE_IMM32S",
195 { "OPERAND_TYPE_IMM64",
197 { "OPERAND_TYPE_BASEINDEX",
199 { "OPERAND_TYPE_DISP8",
201 { "OPERAND_TYPE_DISP16",
203 { "OPERAND_TYPE_DISP32",
205 { "OPERAND_TYPE_DISP32S",
207 { "OPERAND_TYPE_DISP64",
209 { "OPERAND_TYPE_INOUTPORTREG",
211 { "OPERAND_TYPE_SHIFTCOUNT",
213 { "OPERAND_TYPE_CONTROL",
215 { "OPERAND_TYPE_TEST",
217 { "OPERAND_TYPE_DEBUG",
219 { "OPERAND_TYPE_FLOATREG",
221 { "OPERAND_TYPE_FLOATACC",
223 { "OPERAND_TYPE_SREG2",
225 { "OPERAND_TYPE_SREG3",
227 { "OPERAND_TYPE_ACC",
229 { "OPERAND_TYPE_JUMPABSOLUTE",
231 { "OPERAND_TYPE_REGMMX",
233 { "OPERAND_TYPE_REGXMM",
235 { "OPERAND_TYPE_REGYMM",
237 { "OPERAND_TYPE_ESSEG",
239 { "OPERAND_TYPE_ACC32",
241 { "OPERAND_TYPE_ACC64",
243 { "OPERAND_TYPE_INOUTPORTREG",
245 { "OPERAND_TYPE_REG16_INOUTPORTREG",
246 "Reg16|InOutPortReg" },
247 { "OPERAND_TYPE_DISP16_32",
249 { "OPERAND_TYPE_ANYDISP",
250 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
251 { "OPERAND_TYPE_IMM16_32",
253 { "OPERAND_TYPE_IMM16_32S",
255 { "OPERAND_TYPE_IMM16_32_32S",
256 "Imm16|Imm32|Imm32S" },
257 { "OPERAND_TYPE_IMM32_32S_DISP32",
258 "Imm32|Imm32S|Disp32" },
259 { "OPERAND_TYPE_IMM64_DISP64",
261 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
262 "Imm32|Imm32S|Imm64|Disp32" },
263 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
264 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
265 { "OPERAND_TYPE_VEC_IMM4",
269 typedef struct bitfield
276 #define BITFIELD(n) { n, 0, #n }
278 static bitfield cpu_flags
[] =
286 BITFIELD (CpuClflush
),
287 BITFIELD (CpuSYSCALL
),
292 BITFIELD (CpuFISTTP
),
298 BITFIELD (CpuSSE4_1
),
299 BITFIELD (CpuSSE4_2
),
304 BITFIELD (Cpu3dnowA
),
305 BITFIELD (CpuPadLock
),
311 BITFIELD (CpuXsaveopt
),
313 BITFIELD (CpuPCLMUL
),
321 BITFIELD (CpuRdtscp
),
322 BITFIELD (CpuFSGSBase
),
328 BITFIELD (CpuUnused
),
332 static bitfield opcode_modifiers
[] =
338 BITFIELD (ShortForm
),
340 BITFIELD (JumpDword
),
342 BITFIELD (JumpInterSegment
),
349 BITFIELD (IgnoreSize
),
350 BITFIELD (DefaultSize
),
359 BITFIELD (IsLockable
),
360 BITFIELD (RegKludge
),
361 BITFIELD (FirstXmm0
),
362 BITFIELD (Implicit1stXmm0
),
365 BITFIELD (AddrPrefixOp0
),
374 BITFIELD (VexOpcode
),
375 BITFIELD (VexSources
),
376 BITFIELD (VexImmExt
),
380 BITFIELD (ATTMnemonic
),
381 BITFIELD (ATTSyntax
),
382 BITFIELD (IntelSyntax
),
385 static bitfield operand_types
[] =
402 BITFIELD (BaseIndex
),
408 BITFIELD (InOutPortReg
),
409 BITFIELD (ShiftCount
),
417 BITFIELD (JumpAbsolute
),
429 BITFIELD (Unspecified
),
437 static const char *filename
;
440 compare (const void *x
, const void *y
)
442 const bitfield
*xp
= (const bitfield
*) x
;
443 const bitfield
*yp
= (const bitfield
*) y
;
444 return xp
->position
- yp
->position
;
448 fail (const char *message
, ...)
452 va_start (args
, message
);
453 fprintf (stderr
, _("%s: Error: "), program_name
);
454 vfprintf (stderr
, message
, args
);
460 process_copyright (FILE *fp
)
462 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
463 /* Copyright 2007, 2008, 2009, 2010\n\
464 Free Software Foundation, Inc.\n\
466 This file is part of the GNU opcodes library.\n\
468 This library is free software; you can redistribute it and/or modify\n\
469 it under the terms of the GNU General Public License as published by\n\
470 the Free Software Foundation; either version 3, or (at your option)\n\
471 any later version.\n\
473 It is distributed in the hope that it will be useful, but WITHOUT\n\
474 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
475 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
476 License for more details.\n\
478 You should have received a copy of the GNU General Public License\n\
479 along with this program; if not, write to the Free Software\n\
480 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
481 MA 02110-1301, USA. */\n");
484 /* Remove leading white spaces. */
487 remove_leading_whitespaces (char *str
)
489 while (ISSPACE (*str
))
494 /* Remove trailing white spaces. */
497 remove_trailing_whitespaces (char *str
)
499 size_t last
= strlen (str
);
507 if (ISSPACE (str
[last
]))
515 /* Find next field separated by SEP and terminate it. Return a
516 pointer to the one after it. */
519 next_field (char *str
, char sep
, char **next
, char *last
)
523 p
= remove_leading_whitespaces (str
);
524 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
527 remove_trailing_whitespaces (p
);
538 set_bitfield (const char *f
, bitfield
*array
, int value
,
539 unsigned int size
, int lineno
)
543 if (strcmp (f
, "CpuFP") == 0)
545 set_bitfield("Cpu387", array
, value
, size
, lineno
);
546 set_bitfield("Cpu287", array
, value
, size
, lineno
);
549 else if (strcmp (f
, "Mmword") == 0)
551 else if (strcmp (f
, "Oword") == 0)
554 for (i
= 0; i
< size
; i
++)
555 if (strcasecmp (array
[i
].name
, f
) == 0)
557 array
[i
].value
= value
;
563 const char *v
= strchr (f
, '=');
570 for (i
= 0; i
< size
; i
++)
571 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
573 value
= strtol (v
+ 1, &end
, 0);
576 array
[i
].value
= value
;
585 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
587 fail (_("Unknown bitfield: %s\n"), f
);
591 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
592 int macro
, const char *comma
, const char *indent
)
596 fprintf (table
, "%s{ { ", indent
);
598 for (i
= 0; i
< size
- 1; i
++)
600 fprintf (table
, "%d, ", flags
[i
].value
);
601 if (((i
+ 1) % 20) == 0)
603 /* We need \\ for macro. */
605 fprintf (table
, " \\\n %s", indent
);
607 fprintf (table
, "\n %s", indent
);
611 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
615 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
616 const char *comma
, const char *indent
,
619 char *str
, *next
, *last
;
621 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
623 /* Copy the default cpu flags. */
624 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
626 if (strcasecmp (flag
, "unknown") == 0)
628 /* We turn on everything except for cpu64 in case of
629 CPU_UNKNOWN_FLAGS. */
630 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
631 if (flags
[i
].position
!= Cpu64
)
634 else if (flag
[0] == '~')
636 last
= flag
+ strlen (flag
);
643 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
650 /* First we turn on everything except for cpu64. */
651 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
652 if (flags
[i
].position
!= Cpu64
)
655 /* Turn off selective bits. */
656 for (; next
&& next
< last
; )
658 str
= next_field (next
, '|', &next
, last
);
660 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
663 else if (strcmp (flag
, "0"))
665 /* Turn on selective bits. */
666 last
= flag
+ strlen (flag
);
667 for (next
= flag
; next
&& next
< last
; )
669 str
= next_field (next
, '|', &next
, last
);
671 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
675 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
680 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
684 fprintf (table
, " { ");
686 for (i
= 0; i
< size
- 1; i
++)
688 fprintf (table
, "%d, ", modifier
[i
].value
);
689 if (((i
+ 1) % 20) == 0)
690 fprintf (table
, "\n ");
693 fprintf (table
, "%d },\n", modifier
[i
].value
);
697 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
699 char *str
, *next
, *last
;
700 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
702 /* Copy the default opcode modifier. */
703 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
705 if (strcmp (mod
, "0"))
707 last
= mod
+ strlen (mod
);
708 for (next
= mod
; next
&& next
< last
; )
710 str
= next_field (next
, '|', &next
, last
);
712 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
716 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
720 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
721 int macro
, const char *indent
)
725 fprintf (table
, "{ { ");
727 for (i
= 0; i
< size
- 1; i
++)
729 fprintf (table
, "%d, ", types
[i
].value
);
730 if (((i
+ 1) % 20) == 0)
732 /* We need \\ for macro. */
734 fprintf (table
, "\\\n%s", indent
);
736 fprintf (table
, "\n%s", indent
);
740 fprintf (table
, "%d } }", types
[i
].value
);
744 process_i386_operand_type (FILE *table
, char *op
, int macro
,
745 const char *indent
, int lineno
)
747 char *str
, *next
, *last
;
748 bitfield types
[ARRAY_SIZE (operand_types
)];
750 /* Copy the default operand type. */
751 memcpy (types
, operand_types
, sizeof (types
));
753 if (strcmp (op
, "0"))
755 last
= op
+ strlen (op
);
756 for (next
= op
; next
&& next
< last
; )
758 str
= next_field (next
, '|', &next
, last
);
760 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
763 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
768 output_i386_opcode (FILE *table
, const char *name
, char *str
,
769 char *last
, int lineno
)
772 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
773 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
775 /* Find number of operands. */
776 operands
= next_field (str
, ',', &str
, last
);
778 /* Find base_opcode. */
779 base_opcode
= next_field (str
, ',', &str
, last
);
781 /* Find extension_opcode. */
782 extension_opcode
= next_field (str
, ',', &str
, last
);
784 /* Find opcode_length. */
785 opcode_length
= next_field (str
, ',', &str
, last
);
787 /* Find cpu_flags. */
788 cpu_flags
= next_field (str
, ',', &str
, last
);
790 /* Find opcode_modifier. */
791 opcode_modifier
= next_field (str
, ',', &str
, last
);
793 /* Remove the first {. */
794 str
= remove_leading_whitespaces (str
);
797 str
= remove_leading_whitespaces (str
+ 1);
801 /* There are at least "X}". */
805 /* Remove trailing white spaces and }. */
809 if (ISSPACE (str
[i
]) || str
[i
] == '}')
818 /* Find operand_types. */
819 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
823 operand_types
[i
] = NULL
;
827 operand_types
[i
] = next_field (str
, ',', &str
, last
);
828 if (*operand_types
[i
] == '0')
831 operand_types
[i
] = NULL
;
836 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
837 name
, operands
, base_opcode
, extension_opcode
,
840 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
842 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
844 fprintf (table
, " { ");
846 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
848 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
851 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
856 fprintf (table
, ",\n ");
858 process_i386_operand_type (table
, operand_types
[i
], 0,
861 fprintf (table
, " } },\n");
864 struct opcode_hash_entry
866 struct opcode_hash_entry
*next
;
872 /* Calculate the hash value of an opcode hash entry P. */
875 opcode_hash_hash (const void *p
)
877 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
878 return htab_hash_string (entry
->name
);
881 /* Compare a string Q against an opcode hash entry P. */
884 opcode_hash_eq (const void *p
, const void *q
)
886 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
887 const char *name
= (const char *) q
;
888 return strcmp (name
, entry
->name
) == 0;
892 process_i386_opcodes (FILE *table
)
897 char *str
, *p
, *last
, *name
;
898 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
899 htab_t opcode_hash_table
;
900 struct opcode_hash_entry
**opcode_array
;
901 unsigned int opcode_array_size
= 1024;
904 filename
= "i386-opc.tbl";
905 fp
= fopen (filename
, "r");
908 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
912 opcode_array
= (struct opcode_hash_entry
**)
913 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
915 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
916 opcode_hash_eq
, NULL
,
919 fprintf (table
, "\n/* i386 opcode table. */\n\n");
920 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
922 /* Put everything on opcode array. */
925 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
930 p
= remove_leading_whitespaces (buf
);
933 str
= strstr (p
, "//");
937 /* Remove trailing white spaces. */
938 remove_trailing_whitespaces (p
);
943 /* Ignore comments. */
951 last
= p
+ strlen (p
);
954 name
= next_field (p
, ',', &str
, last
);
956 /* Get the slot in hash table. */
957 hash_slot
= (struct opcode_hash_entry
**)
958 htab_find_slot_with_hash (opcode_hash_table
, name
,
959 htab_hash_string (name
),
962 if (*hash_slot
== NULL
)
964 /* It is the new one. Put it on opcode array. */
965 if (i
>= opcode_array_size
)
967 /* Grow the opcode array when needed. */
968 opcode_array_size
+= 1024;
969 opcode_array
= (struct opcode_hash_entry
**)
970 xrealloc (opcode_array
,
971 sizeof (*opcode_array
) * opcode_array_size
);
974 opcode_array
[i
] = (struct opcode_hash_entry
*)
975 xmalloc (sizeof (struct opcode_hash_entry
));
976 opcode_array
[i
]->next
= NULL
;
977 opcode_array
[i
]->name
= xstrdup (name
);
978 opcode_array
[i
]->opcode
= xstrdup (str
);
979 opcode_array
[i
]->lineno
= lineno
;
980 *hash_slot
= opcode_array
[i
];
985 /* Append it to the existing one. */
987 while ((*entry
) != NULL
)
988 entry
= &(*entry
)->next
;
989 *entry
= (struct opcode_hash_entry
*)
990 xmalloc (sizeof (struct opcode_hash_entry
));
991 (*entry
)->next
= NULL
;
992 (*entry
)->name
= (*hash_slot
)->name
;
993 (*entry
)->opcode
= xstrdup (str
);
994 (*entry
)->lineno
= lineno
;
998 /* Process opcode array. */
999 for (j
= 0; j
< i
; j
++)
1001 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1005 lineno
= next
->lineno
;
1006 last
= str
+ strlen (str
);
1007 output_i386_opcode (table
, name
, str
, last
, lineno
);
1013 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1015 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1017 process_i386_opcode_modifier (table
, "0", -1);
1019 fprintf (table
, " { ");
1020 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1021 fprintf (table
, " } }\n");
1023 fprintf (table
, "};\n");
1027 process_i386_registers (FILE *table
)
1031 char *str
, *p
, *last
;
1032 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1033 char *dw2_32_num
, *dw2_64_num
;
1036 filename
= "i386-reg.tbl";
1037 fp
= fopen (filename
, "r");
1039 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1042 fprintf (table
, "\n/* i386 register table. */\n\n");
1043 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1047 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1052 p
= remove_leading_whitespaces (buf
);
1054 /* Skip comments. */
1055 str
= strstr (p
, "//");
1059 /* Remove trailing white spaces. */
1060 remove_trailing_whitespaces (p
);
1065 fprintf (table
, "%s\n", p
);
1073 last
= p
+ strlen (p
);
1075 /* Find reg_name. */
1076 reg_name
= next_field (p
, ',', &str
, last
);
1078 /* Find reg_type. */
1079 reg_type
= next_field (str
, ',', &str
, last
);
1081 /* Find reg_flags. */
1082 reg_flags
= next_field (str
, ',', &str
, last
);
1085 reg_num
= next_field (str
, ',', &str
, last
);
1087 fprintf (table
, " { \"%s\",\n ", reg_name
);
1089 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1091 /* Find 32-bit Dwarf2 register number. */
1092 dw2_32_num
= next_field (str
, ',', &str
, last
);
1094 /* Find 64-bit Dwarf2 register number. */
1095 dw2_64_num
= next_field (str
, ',', &str
, last
);
1097 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1098 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1103 fprintf (table
, "};\n");
1105 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1109 process_i386_initializers (void)
1112 FILE *fp
= fopen ("i386-init.h", "w");
1116 fail (_("can't create i386-init.h, errno = %s\n"),
1119 process_copyright (fp
);
1121 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1123 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1124 init
= xstrdup (cpu_flag_init
[i
].init
);
1125 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1129 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1131 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1132 init
= xstrdup (operand_type_init
[i
].init
);
1133 process_i386_operand_type (fp
, init
, 1, " ", -1);
1141 /* Program options. */
1142 #define OPTION_SRCDIR 200
1144 struct option long_options
[] =
1146 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1147 {"debug", no_argument
, NULL
, 'd'},
1148 {"version", no_argument
, NULL
, 'V'},
1149 {"help", no_argument
, NULL
, 'h'},
1150 {0, no_argument
, NULL
, 0}
1154 print_version (void)
1156 printf ("%s: version 1.0\n", program_name
);
1161 usage (FILE * stream
, int status
)
1163 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1169 main (int argc
, char **argv
)
1171 extern int chdir (char *);
1172 char *srcdir
= NULL
;
1176 program_name
= *argv
;
1177 xmalloc_set_program_name (program_name
);
1179 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1204 if (chdir (srcdir
) != 0)
1205 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1206 srcdir
, xstrerror (errno
));
1208 /* Check the unused bitfield in i386_cpu_flags. */
1210 c
= CpuNumOfBits
- CpuMax
- 1;
1212 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1215 /* Check the unused bitfield in i386_operand_type. */
1217 c
= OTNumOfBits
- OTMax
- 1;
1219 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1222 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1225 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1226 sizeof (opcode_modifiers
[0]), compare
);
1228 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1229 sizeof (operand_types
[0]), compare
);
1231 table
= fopen ("i386-tbl.h", "w");
1233 fail (_("can't create i386-tbl.h, errno = %s\n"),
1236 process_copyright (table
);
1238 process_i386_opcodes (table
);
1239 process_i386_registers (table
);
1240 process_i386_initializers ();