1 /* Copyright 2007, 2008, 2009
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" },
126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
127 { "CPU_PCLMUL_FLAGS",
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
139 { "CPU_RDTSCP_FLAGS",
145 { "CPU_3DNOWA_FLAGS",
146 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
147 { "CPU_PADLOCK_FLAGS",
152 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
156 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
157 { "CPU_ANY_AVX_FLAGS",
163 static initializer operand_type_init
[] =
165 { "OPERAND_TYPE_NONE",
167 { "OPERAND_TYPE_REG8",
169 { "OPERAND_TYPE_REG16",
171 { "OPERAND_TYPE_REG32",
173 { "OPERAND_TYPE_REG64",
175 { "OPERAND_TYPE_IMM1",
177 { "OPERAND_TYPE_IMM8",
179 { "OPERAND_TYPE_IMM8S",
181 { "OPERAND_TYPE_IMM16",
183 { "OPERAND_TYPE_IMM32",
185 { "OPERAND_TYPE_IMM32S",
187 { "OPERAND_TYPE_IMM64",
189 { "OPERAND_TYPE_BASEINDEX",
191 { "OPERAND_TYPE_DISP8",
193 { "OPERAND_TYPE_DISP16",
195 { "OPERAND_TYPE_DISP32",
197 { "OPERAND_TYPE_DISP32S",
199 { "OPERAND_TYPE_DISP64",
201 { "OPERAND_TYPE_INOUTPORTREG",
203 { "OPERAND_TYPE_SHIFTCOUNT",
205 { "OPERAND_TYPE_CONTROL",
207 { "OPERAND_TYPE_TEST",
209 { "OPERAND_TYPE_DEBUG",
211 { "OPERAND_TYPE_FLOATREG",
213 { "OPERAND_TYPE_FLOATACC",
215 { "OPERAND_TYPE_SREG2",
217 { "OPERAND_TYPE_SREG3",
219 { "OPERAND_TYPE_ACC",
221 { "OPERAND_TYPE_JUMPABSOLUTE",
223 { "OPERAND_TYPE_REGMMX",
225 { "OPERAND_TYPE_REGXMM",
227 { "OPERAND_TYPE_REGYMM",
229 { "OPERAND_TYPE_ESSEG",
231 { "OPERAND_TYPE_ACC32",
233 { "OPERAND_TYPE_ACC64",
235 { "OPERAND_TYPE_INOUTPORTREG",
237 { "OPERAND_TYPE_REG16_INOUTPORTREG",
238 "Reg16|InOutPortReg" },
239 { "OPERAND_TYPE_DISP16_32",
241 { "OPERAND_TYPE_ANYDISP",
242 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
243 { "OPERAND_TYPE_IMM16_32",
245 { "OPERAND_TYPE_IMM16_32S",
247 { "OPERAND_TYPE_IMM16_32_32S",
248 "Imm16|Imm32|Imm32S" },
249 { "OPERAND_TYPE_IMM32_32S_DISP32",
250 "Imm32|Imm32S|Disp32" },
251 { "OPERAND_TYPE_IMM64_DISP64",
253 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
254 "Imm32|Imm32S|Imm64|Disp32" },
255 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
256 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
259 typedef struct bitfield
266 #define BITFIELD(n) { n, 0, #n }
268 static bitfield cpu_flags
[] =
276 BITFIELD (CpuClflush
),
277 BITFIELD (CpuSYSCALL
),
282 BITFIELD (CpuFISTTP
),
288 BITFIELD (CpuSSE4_1
),
289 BITFIELD (CpuSSE4_2
),
294 BITFIELD (Cpu3dnowA
),
295 BITFIELD (CpuPadLock
),
302 BITFIELD (CpuPCLMUL
),
310 BITFIELD (CpuRdtscp
),
314 BITFIELD (CpuUnused
),
318 static bitfield opcode_modifiers
[] =
324 BITFIELD (ShortForm
),
326 BITFIELD (JumpDword
),
328 BITFIELD (JumpInterSegment
),
335 BITFIELD (IgnoreSize
),
336 BITFIELD (DefaultSize
),
345 BITFIELD (IsLockable
),
346 BITFIELD (RegKludge
),
347 BITFIELD (FirstXmm0
),
348 BITFIELD (Implicit1stXmm0
),
351 BITFIELD (AddrPrefixOp0
),
360 BITFIELD (VexOpcode
),
361 BITFIELD (VexSources
),
362 BITFIELD (VexImmExt
),
366 BITFIELD (ATTMnemonic
),
367 BITFIELD (ATTSyntax
),
368 BITFIELD (IntelSyntax
),
371 static bitfield operand_types
[] =
388 BITFIELD (BaseIndex
),
394 BITFIELD (InOutPortReg
),
395 BITFIELD (ShiftCount
),
403 BITFIELD (JumpAbsolute
),
415 BITFIELD (Unspecified
),
422 static const char *filename
;
425 compare (const void *x
, const void *y
)
427 const bitfield
*xp
= (const bitfield
*) x
;
428 const bitfield
*yp
= (const bitfield
*) y
;
429 return xp
->position
- yp
->position
;
433 fail (const char *message
, ...)
437 va_start (args
, message
);
438 fprintf (stderr
, _("%s: Error: "), program_name
);
439 vfprintf (stderr
, message
, args
);
445 process_copyright (FILE *fp
)
447 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
448 /* Copyright 2007, 2008, 2009\n\
449 Free Software Foundation, Inc.\n\
451 This file is part of the GNU opcodes library.\n\
453 This library is free software; you can redistribute it and/or modify\n\
454 it under the terms of the GNU General Public License as published by\n\
455 the Free Software Foundation; either version 3, or (at your option)\n\
456 any later version.\n\
458 It is distributed in the hope that it will be useful, but WITHOUT\n\
459 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
460 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
461 License for more details.\n\
463 You should have received a copy of the GNU General Public License\n\
464 along with this program; if not, write to the Free Software\n\
465 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
466 MA 02110-1301, USA. */\n");
469 /* Remove leading white spaces. */
472 remove_leading_whitespaces (char *str
)
474 while (ISSPACE (*str
))
479 /* Remove trailing white spaces. */
482 remove_trailing_whitespaces (char *str
)
484 size_t last
= strlen (str
);
492 if (ISSPACE (str
[last
]))
500 /* Find next field separated by SEP and terminate it. Return a
501 pointer to the one after it. */
504 next_field (char *str
, char sep
, char **next
, char *last
)
508 p
= remove_leading_whitespaces (str
);
509 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
512 remove_trailing_whitespaces (p
);
523 set_bitfield (const char *f
, bitfield
*array
, int value
,
524 unsigned int size
, int lineno
)
528 if (strcmp (f
, "CpuFP") == 0)
530 set_bitfield("Cpu387", array
, value
, size
, lineno
);
531 set_bitfield("Cpu287", array
, value
, size
, lineno
);
534 else if (strcmp (f
, "Mmword") == 0)
536 else if (strcmp (f
, "Oword") == 0)
539 for (i
= 0; i
< size
; i
++)
540 if (strcasecmp (array
[i
].name
, f
) == 0)
542 array
[i
].value
= value
;
548 const char *v
= strchr (f
, '=');
555 for (i
= 0; i
< size
; i
++)
556 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
558 value
= strtol (v
+ 1, &end
, 0);
561 array
[i
].value
= value
;
570 fail (_("%s: %d: Unknown bitfield: %s\n"), filename
, lineno
, f
);
572 fail (_("Unknown bitfield: %s\n"), f
);
576 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
577 int macro
, const char *comma
, const char *indent
)
581 fprintf (table
, "%s{ { ", indent
);
583 for (i
= 0; i
< size
- 1; i
++)
585 fprintf (table
, "%d, ", flags
[i
].value
);
586 if (((i
+ 1) % 20) == 0)
588 /* We need \\ for macro. */
590 fprintf (table
, " \\\n %s", indent
);
592 fprintf (table
, "\n %s", indent
);
596 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
600 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
601 const char *comma
, const char *indent
,
604 char *str
, *next
, *last
;
606 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
608 /* Copy the default cpu flags. */
609 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
611 if (strcasecmp (flag
, "unknown") == 0)
613 /* We turn on everything except for cpu64 in case of
614 CPU_UNKNOWN_FLAGS. */
615 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
616 if (flags
[i
].position
!= Cpu64
)
619 else if (flag
[0] == '~')
621 last
= flag
+ strlen (flag
);
628 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename
,
635 /* First we turn on everything except for cpu64. */
636 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
637 if (flags
[i
].position
!= Cpu64
)
640 /* Turn off selective bits. */
641 for (; next
&& next
< last
; )
643 str
= next_field (next
, '|', &next
, last
);
645 set_bitfield (str
, flags
, 0, ARRAY_SIZE (flags
), lineno
);
648 else if (strcmp (flag
, "0"))
650 /* Turn on selective bits. */
651 last
= flag
+ strlen (flag
);
652 for (next
= flag
; next
&& next
< last
; )
654 str
= next_field (next
, '|', &next
, last
);
656 set_bitfield (str
, flags
, 1, ARRAY_SIZE (flags
), lineno
);
660 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
665 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
669 fprintf (table
, " { ");
671 for (i
= 0; i
< size
- 1; i
++)
673 fprintf (table
, "%d, ", modifier
[i
].value
);
674 if (((i
+ 1) % 20) == 0)
675 fprintf (table
, "\n ");
678 fprintf (table
, "%d },\n", modifier
[i
].value
);
682 process_i386_opcode_modifier (FILE *table
, char *mod
, int lineno
)
684 char *str
, *next
, *last
;
685 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
687 /* Copy the default opcode modifier. */
688 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
690 if (strcmp (mod
, "0"))
692 last
= mod
+ strlen (mod
);
693 for (next
= mod
; next
&& next
< last
; )
695 str
= next_field (next
, '|', &next
, last
);
697 set_bitfield (str
, modifiers
, 1, ARRAY_SIZE (modifiers
),
701 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
705 output_operand_type (FILE *table
, bitfield
*types
, unsigned int size
,
706 int macro
, const char *indent
)
710 fprintf (table
, "{ { ");
712 for (i
= 0; i
< size
- 1; i
++)
714 fprintf (table
, "%d, ", types
[i
].value
);
715 if (((i
+ 1) % 20) == 0)
717 /* We need \\ for macro. */
719 fprintf (table
, "\\\n%s", indent
);
721 fprintf (table
, "\n%s", indent
);
725 fprintf (table
, "%d } }", types
[i
].value
);
729 process_i386_operand_type (FILE *table
, char *op
, int macro
,
730 const char *indent
, int lineno
)
732 char *str
, *next
, *last
;
733 bitfield types
[ARRAY_SIZE (operand_types
)];
735 /* Copy the default operand type. */
736 memcpy (types
, operand_types
, sizeof (types
));
738 if (strcmp (op
, "0"))
740 last
= op
+ strlen (op
);
741 for (next
= op
; next
&& next
< last
; )
743 str
= next_field (next
, '|', &next
, last
);
745 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
748 output_operand_type (table
, types
, ARRAY_SIZE (types
), macro
,
753 output_i386_opcode (FILE *table
, const char *name
, char *str
,
754 char *last
, int lineno
)
757 char *operands
, *base_opcode
, *extension_opcode
, *opcode_length
;
758 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
760 /* Find number of operands. */
761 operands
= next_field (str
, ',', &str
, last
);
763 /* Find base_opcode. */
764 base_opcode
= next_field (str
, ',', &str
, last
);
766 /* Find extension_opcode. */
767 extension_opcode
= next_field (str
, ',', &str
, last
);
769 /* Find opcode_length. */
770 opcode_length
= next_field (str
, ',', &str
, last
);
772 /* Find cpu_flags. */
773 cpu_flags
= next_field (str
, ',', &str
, last
);
775 /* Find opcode_modifier. */
776 opcode_modifier
= next_field (str
, ',', &str
, last
);
778 /* Remove the first {. */
779 str
= remove_leading_whitespaces (str
);
782 str
= remove_leading_whitespaces (str
+ 1);
786 /* There are at least "X}". */
790 /* Remove trailing white spaces and }. */
794 if (ISSPACE (str
[i
]) || str
[i
] == '}')
803 /* Find operand_types. */
804 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
808 operand_types
[i
] = NULL
;
812 operand_types
[i
] = next_field (str
, ',', &str
, last
);
813 if (*operand_types
[i
] == '0')
816 operand_types
[i
] = NULL
;
821 fprintf (table
, " { \"%s\", %s, %s, %s, %s,\n",
822 name
, operands
, base_opcode
, extension_opcode
,
825 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
827 process_i386_opcode_modifier (table
, opcode_modifier
, lineno
);
829 fprintf (table
, " { ");
831 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
833 if (operand_types
[i
] == NULL
|| *operand_types
[i
] == '0')
836 process_i386_operand_type (table
, "0", 0, "\t ", lineno
);
841 fprintf (table
, ",\n ");
843 process_i386_operand_type (table
, operand_types
[i
], 0,
846 fprintf (table
, " } },\n");
849 struct opcode_hash_entry
851 struct opcode_hash_entry
*next
;
857 /* Calculate the hash value of an opcode hash entry P. */
860 opcode_hash_hash (const void *p
)
862 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
863 return htab_hash_string (entry
->name
);
866 /* Compare a string Q against an opcode hash entry P. */
869 opcode_hash_eq (const void *p
, const void *q
)
871 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
872 const char *name
= (const char *) q
;
873 return strcmp (name
, entry
->name
) == 0;
877 process_i386_opcodes (FILE *table
)
882 char *str
, *p
, *last
, *name
;
883 struct opcode_hash_entry
**hash_slot
, **entry
, *next
;
884 htab_t opcode_hash_table
;
885 struct opcode_hash_entry
**opcode_array
;
886 unsigned int opcode_array_size
= 1024;
889 filename
= "i386-opc.tbl";
890 fp
= fopen (filename
, "r");
893 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
897 opcode_array
= (struct opcode_hash_entry
**)
898 xmalloc (sizeof (*opcode_array
) * opcode_array_size
);
900 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
901 opcode_hash_eq
, NULL
,
904 fprintf (table
, "\n/* i386 opcode table. */\n\n");
905 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
907 /* Put everything on opcode array. */
910 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
915 p
= remove_leading_whitespaces (buf
);
918 str
= strstr (p
, "//");
922 /* Remove trailing white spaces. */
923 remove_trailing_whitespaces (p
);
928 /* Ignore comments. */
936 last
= p
+ strlen (p
);
939 name
= next_field (p
, ',', &str
, last
);
941 /* Get the slot in hash table. */
942 hash_slot
= (struct opcode_hash_entry
**)
943 htab_find_slot_with_hash (opcode_hash_table
, name
,
944 htab_hash_string (name
),
947 if (*hash_slot
== NULL
)
949 /* It is the new one. Put it on opcode array. */
950 if (i
>= opcode_array_size
)
952 /* Grow the opcode array when needed. */
953 opcode_array_size
+= 1024;
954 opcode_array
= (struct opcode_hash_entry
**)
955 xrealloc (opcode_array
,
956 sizeof (*opcode_array
) * opcode_array_size
);
959 opcode_array
[i
] = (struct opcode_hash_entry
*)
960 xmalloc (sizeof (struct opcode_hash_entry
));
961 opcode_array
[i
]->next
= NULL
;
962 opcode_array
[i
]->name
= xstrdup (name
);
963 opcode_array
[i
]->opcode
= xstrdup (str
);
964 opcode_array
[i
]->lineno
= lineno
;
965 *hash_slot
= opcode_array
[i
];
970 /* Append it to the existing one. */
972 while ((*entry
) != NULL
)
973 entry
= &(*entry
)->next
;
974 *entry
= (struct opcode_hash_entry
*)
975 xmalloc (sizeof (struct opcode_hash_entry
));
976 (*entry
)->next
= NULL
;
977 (*entry
)->name
= (*hash_slot
)->name
;
978 (*entry
)->opcode
= xstrdup (str
);
979 (*entry
)->lineno
= lineno
;
983 /* Process opcode array. */
984 for (j
= 0; j
< i
; j
++)
986 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
990 lineno
= next
->lineno
;
991 last
= str
+ strlen (str
);
992 output_i386_opcode (table
, name
, str
, last
, lineno
);
998 fprintf (table
, " { NULL, 0, 0, 0, 0,\n");
1000 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1002 process_i386_opcode_modifier (table
, "0", -1);
1004 fprintf (table
, " { ");
1005 process_i386_operand_type (table
, "0", 0, "\t ", -1);
1006 fprintf (table
, " } }\n");
1008 fprintf (table
, "};\n");
1012 process_i386_registers (FILE *table
)
1016 char *str
, *p
, *last
;
1017 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1018 char *dw2_32_num
, *dw2_64_num
;
1021 filename
= "i386-reg.tbl";
1022 fp
= fopen (filename
, "r");
1024 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1027 fprintf (table
, "\n/* i386 register table. */\n\n");
1028 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1032 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1037 p
= remove_leading_whitespaces (buf
);
1039 /* Skip comments. */
1040 str
= strstr (p
, "//");
1044 /* Remove trailing white spaces. */
1045 remove_trailing_whitespaces (p
);
1050 fprintf (table
, "%s\n", p
);
1058 last
= p
+ strlen (p
);
1060 /* Find reg_name. */
1061 reg_name
= next_field (p
, ',', &str
, last
);
1063 /* Find reg_type. */
1064 reg_type
= next_field (str
, ',', &str
, last
);
1066 /* Find reg_flags. */
1067 reg_flags
= next_field (str
, ',', &str
, last
);
1070 reg_num
= next_field (str
, ',', &str
, last
);
1072 fprintf (table
, " { \"%s\",\n ", reg_name
);
1074 process_i386_operand_type (table
, reg_type
, 0, "\t", lineno
);
1076 /* Find 32-bit Dwarf2 register number. */
1077 dw2_32_num
= next_field (str
, ',', &str
, last
);
1079 /* Find 64-bit Dwarf2 register number. */
1080 dw2_64_num
= next_field (str
, ',', &str
, last
);
1082 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1083 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1088 fprintf (table
, "};\n");
1090 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1094 process_i386_initializers (void)
1097 FILE *fp
= fopen ("i386-init.h", "w");
1101 fail (_("can't create i386-init.h, errno = %s\n"),
1104 process_copyright (fp
);
1106 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
1108 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
1109 init
= xstrdup (cpu_flag_init
[i
].init
);
1110 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
1114 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
1116 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
1117 init
= xstrdup (operand_type_init
[i
].init
);
1118 process_i386_operand_type (fp
, init
, 1, " ", -1);
1126 /* Program options. */
1127 #define OPTION_SRCDIR 200
1129 struct option long_options
[] =
1131 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1132 {"debug", no_argument
, NULL
, 'd'},
1133 {"version", no_argument
, NULL
, 'V'},
1134 {"help", no_argument
, NULL
, 'h'},
1135 {0, no_argument
, NULL
, 0}
1139 print_version (void)
1141 printf ("%s: version 1.0\n", program_name
);
1146 usage (FILE * stream
, int status
)
1148 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1154 main (int argc
, char **argv
)
1156 extern int chdir (char *);
1157 char *srcdir
= NULL
;
1161 program_name
= *argv
;
1162 xmalloc_set_program_name (program_name
);
1164 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1189 if (chdir (srcdir
) != 0)
1190 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1191 srcdir
, xstrerror (errno
));
1193 /* Check the unused bitfield in i386_cpu_flags. */
1195 c
= CpuNumOfBits
- CpuMax
- 1;
1197 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
1200 /* Check the unused bitfield in i386_operand_type. */
1202 c
= OTNumOfBits
- OTMax
- 1;
1204 fail (_("%d unused bits in i386_operand_type.\n"), c
);
1207 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
1210 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
1211 sizeof (opcode_modifiers
[0]), compare
);
1213 qsort (operand_types
, ARRAY_SIZE (operand_types
),
1214 sizeof (operand_types
[0]), compare
);
1216 table
= fopen ("i386-tbl.h", "w");
1218 fail (_("can't create i386-tbl.h, errno = %s\n"),
1221 process_copyright (table
);
1223 process_i386_opcodes (table
);
1224 process_i386_registers (table
);
1225 process_i386_initializers ();