opcodes/
[binutils-gdb.git] / opcodes / i386-gen.c
blobbed1c386c43a463eb58c2451f21e2ca11ba8d672
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)
9 any later version.
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. */
21 #include "sysdep.h"
22 #include <stdio.h>
23 #include <errno.h>
24 #include "getopt.h"
25 #include "libiberty.h"
26 #include "hashtab.h"
27 #include "safe-ctype.h"
29 #include "i386-opc.h"
31 #include <libintl.h>
32 #define _(String) gettext (String)
34 static const char *program_name = NULL;
35 static int debug = 0;
37 typedef struct initializer
39 const char *name;
40 const char *init;
41 } initializer;
43 static initializer cpu_flag_init[] =
45 { "CPU_UNKNOWN_FLAGS",
46 "unknown" },
47 { "CPU_GENERIC32_FLAGS",
48 "Cpu186|Cpu286|Cpu386" },
49 { "CPU_GENERIC64_FLAGS",
50 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuLM" },
51 { "CPU_NONE_FLAGS",
52 "0" },
53 { "CPU_I186_FLAGS",
54 "Cpu186" },
55 { "CPU_I286_FLAGS",
56 "Cpu186|Cpu286" },
57 { "CPU_I386_FLAGS",
58 "Cpu186|Cpu286|Cpu386" },
59 { "CPU_I486_FLAGS",
60 "Cpu186|Cpu286|Cpu386|Cpu486" },
61 { "CPU_I586_FLAGS",
62 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
63 { "CPU_I686_FLAGS",
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686" },
65 { "CPU_P2_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX" },
67 { "CPU_P3_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE" },
69 { "CPU_P4_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2" },
71 { "CPU_NOCONA_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
73 { "CPU_CORE_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
75 { "CPU_CORE2_FLAGS",
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
77 { "CPU_COREI7_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
79 { "CPU_K6_FLAGS",
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|CpuMMX" },
81 { "CPU_K6_2_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|CpuMMX|Cpu3dnow" },
83 { "CPU_ATHLON_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuMMX|Cpu3dnow|Cpu3dnowA" },
85 { "CPU_K8_FLAGS",
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
87 { "CPU_AMDFAM10_FLAGS",
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
89 { "CPU_CLFLUSH_FLAGS",
90 "CpuClflush" },
91 { "CPU_SYSCALL_FLAGS",
92 "CpuSYSCALL" },
93 { "CPU_MMX_FLAGS",
94 "CpuMMX" },
95 { "CPU_SSE_FLAGS",
96 "CpuMMX|CpuSSE" },
97 { "CPU_SSE2_FLAGS",
98 "CpuMMX|CpuSSE|CpuSSE2" },
99 { "CPU_SSE3_FLAGS",
100 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
101 { "CPU_SSSE3_FLAGS",
102 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
103 { "CPU_SSE4_1_FLAGS",
104 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
105 { "CPU_SSE4_2_FLAGS",
106 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
107 { "CPU_VMX_FLAGS",
108 "CpuVMX" },
109 { "CPU_SMX_FLAGS",
110 "CpuSMX" },
111 { "CPU_XSAVE_FLAGS",
112 "CpuXsave" },
113 { "CPU_AES_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
115 { "CPU_PCLMUL_FLAGS",
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
117 { "CPU_FMA_FLAGS",
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
119 { "CPU_MOVBE_FLAGS",
120 "CpuMovbe" },
121 { "CPU_RDTSCP_FLAGS",
122 "CpuRdtscp" },
123 { "CPU_EPT_FLAGS",
124 "CpuEPT" },
125 { "CPU_3DNOW_FLAGS",
126 "CpuMMX|Cpu3dnow" },
127 { "CPU_3DNOWA_FLAGS",
128 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
129 { "CPU_PADLOCK_FLAGS",
130 "CpuPadLock" },
131 { "CPU_SVME_FLAGS",
132 "CpuSVME" },
133 { "CPU_SSE4A_FLAGS",
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
135 { "CPU_ABM_FLAGS",
136 "CpuABM" },
137 { "CPU_SSE5_FLAGS",
138 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuSSE5"},
139 { "CPU_AVX_FLAGS",
140 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
143 static initializer operand_type_init[] =
145 { "OPERAND_TYPE_NONE",
146 "0" },
147 { "OPERAND_TYPE_REG8",
148 "Reg8" },
149 { "OPERAND_TYPE_REG16",
150 "Reg16" },
151 { "OPERAND_TYPE_REG32",
152 "Reg32" },
153 { "OPERAND_TYPE_REG64",
154 "Reg64" },
155 { "OPERAND_TYPE_IMM1",
156 "Imm1" },
157 { "OPERAND_TYPE_IMM8",
158 "Imm8" },
159 { "OPERAND_TYPE_IMM8S",
160 "Imm8S" },
161 { "OPERAND_TYPE_IMM16",
162 "Imm16" },
163 { "OPERAND_TYPE_IMM32",
164 "Imm32" },
165 { "OPERAND_TYPE_IMM32S",
166 "Imm32S" },
167 { "OPERAND_TYPE_IMM64",
168 "Imm64" },
169 { "OPERAND_TYPE_BASEINDEX",
170 "BaseIndex" },
171 { "OPERAND_TYPE_DISP8",
172 "Disp8" },
173 { "OPERAND_TYPE_DISP16",
174 "Disp16" },
175 { "OPERAND_TYPE_DISP32",
176 "Disp32" },
177 { "OPERAND_TYPE_DISP32S",
178 "Disp32S" },
179 { "OPERAND_TYPE_DISP64",
180 "Disp64" },
181 { "OPERAND_TYPE_INOUTPORTREG",
182 "InOutPortReg" },
183 { "OPERAND_TYPE_SHIFTCOUNT",
184 "ShiftCount" },
185 { "OPERAND_TYPE_CONTROL",
186 "Control" },
187 { "OPERAND_TYPE_TEST",
188 "Test" },
189 { "OPERAND_TYPE_DEBUG",
190 "FloatReg" },
191 { "OPERAND_TYPE_FLOATREG",
192 "FloatReg" },
193 { "OPERAND_TYPE_FLOATACC",
194 "FloatAcc" },
195 { "OPERAND_TYPE_SREG2",
196 "SReg2" },
197 { "OPERAND_TYPE_SREG3",
198 "SReg3" },
199 { "OPERAND_TYPE_ACC",
200 "Acc" },
201 { "OPERAND_TYPE_JUMPABSOLUTE",
202 "JumpAbsolute" },
203 { "OPERAND_TYPE_REGMMX",
204 "RegMMX" },
205 { "OPERAND_TYPE_REGXMM",
206 "RegXMM" },
207 { "OPERAND_TYPE_REGYMM",
208 "RegYMM" },
209 { "OPERAND_TYPE_ESSEG",
210 "EsSeg" },
211 { "OPERAND_TYPE_ACC32",
212 "Reg32|Acc|Dword" },
213 { "OPERAND_TYPE_ACC64",
214 "Reg64|Acc|Qword" },
215 { "OPERAND_TYPE_INOUTPORTREG",
216 "InOutPortReg" },
217 { "OPERAND_TYPE_REG16_INOUTPORTREG",
218 "Reg16|InOutPortReg" },
219 { "OPERAND_TYPE_DISP16_32",
220 "Disp16|Disp32" },
221 { "OPERAND_TYPE_ANYDISP",
222 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
223 { "OPERAND_TYPE_IMM16_32",
224 "Imm16|Imm32" },
225 { "OPERAND_TYPE_IMM16_32S",
226 "Imm16|Imm32S" },
227 { "OPERAND_TYPE_IMM16_32_32S",
228 "Imm16|Imm32|Imm32S" },
229 { "OPERAND_TYPE_IMM32_32S_DISP32",
230 "Imm32|Imm32S|Disp32" },
231 { "OPERAND_TYPE_IMM64_DISP64",
232 "Imm64|Disp64" },
233 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
234 "Imm32|Imm32S|Imm64|Disp32" },
235 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
236 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
239 typedef struct bitfield
241 int position;
242 int value;
243 const char *name;
244 } bitfield;
246 #define BITFIELD(n) { n, 0, #n }
248 static bitfield cpu_flags[] =
250 BITFIELD (Cpu186),
251 BITFIELD (Cpu286),
252 BITFIELD (Cpu386),
253 BITFIELD (Cpu486),
254 BITFIELD (Cpu586),
255 BITFIELD (Cpu686),
256 BITFIELD (CpuClflush),
257 BITFIELD (CpuSYSCALL),
258 BITFIELD (CpuMMX),
259 BITFIELD (CpuSSE),
260 BITFIELD (CpuSSE2),
261 BITFIELD (CpuSSE3),
262 BITFIELD (CpuSSSE3),
263 BITFIELD (CpuSSE4_1),
264 BITFIELD (CpuSSE4_2),
265 BITFIELD (CpuAVX),
266 BITFIELD (CpuSSE4a),
267 BITFIELD (CpuSSE5),
268 BITFIELD (Cpu3dnow),
269 BITFIELD (Cpu3dnowA),
270 BITFIELD (CpuPadLock),
271 BITFIELD (CpuSVME),
272 BITFIELD (CpuVMX),
273 BITFIELD (CpuSMX),
274 BITFIELD (CpuABM),
275 BITFIELD (CpuXsave),
276 BITFIELD (CpuAES),
277 BITFIELD (CpuPCLMUL),
278 BITFIELD (CpuFMA),
279 BITFIELD (CpuLM),
280 BITFIELD (CpuMovbe),
281 BITFIELD (CpuEPT),
282 BITFIELD (CpuRdtscp),
283 BITFIELD (Cpu64),
284 BITFIELD (CpuNo64),
285 #ifdef CpuUnused
286 BITFIELD (CpuUnused),
287 #endif
290 static bitfield opcode_modifiers[] =
292 BITFIELD (D),
293 BITFIELD (W),
294 BITFIELD (S),
295 BITFIELD (Modrm),
296 BITFIELD (ShortForm),
297 BITFIELD (Jump),
298 BITFIELD (JumpDword),
299 BITFIELD (JumpByte),
300 BITFIELD (JumpInterSegment),
301 BITFIELD (FloatMF),
302 BITFIELD (FloatR),
303 BITFIELD (FloatD),
304 BITFIELD (Size16),
305 BITFIELD (Size32),
306 BITFIELD (Size64),
307 BITFIELD (IgnoreSize),
308 BITFIELD (DefaultSize),
309 BITFIELD (No_bSuf),
310 BITFIELD (No_wSuf),
311 BITFIELD (No_lSuf),
312 BITFIELD (No_sSuf),
313 BITFIELD (No_qSuf),
314 BITFIELD (No_ldSuf),
315 BITFIELD (FWait),
316 BITFIELD (IsString),
317 BITFIELD (RegKludge),
318 BITFIELD (FirstXmm0),
319 BITFIELD (Implicit1stXmm0),
320 BITFIELD (ByteOkIntel),
321 BITFIELD (ToDword),
322 BITFIELD (ToQword),
323 BITFIELD (AddrPrefixOp0),
324 BITFIELD (IsPrefix),
325 BITFIELD (ImmExt),
326 BITFIELD (NoRex64),
327 BITFIELD (Rex64),
328 BITFIELD (Ugh),
329 BITFIELD (Drex),
330 BITFIELD (Drexv),
331 BITFIELD (Drexc),
332 BITFIELD (Vex),
333 BITFIELD (Vex256),
334 BITFIELD (VexNDS),
335 BITFIELD (VexNDD),
336 BITFIELD (VexW0),
337 BITFIELD (VexW1),
338 BITFIELD (Vex0F),
339 BITFIELD (Vex0F38),
340 BITFIELD (Vex0F3A),
341 BITFIELD (Vex3Sources),
342 BITFIELD (VexImmExt),
343 BITFIELD (SSE2AVX),
344 BITFIELD (NoAVX),
345 BITFIELD (OldGcc),
346 BITFIELD (ATTMnemonic),
347 BITFIELD (ATTSyntax),
348 BITFIELD (IntelSyntax),
351 static bitfield operand_types[] =
353 BITFIELD (Reg8),
354 BITFIELD (Reg16),
355 BITFIELD (Reg32),
356 BITFIELD (Reg64),
357 BITFIELD (FloatReg),
358 BITFIELD (RegMMX),
359 BITFIELD (RegXMM),
360 BITFIELD (RegYMM),
361 BITFIELD (Imm8),
362 BITFIELD (Imm8S),
363 BITFIELD (Imm16),
364 BITFIELD (Imm32),
365 BITFIELD (Imm32S),
366 BITFIELD (Imm64),
367 BITFIELD (Imm1),
368 BITFIELD (BaseIndex),
369 BITFIELD (Disp8),
370 BITFIELD (Disp16),
371 BITFIELD (Disp32),
372 BITFIELD (Disp32S),
373 BITFIELD (Disp64),
374 BITFIELD (InOutPortReg),
375 BITFIELD (ShiftCount),
376 BITFIELD (Control),
377 BITFIELD (Debug),
378 BITFIELD (Test),
379 BITFIELD (SReg2),
380 BITFIELD (SReg3),
381 BITFIELD (Acc),
382 BITFIELD (FloatAcc),
383 BITFIELD (JumpAbsolute),
384 BITFIELD (EsSeg),
385 BITFIELD (RegMem),
386 BITFIELD (Mem),
387 BITFIELD (Byte),
388 BITFIELD (Word),
389 BITFIELD (Dword),
390 BITFIELD (Fword),
391 BITFIELD (Qword),
392 BITFIELD (Tbyte),
393 BITFIELD (Xmmword),
394 BITFIELD (Ymmword),
395 BITFIELD (Unspecified),
396 BITFIELD (Anysize),
397 #ifdef OTUnused
398 BITFIELD (OTUnused),
399 #endif
402 static const char *filename;
404 static int
405 compare (const void *x, const void *y)
407 const bitfield *xp = (const bitfield *) x;
408 const bitfield *yp = (const bitfield *) y;
409 return xp->position - yp->position;
412 static void
413 fail (const char *message, ...)
415 va_list args;
417 va_start (args, message);
418 fprintf (stderr, _("%s: Error: "), program_name);
419 vfprintf (stderr, message, args);
420 va_end (args);
421 xexit (1);
424 static void
425 process_copyright (FILE *fp)
427 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
428 /* Copyright 2007, 2008, 2009\n\
429 Free Software Foundation, Inc.\n\
431 This file is part of the GNU opcodes library.\n\
433 This library is free software; you can redistribute it and/or modify\n\
434 it under the terms of the GNU General Public License as published by\n\
435 the Free Software Foundation; either version 3, or (at your option)\n\
436 any later version.\n\
438 It is distributed in the hope that it will be useful, but WITHOUT\n\
439 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
440 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
441 License for more details.\n\
443 You should have received a copy of the GNU General Public License\n\
444 along with this program; if not, write to the Free Software\n\
445 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
446 MA 02110-1301, USA. */\n");
449 /* Remove leading white spaces. */
451 static char *
452 remove_leading_whitespaces (char *str)
454 while (ISSPACE (*str))
455 str++;
456 return str;
459 /* Remove trailing white spaces. */
461 static void
462 remove_trailing_whitespaces (char *str)
464 size_t last = strlen (str);
466 if (last == 0)
467 return;
471 last--;
472 if (ISSPACE (str [last]))
473 str[last] = '\0';
474 else
475 break;
477 while (last != 0);
480 /* Find next field separated by SEP and terminate it. Return a
481 pointer to the one after it. */
483 static char *
484 next_field (char *str, char sep, char **next, char *last)
486 char *p;
488 p = remove_leading_whitespaces (str);
489 for (str = p; *str != sep && *str != '\0'; str++);
491 *str = '\0';
492 remove_trailing_whitespaces (p);
494 *next = str + 1;
496 if (p >= last)
497 abort ();
499 return p;
502 static void
503 set_bitfield (const char *f, bitfield *array, unsigned int size, int lineno)
505 unsigned int i;
507 if (strcmp (f, "Mmword") == 0)
508 f= "Qword";
509 else if (strcmp (f, "Oword") == 0)
510 f= "Xmmword";
512 for (i = 0; i < size; i++)
513 if (strcasecmp (array[i].name, f) == 0)
515 array[i].value = 1;
516 return;
519 if (lineno != -1)
520 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
521 else
522 fail (_("Unknown bitfield: %s\n"), f);
525 static void
526 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
527 int macro, const char *comma, const char *indent)
529 unsigned int i;
531 fprintf (table, "%s{ { ", indent);
533 for (i = 0; i < size - 1; i++)
535 fprintf (table, "%d, ", flags[i].value);
536 if (((i + 1) % 20) == 0)
538 /* We need \\ for macro. */
539 if (macro)
540 fprintf (table, " \\\n %s", indent);
541 else
542 fprintf (table, "\n %s", indent);
546 fprintf (table, "%d } }%s\n", flags[i].value, comma);
549 static void
550 process_i386_cpu_flag (FILE *table, char *flag, int macro,
551 const char *comma, const char *indent,
552 int lineno)
554 char *str, *next, *last;
555 bitfield flags [ARRAY_SIZE (cpu_flags)];
557 /* Copy the default cpu flags. */
558 memcpy (flags, cpu_flags, sizeof (cpu_flags));
560 if (strcasecmp (flag, "unknown") == 0)
562 unsigned int i;
564 /* We turn on everything except for cpu64 in case of
565 CPU_UNKNOWN_FLAGS. */
566 for (i = 0; i < ARRAY_SIZE (flags); i++)
567 if (flags[i].position != Cpu64)
568 flags[i].value = 1;
570 else if (strcmp (flag, "0"))
572 last = flag + strlen (flag);
573 for (next = flag; next && next < last; )
575 str = next_field (next, '|', &next, last);
576 if (str)
577 set_bitfield (str, flags, ARRAY_SIZE (flags), lineno);
581 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
582 comma, indent);
585 static void
586 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
588 unsigned int i;
590 fprintf (table, " { ");
592 for (i = 0; i < size - 1; i++)
594 fprintf (table, "%d, ", modifier[i].value);
595 if (((i + 1) % 20) == 0)
596 fprintf (table, "\n ");
599 fprintf (table, "%d },\n", modifier[i].value);
602 static void
603 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
605 char *str, *next, *last;
606 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
608 /* Copy the default opcode modifier. */
609 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
611 if (strcmp (mod, "0"))
613 last = mod + strlen (mod);
614 for (next = mod; next && next < last; )
616 str = next_field (next, '|', &next, last);
617 if (str)
618 set_bitfield (str, modifiers, ARRAY_SIZE (modifiers), lineno);
621 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
624 static void
625 output_operand_type (FILE *table, bitfield *types, unsigned int size,
626 int macro, const char *indent)
628 unsigned int i;
630 fprintf (table, "{ { ");
632 for (i = 0; i < size - 1; i++)
634 fprintf (table, "%d, ", types[i].value);
635 if (((i + 1) % 20) == 0)
637 /* We need \\ for macro. */
638 if (macro)
639 fprintf (table, "\\\n%s", indent);
640 else
641 fprintf (table, "\n%s", indent);
645 fprintf (table, "%d } }", types[i].value);
648 static void
649 process_i386_operand_type (FILE *table, char *op, int macro,
650 const char *indent, int lineno)
652 char *str, *next, *last;
653 bitfield types [ARRAY_SIZE (operand_types)];
655 /* Copy the default operand type. */
656 memcpy (types, operand_types, sizeof (types));
658 if (strcmp (op, "0"))
660 last = op + strlen (op);
661 for (next = op; next && next < last; )
663 str = next_field (next, '|', &next, last);
664 if (str)
665 set_bitfield (str, types, ARRAY_SIZE (types), lineno);
668 output_operand_type (table, types, ARRAY_SIZE (types), macro,
669 indent);
672 static void
673 output_i386_opcode (FILE *table, const char *name, char *str,
674 char *last, int lineno)
676 unsigned int i;
677 char *operands, *base_opcode, *extension_opcode, *opcode_length;
678 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
680 /* Find number of operands. */
681 operands = next_field (str, ',', &str, last);
683 /* Find base_opcode. */
684 base_opcode = next_field (str, ',', &str, last);
686 /* Find extension_opcode. */
687 extension_opcode = next_field (str, ',', &str, last);
689 /* Find opcode_length. */
690 opcode_length = next_field (str, ',', &str, last);
692 /* Find cpu_flags. */
693 cpu_flags = next_field (str, ',', &str, last);
695 /* Find opcode_modifier. */
696 opcode_modifier = next_field (str, ',', &str, last);
698 /* Remove the first {. */
699 str = remove_leading_whitespaces (str);
700 if (*str != '{')
701 abort ();
702 str = remove_leading_whitespaces (str + 1);
704 i = strlen (str);
706 /* There are at least "X}". */
707 if (i < 2)
708 abort ();
710 /* Remove trailing white spaces and }. */
713 i--;
714 if (ISSPACE (str[i]) || str[i] == '}')
715 str[i] = '\0';
716 else
717 break;
719 while (i != 0);
721 last = str + i;
723 /* Find operand_types. */
724 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
726 if (str >= last)
728 operand_types [i] = NULL;
729 break;
732 operand_types [i] = next_field (str, ',', &str, last);
733 if (*operand_types[i] == '0')
735 if (i != 0)
736 operand_types[i] = NULL;
737 break;
741 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
742 name, operands, base_opcode, extension_opcode,
743 opcode_length);
745 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
747 process_i386_opcode_modifier (table, opcode_modifier, lineno);
749 fprintf (table, " { ");
751 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
753 if (operand_types[i] == NULL || *operand_types[i] == '0')
755 if (i == 0)
756 process_i386_operand_type (table, "0", 0, "\t ", lineno);
757 break;
760 if (i != 0)
761 fprintf (table, ",\n ");
763 process_i386_operand_type (table, operand_types[i], 0,
764 "\t ", lineno);
766 fprintf (table, " } },\n");
769 struct opcode_hash_entry
771 struct opcode_hash_entry *next;
772 char *name;
773 char *opcode;
774 int lineno;
777 /* Calculate the hash value of an opcode hash entry P. */
779 static hashval_t
780 opcode_hash_hash (const void *p)
782 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
783 return htab_hash_string (entry->name);
786 /* Compare a string Q against an opcode hash entry P. */
788 static int
789 opcode_hash_eq (const void *p, const void *q)
791 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
792 const char *name = (const char *) q;
793 return strcmp (name, entry->name) == 0;
796 static void
797 process_i386_opcodes (FILE *table)
799 FILE *fp;
800 char buf[2048];
801 unsigned int i, j;
802 char *str, *p, *last, *name;
803 struct opcode_hash_entry **hash_slot, **entry, *next;
804 htab_t opcode_hash_table;
805 struct opcode_hash_entry **opcode_array;
806 unsigned int opcode_array_size = 1024;
807 int lineno = 0;
809 filename = "i386-opc.tbl";
810 fp = fopen (filename, "r");
812 if (fp == NULL)
813 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
814 xstrerror (errno));
816 i = 0;
817 opcode_array = (struct opcode_hash_entry **)
818 xmalloc (sizeof (*opcode_array) * opcode_array_size);
820 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
821 opcode_hash_eq, NULL,
822 xcalloc, free);
824 fprintf (table, "\n/* i386 opcode table. */\n\n");
825 fprintf (table, "const template i386_optab[] =\n{\n");
827 /* Put everything on opcode array. */
828 while (!feof (fp))
830 if (fgets (buf, sizeof (buf), fp) == NULL)
831 break;
833 lineno++;
835 p = remove_leading_whitespaces (buf);
837 /* Skip comments. */
838 str = strstr (p, "//");
839 if (str != NULL)
840 str[0] = '\0';
842 /* Remove trailing white spaces. */
843 remove_trailing_whitespaces (p);
845 switch (p[0])
847 case '#':
848 /* Ignore comments. */
849 case '\0':
850 continue;
851 break;
852 default:
853 break;
856 last = p + strlen (p);
858 /* Find name. */
859 name = next_field (p, ',', &str, last);
861 /* Get the slot in hash table. */
862 hash_slot = (struct opcode_hash_entry **)
863 htab_find_slot_with_hash (opcode_hash_table, name,
864 htab_hash_string (name),
865 INSERT);
867 if (*hash_slot == NULL)
869 /* It is the new one. Put it on opcode array. */
870 if (i >= opcode_array_size)
872 /* Grow the opcode array when needed. */
873 opcode_array_size += 1024;
874 opcode_array = (struct opcode_hash_entry **)
875 xrealloc (opcode_array,
876 sizeof (*opcode_array) * opcode_array_size);
879 opcode_array[i] = (struct opcode_hash_entry *)
880 xmalloc (sizeof (struct opcode_hash_entry));
881 opcode_array[i]->next = NULL;
882 opcode_array[i]->name = xstrdup (name);
883 opcode_array[i]->opcode = xstrdup (str);
884 opcode_array[i]->lineno = lineno;
885 *hash_slot = opcode_array[i];
886 i++;
888 else
890 /* Append it to the existing one. */
891 entry = hash_slot;
892 while ((*entry) != NULL)
893 entry = &(*entry)->next;
894 *entry = (struct opcode_hash_entry *)
895 xmalloc (sizeof (struct opcode_hash_entry));
896 (*entry)->next = NULL;
897 (*entry)->name = (*hash_slot)->name;
898 (*entry)->opcode = xstrdup (str);
899 (*entry)->lineno = lineno;
903 /* Process opcode array. */
904 for (j = 0; j < i; j++)
906 for (next = opcode_array[j]; next; next = next->next)
908 name = next->name;
909 str = next->opcode;
910 lineno = next->lineno;
911 last = str + strlen (str);
912 output_i386_opcode (table, name, str, last, lineno);
916 fclose (fp);
918 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
920 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
922 process_i386_opcode_modifier (table, "0", -1);
924 fprintf (table, " { ");
925 process_i386_operand_type (table, "0", 0, "\t ", -1);
926 fprintf (table, " } }\n");
928 fprintf (table, "};\n");
931 static void
932 process_i386_registers (FILE *table)
934 FILE *fp;
935 char buf[2048];
936 char *str, *p, *last;
937 char *reg_name, *reg_type, *reg_flags, *reg_num;
938 char *dw2_32_num, *dw2_64_num;
939 int lineno = 0;
941 filename = "i386-reg.tbl";
942 fp = fopen (filename, "r");
943 if (fp == NULL)
944 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
945 xstrerror (errno));
947 fprintf (table, "\n/* i386 register table. */\n\n");
948 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
950 while (!feof (fp))
952 if (fgets (buf, sizeof (buf), fp) == NULL)
953 break;
955 lineno++;
957 p = remove_leading_whitespaces (buf);
959 /* Skip comments. */
960 str = strstr (p, "//");
961 if (str != NULL)
962 str[0] = '\0';
964 /* Remove trailing white spaces. */
965 remove_trailing_whitespaces (p);
967 switch (p[0])
969 case '#':
970 fprintf (table, "%s\n", p);
971 case '\0':
972 continue;
973 break;
974 default:
975 break;
978 last = p + strlen (p);
980 /* Find reg_name. */
981 reg_name = next_field (p, ',', &str, last);
983 /* Find reg_type. */
984 reg_type = next_field (str, ',', &str, last);
986 /* Find reg_flags. */
987 reg_flags = next_field (str, ',', &str, last);
989 /* Find reg_num. */
990 reg_num = next_field (str, ',', &str, last);
992 fprintf (table, " { \"%s\",\n ", reg_name);
994 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
996 /* Find 32-bit Dwarf2 register number. */
997 dw2_32_num = next_field (str, ',', &str, last);
999 /* Find 64-bit Dwarf2 register number. */
1000 dw2_64_num = next_field (str, ',', &str, last);
1002 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1003 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1006 fclose (fp);
1008 fprintf (table, "};\n");
1010 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1013 static void
1014 process_i386_initializers (void)
1016 unsigned int i;
1017 FILE *fp = fopen ("i386-init.h", "w");
1018 char *init;
1020 if (fp == NULL)
1021 fail (_("can't create i386-init.h, errno = %s\n"),
1022 xstrerror (errno));
1024 process_copyright (fp);
1026 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1028 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1029 init = xstrdup (cpu_flag_init[i].init);
1030 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1031 free (init);
1034 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1036 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1037 init = xstrdup (operand_type_init[i].init);
1038 process_i386_operand_type (fp, init, 1, " ", -1);
1039 free (init);
1041 fprintf (fp, "\n");
1043 fclose (fp);
1046 /* Program options. */
1047 #define OPTION_SRCDIR 200
1049 struct option long_options[] =
1051 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1052 {"debug", no_argument, NULL, 'd'},
1053 {"version", no_argument, NULL, 'V'},
1054 {"help", no_argument, NULL, 'h'},
1055 {0, no_argument, NULL, 0}
1058 static void
1059 print_version (void)
1061 printf ("%s: version 1.0\n", program_name);
1062 xexit (0);
1065 static void
1066 usage (FILE * stream, int status)
1068 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1069 program_name);
1070 xexit (status);
1074 main (int argc, char **argv)
1076 extern int chdir (char *);
1077 char *srcdir = NULL;
1078 int c;
1079 FILE *table;
1081 program_name = *argv;
1082 xmalloc_set_program_name (program_name);
1084 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1085 switch (c)
1087 case OPTION_SRCDIR:
1088 srcdir = optarg;
1089 break;
1090 case 'V':
1091 case 'v':
1092 print_version ();
1093 break;
1094 case 'd':
1095 debug = 1;
1096 break;
1097 case 'h':
1098 case '?':
1099 usage (stderr, 0);
1100 default:
1101 case 0:
1102 break;
1105 if (optind != argc)
1106 usage (stdout, 1);
1108 if (srcdir != NULL)
1109 if (chdir (srcdir) != 0)
1110 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1111 srcdir, xstrerror (errno));
1113 /* Check the unused bitfield in i386_cpu_flags. */
1114 #ifndef CpuUnused
1115 c = CpuNumOfBits - CpuMax - 1;
1116 if (c)
1117 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1118 #endif
1120 /* Check the unused bitfield in i386_operand_type. */
1121 #ifndef OTUnused
1122 c = OTNumOfBits - OTMax - 1;
1123 if (c)
1124 fail (_("%d unused bits in i386_operand_type.\n"), c);
1125 #endif
1127 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1128 compare);
1130 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1131 sizeof (opcode_modifiers [0]), compare);
1133 qsort (operand_types, ARRAY_SIZE (operand_types),
1134 sizeof (operand_types [0]), compare);
1136 table = fopen ("i386-tbl.h", "w");
1137 if (table == NULL)
1138 fail (_("can't create i386-tbl.h, errno = %s\n"),
1139 xstrerror (errno));
1141 process_copyright (table);
1143 process_i386_opcodes (table);
1144 process_i386_registers (table);
1145 process_i386_initializers ();
1147 fclose (table);
1149 exit (0);