Sync from gcc mainline.
[binutils.git] / opcodes / i386-gen.c
blob5cd92054dbe9bfb9dce476c6949cd77ca68baea7
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)
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 "~CpuL1OM" },
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" },
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|Cpu387" },
63 { "CPU_I686_FLAGS",
64 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687" },
65 { "CPU_P2_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuMMX" },
67 { "CPU_P3_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuMMX|CpuSSE" },
69 { "CPU_P4_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuMMX|CpuSSE|CpuSSE2" },
71 { "CPU_NOCONA_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
73 { "CPU_CORE_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
75 { "CPU_CORE2_FLAGS",
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
77 { "CPU_COREI7_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
79 { "CPU_K6_FLAGS",
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
81 { "CPU_K6_2_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX|Cpu3dnow" },
83 { "CPU_ATHLON_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuMMX|Cpu3dnow|Cpu3dnowA" },
85 { "CPU_K8_FLAGS",
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" },
89 { "CPU_BDVER1_FLAGS",
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP" },
91 { "CPU_8087_FLAGS",
92 "Cpu8087" },
93 { "CPU_287_FLAGS",
94 "Cpu287" },
95 { "CPU_387_FLAGS",
96 "Cpu387" },
97 { "CPU_ANY87_FLAGS",
98 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
99 { "CPU_CLFLUSH_FLAGS",
100 "CpuClflush" },
101 { "CPU_SYSCALL_FLAGS",
102 "CpuSYSCALL" },
103 { "CPU_MMX_FLAGS",
104 "CpuMMX" },
105 { "CPU_SSE_FLAGS",
106 "CpuMMX|CpuSSE" },
107 { "CPU_SSE2_FLAGS",
108 "CpuMMX|CpuSSE|CpuSSE2" },
109 { "CPU_SSE3_FLAGS",
110 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
111 { "CPU_SSSE3_FLAGS",
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" },
119 { "CPU_VMX_FLAGS",
120 "CpuVMX" },
121 { "CPU_SMX_FLAGS",
122 "CpuSMX" },
123 { "CPU_XSAVE_FLAGS",
124 "CpuXsave" },
125 { "CPU_AES_FLAGS",
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" },
129 { "CPU_FMA_FLAGS",
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
131 { "CPU_FMA4_FLAGS",
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
133 { "CPU_XOP_FLAGS",
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
135 { "CPU_LWP_FLAGS",
136 "CpuLWP" },
137 { "CPU_MOVBE_FLAGS",
138 "CpuMovbe" },
139 { "CPU_RDTSCP_FLAGS",
140 "CpuRdtscp" },
141 { "CPU_EPT_FLAGS",
142 "CpuEPT" },
143 { "CPU_3DNOW_FLAGS",
144 "CpuMMX|Cpu3dnow" },
145 { "CPU_3DNOWA_FLAGS",
146 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
147 { "CPU_PADLOCK_FLAGS",
148 "CpuPadLock" },
149 { "CPU_SVME_FLAGS",
150 "CpuSVME" },
151 { "CPU_SSE4A_FLAGS",
152 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
153 { "CPU_ABM_FLAGS",
154 "CpuABM" },
155 { "CPU_AVX_FLAGS",
156 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
157 { "CPU_ANY_AVX_FLAGS",
158 "CpuAVX" },
159 { "CPU_L1OM_FLAGS",
160 "unknown" },
163 static initializer operand_type_init[] =
165 { "OPERAND_TYPE_NONE",
166 "0" },
167 { "OPERAND_TYPE_REG8",
168 "Reg8" },
169 { "OPERAND_TYPE_REG16",
170 "Reg16" },
171 { "OPERAND_TYPE_REG32",
172 "Reg32" },
173 { "OPERAND_TYPE_REG64",
174 "Reg64" },
175 { "OPERAND_TYPE_IMM1",
176 "Imm1" },
177 { "OPERAND_TYPE_IMM8",
178 "Imm8" },
179 { "OPERAND_TYPE_IMM8S",
180 "Imm8S" },
181 { "OPERAND_TYPE_IMM16",
182 "Imm16" },
183 { "OPERAND_TYPE_IMM32",
184 "Imm32" },
185 { "OPERAND_TYPE_IMM32S",
186 "Imm32S" },
187 { "OPERAND_TYPE_IMM64",
188 "Imm64" },
189 { "OPERAND_TYPE_BASEINDEX",
190 "BaseIndex" },
191 { "OPERAND_TYPE_DISP8",
192 "Disp8" },
193 { "OPERAND_TYPE_DISP16",
194 "Disp16" },
195 { "OPERAND_TYPE_DISP32",
196 "Disp32" },
197 { "OPERAND_TYPE_DISP32S",
198 "Disp32S" },
199 { "OPERAND_TYPE_DISP64",
200 "Disp64" },
201 { "OPERAND_TYPE_INOUTPORTREG",
202 "InOutPortReg" },
203 { "OPERAND_TYPE_SHIFTCOUNT",
204 "ShiftCount" },
205 { "OPERAND_TYPE_CONTROL",
206 "Control" },
207 { "OPERAND_TYPE_TEST",
208 "Test" },
209 { "OPERAND_TYPE_DEBUG",
210 "FloatReg" },
211 { "OPERAND_TYPE_FLOATREG",
212 "FloatReg" },
213 { "OPERAND_TYPE_FLOATACC",
214 "FloatAcc" },
215 { "OPERAND_TYPE_SREG2",
216 "SReg2" },
217 { "OPERAND_TYPE_SREG3",
218 "SReg3" },
219 { "OPERAND_TYPE_ACC",
220 "Acc" },
221 { "OPERAND_TYPE_JUMPABSOLUTE",
222 "JumpAbsolute" },
223 { "OPERAND_TYPE_REGMMX",
224 "RegMMX" },
225 { "OPERAND_TYPE_REGXMM",
226 "RegXMM" },
227 { "OPERAND_TYPE_REGYMM",
228 "RegYMM" },
229 { "OPERAND_TYPE_ESSEG",
230 "EsSeg" },
231 { "OPERAND_TYPE_ACC32",
232 "Reg32|Acc|Dword" },
233 { "OPERAND_TYPE_ACC64",
234 "Reg64|Acc|Qword" },
235 { "OPERAND_TYPE_INOUTPORTREG",
236 "InOutPortReg" },
237 { "OPERAND_TYPE_REG16_INOUTPORTREG",
238 "Reg16|InOutPortReg" },
239 { "OPERAND_TYPE_DISP16_32",
240 "Disp16|Disp32" },
241 { "OPERAND_TYPE_ANYDISP",
242 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
243 { "OPERAND_TYPE_IMM16_32",
244 "Imm16|Imm32" },
245 { "OPERAND_TYPE_IMM16_32S",
246 "Imm16|Imm32S" },
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",
252 "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" },
257 { "OPERAND_TYPE_VEC_IMM4",
258 "Vec_Imm4" },
261 typedef struct bitfield
263 int position;
264 int value;
265 const char *name;
266 } bitfield;
268 #define BITFIELD(n) { n, 0, #n }
270 static bitfield cpu_flags[] =
272 BITFIELD (Cpu186),
273 BITFIELD (Cpu286),
274 BITFIELD (Cpu386),
275 BITFIELD (Cpu486),
276 BITFIELD (Cpu586),
277 BITFIELD (Cpu686),
278 BITFIELD (CpuClflush),
279 BITFIELD (CpuSYSCALL),
280 BITFIELD (Cpu8087),
281 BITFIELD (Cpu287),
282 BITFIELD (Cpu387),
283 BITFIELD (Cpu687),
284 BITFIELD (CpuFISTTP),
285 BITFIELD (CpuMMX),
286 BITFIELD (CpuSSE),
287 BITFIELD (CpuSSE2),
288 BITFIELD (CpuSSE3),
289 BITFIELD (CpuSSSE3),
290 BITFIELD (CpuSSE4_1),
291 BITFIELD (CpuSSE4_2),
292 BITFIELD (CpuAVX),
293 BITFIELD (CpuL1OM),
294 BITFIELD (CpuSSE4a),
295 BITFIELD (Cpu3dnow),
296 BITFIELD (Cpu3dnowA),
297 BITFIELD (CpuPadLock),
298 BITFIELD (CpuSVME),
299 BITFIELD (CpuVMX),
300 BITFIELD (CpuSMX),
301 BITFIELD (CpuABM),
302 BITFIELD (CpuXsave),
303 BITFIELD (CpuAES),
304 BITFIELD (CpuPCLMUL),
305 BITFIELD (CpuFMA),
306 BITFIELD (CpuFMA4),
307 BITFIELD (CpuXOP),
308 BITFIELD (CpuLWP),
309 BITFIELD (CpuLM),
310 BITFIELD (CpuMovbe),
311 BITFIELD (CpuEPT),
312 BITFIELD (CpuRdtscp),
313 BITFIELD (Cpu64),
314 BITFIELD (CpuNo64),
315 #ifdef CpuUnused
316 BITFIELD (CpuUnused),
317 #endif
320 static bitfield opcode_modifiers[] =
322 BITFIELD (D),
323 BITFIELD (W),
324 BITFIELD (S),
325 BITFIELD (Modrm),
326 BITFIELD (ShortForm),
327 BITFIELD (Jump),
328 BITFIELD (JumpDword),
329 BITFIELD (JumpByte),
330 BITFIELD (JumpInterSegment),
331 BITFIELD (FloatMF),
332 BITFIELD (FloatR),
333 BITFIELD (FloatD),
334 BITFIELD (Size16),
335 BITFIELD (Size32),
336 BITFIELD (Size64),
337 BITFIELD (IgnoreSize),
338 BITFIELD (DefaultSize),
339 BITFIELD (No_bSuf),
340 BITFIELD (No_wSuf),
341 BITFIELD (No_lSuf),
342 BITFIELD (No_sSuf),
343 BITFIELD (No_qSuf),
344 BITFIELD (No_ldSuf),
345 BITFIELD (FWait),
346 BITFIELD (IsString),
347 BITFIELD (IsLockable),
348 BITFIELD (RegKludge),
349 BITFIELD (FirstXmm0),
350 BITFIELD (Implicit1stXmm0),
351 BITFIELD (ToDword),
352 BITFIELD (ToQword),
353 BITFIELD (AddrPrefixOp0),
354 BITFIELD (IsPrefix),
355 BITFIELD (ImmExt),
356 BITFIELD (NoRex64),
357 BITFIELD (Rex64),
358 BITFIELD (Ugh),
359 BITFIELD (Vex),
360 BITFIELD (VexVVVV),
361 BITFIELD (VexW),
362 BITFIELD (VexOpcode),
363 BITFIELD (VexSources),
364 BITFIELD (VexImmExt),
365 BITFIELD (SSE2AVX),
366 BITFIELD (NoAVX),
367 BITFIELD (OldGcc),
368 BITFIELD (ATTMnemonic),
369 BITFIELD (ATTSyntax),
370 BITFIELD (IntelSyntax),
373 static bitfield operand_types[] =
375 BITFIELD (Reg8),
376 BITFIELD (Reg16),
377 BITFIELD (Reg32),
378 BITFIELD (Reg64),
379 BITFIELD (FloatReg),
380 BITFIELD (RegMMX),
381 BITFIELD (RegXMM),
382 BITFIELD (RegYMM),
383 BITFIELD (Imm1),
384 BITFIELD (Imm8),
385 BITFIELD (Imm8S),
386 BITFIELD (Imm16),
387 BITFIELD (Imm32),
388 BITFIELD (Imm32S),
389 BITFIELD (Imm64),
390 BITFIELD (BaseIndex),
391 BITFIELD (Disp8),
392 BITFIELD (Disp16),
393 BITFIELD (Disp32),
394 BITFIELD (Disp32S),
395 BITFIELD (Disp64),
396 BITFIELD (InOutPortReg),
397 BITFIELD (ShiftCount),
398 BITFIELD (Control),
399 BITFIELD (Debug),
400 BITFIELD (Test),
401 BITFIELD (SReg2),
402 BITFIELD (SReg3),
403 BITFIELD (Acc),
404 BITFIELD (FloatAcc),
405 BITFIELD (JumpAbsolute),
406 BITFIELD (EsSeg),
407 BITFIELD (RegMem),
408 BITFIELD (Mem),
409 BITFIELD (Byte),
410 BITFIELD (Word),
411 BITFIELD (Dword),
412 BITFIELD (Fword),
413 BITFIELD (Qword),
414 BITFIELD (Tbyte),
415 BITFIELD (Xmmword),
416 BITFIELD (Ymmword),
417 BITFIELD (Unspecified),
418 BITFIELD (Anysize),
419 BITFIELD (Vec_Imm4),
420 #ifdef OTUnused
421 BITFIELD (OTUnused),
422 #endif
425 static const char *filename;
427 static int
428 compare (const void *x, const void *y)
430 const bitfield *xp = (const bitfield *) x;
431 const bitfield *yp = (const bitfield *) y;
432 return xp->position - yp->position;
435 static void
436 fail (const char *message, ...)
438 va_list args;
440 va_start (args, message);
441 fprintf (stderr, _("%s: Error: "), program_name);
442 vfprintf (stderr, message, args);
443 va_end (args);
444 xexit (1);
447 static void
448 process_copyright (FILE *fp)
450 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
451 /* Copyright 2007, 2008, 2009, 2010\n\
452 Free Software Foundation, Inc.\n\
454 This file is part of the GNU opcodes library.\n\
456 This library is free software; you can redistribute it and/or modify\n\
457 it under the terms of the GNU General Public License as published by\n\
458 the Free Software Foundation; either version 3, or (at your option)\n\
459 any later version.\n\
461 It is distributed in the hope that it will be useful, but WITHOUT\n\
462 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
463 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
464 License for more details.\n\
466 You should have received a copy of the GNU General Public License\n\
467 along with this program; if not, write to the Free Software\n\
468 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
469 MA 02110-1301, USA. */\n");
472 /* Remove leading white spaces. */
474 static char *
475 remove_leading_whitespaces (char *str)
477 while (ISSPACE (*str))
478 str++;
479 return str;
482 /* Remove trailing white spaces. */
484 static void
485 remove_trailing_whitespaces (char *str)
487 size_t last = strlen (str);
489 if (last == 0)
490 return;
494 last--;
495 if (ISSPACE (str [last]))
496 str[last] = '\0';
497 else
498 break;
500 while (last != 0);
503 /* Find next field separated by SEP and terminate it. Return a
504 pointer to the one after it. */
506 static char *
507 next_field (char *str, char sep, char **next, char *last)
509 char *p;
511 p = remove_leading_whitespaces (str);
512 for (str = p; *str != sep && *str != '\0'; str++);
514 *str = '\0';
515 remove_trailing_whitespaces (p);
517 *next = str + 1;
519 if (p >= last)
520 abort ();
522 return p;
525 static void
526 set_bitfield (const char *f, bitfield *array, int value,
527 unsigned int size, int lineno)
529 unsigned int i;
531 if (strcmp (f, "CpuFP") == 0)
533 set_bitfield("Cpu387", array, value, size, lineno);
534 set_bitfield("Cpu287", array, value, size, lineno);
535 f = "Cpu8087";
537 else if (strcmp (f, "Mmword") == 0)
538 f= "Qword";
539 else if (strcmp (f, "Oword") == 0)
540 f= "Xmmword";
542 for (i = 0; i < size; i++)
543 if (strcasecmp (array[i].name, f) == 0)
545 array[i].value = value;
546 return;
549 if (value)
551 const char *v = strchr (f, '=');
553 if (v)
555 size_t n = v - f;
556 char *end;
558 for (i = 0; i < size; i++)
559 if (strncasecmp (array[i].name, f, n) == 0)
561 value = strtol (v + 1, &end, 0);
562 if (*end == '\0')
564 array[i].value = value;
565 return;
567 break;
572 if (lineno != -1)
573 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
574 else
575 fail (_("Unknown bitfield: %s\n"), f);
578 static void
579 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
580 int macro, const char *comma, const char *indent)
582 unsigned int i;
584 fprintf (table, "%s{ { ", indent);
586 for (i = 0; i < size - 1; i++)
588 fprintf (table, "%d, ", flags[i].value);
589 if (((i + 1) % 20) == 0)
591 /* We need \\ for macro. */
592 if (macro)
593 fprintf (table, " \\\n %s", indent);
594 else
595 fprintf (table, "\n %s", indent);
599 fprintf (table, "%d } }%s\n", flags[i].value, comma);
602 static void
603 process_i386_cpu_flag (FILE *table, char *flag, int macro,
604 const char *comma, const char *indent,
605 int lineno)
607 char *str, *next, *last;
608 unsigned int i;
609 bitfield flags [ARRAY_SIZE (cpu_flags)];
611 /* Copy the default cpu flags. */
612 memcpy (flags, cpu_flags, sizeof (cpu_flags));
614 if (strcasecmp (flag, "unknown") == 0)
616 /* We turn on everything except for cpu64 in case of
617 CPU_UNKNOWN_FLAGS. */
618 for (i = 0; i < ARRAY_SIZE (flags); i++)
619 if (flags[i].position != Cpu64)
620 flags[i].value = 1;
622 else if (flag[0] == '~')
624 last = flag + strlen (flag);
626 if (flag[1] == '(')
628 last -= 1;
629 next = flag + 2;
630 if (*last != ')')
631 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
632 lineno, flag);
633 *last = '\0';
635 else
636 next = flag + 1;
638 /* First we turn on everything except for cpu64. */
639 for (i = 0; i < ARRAY_SIZE (flags); i++)
640 if (flags[i].position != Cpu64)
641 flags[i].value = 1;
643 /* Turn off selective bits. */
644 for (; next && next < last; )
646 str = next_field (next, '|', &next, last);
647 if (str)
648 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
651 else if (strcmp (flag, "0"))
653 /* Turn on selective bits. */
654 last = flag + strlen (flag);
655 for (next = flag; next && next < last; )
657 str = next_field (next, '|', &next, last);
658 if (str)
659 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
663 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
664 comma, indent);
667 static void
668 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
670 unsigned int i;
672 fprintf (table, " { ");
674 for (i = 0; i < size - 1; i++)
676 fprintf (table, "%d, ", modifier[i].value);
677 if (((i + 1) % 20) == 0)
678 fprintf (table, "\n ");
681 fprintf (table, "%d },\n", modifier[i].value);
684 static void
685 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
687 char *str, *next, *last;
688 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
690 /* Copy the default opcode modifier. */
691 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
693 if (strcmp (mod, "0"))
695 last = mod + strlen (mod);
696 for (next = mod; next && next < last; )
698 str = next_field (next, '|', &next, last);
699 if (str)
700 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
701 lineno);
704 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
707 static void
708 output_operand_type (FILE *table, bitfield *types, unsigned int size,
709 int macro, const char *indent)
711 unsigned int i;
713 fprintf (table, "{ { ");
715 for (i = 0; i < size - 1; i++)
717 fprintf (table, "%d, ", types[i].value);
718 if (((i + 1) % 20) == 0)
720 /* We need \\ for macro. */
721 if (macro)
722 fprintf (table, "\\\n%s", indent);
723 else
724 fprintf (table, "\n%s", indent);
728 fprintf (table, "%d } }", types[i].value);
731 static void
732 process_i386_operand_type (FILE *table, char *op, int macro,
733 const char *indent, int lineno)
735 char *str, *next, *last;
736 bitfield types [ARRAY_SIZE (operand_types)];
738 /* Copy the default operand type. */
739 memcpy (types, operand_types, sizeof (types));
741 if (strcmp (op, "0"))
743 last = op + strlen (op);
744 for (next = op; next && next < last; )
746 str = next_field (next, '|', &next, last);
747 if (str)
748 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
751 output_operand_type (table, types, ARRAY_SIZE (types), macro,
752 indent);
755 static void
756 output_i386_opcode (FILE *table, const char *name, char *str,
757 char *last, int lineno)
759 unsigned int i;
760 char *operands, *base_opcode, *extension_opcode, *opcode_length;
761 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
763 /* Find number of operands. */
764 operands = next_field (str, ',', &str, last);
766 /* Find base_opcode. */
767 base_opcode = next_field (str, ',', &str, last);
769 /* Find extension_opcode. */
770 extension_opcode = next_field (str, ',', &str, last);
772 /* Find opcode_length. */
773 opcode_length = next_field (str, ',', &str, last);
775 /* Find cpu_flags. */
776 cpu_flags = next_field (str, ',', &str, last);
778 /* Find opcode_modifier. */
779 opcode_modifier = next_field (str, ',', &str, last);
781 /* Remove the first {. */
782 str = remove_leading_whitespaces (str);
783 if (*str != '{')
784 abort ();
785 str = remove_leading_whitespaces (str + 1);
787 i = strlen (str);
789 /* There are at least "X}". */
790 if (i < 2)
791 abort ();
793 /* Remove trailing white spaces and }. */
796 i--;
797 if (ISSPACE (str[i]) || str[i] == '}')
798 str[i] = '\0';
799 else
800 break;
802 while (i != 0);
804 last = str + i;
806 /* Find operand_types. */
807 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
809 if (str >= last)
811 operand_types [i] = NULL;
812 break;
815 operand_types [i] = next_field (str, ',', &str, last);
816 if (*operand_types[i] == '0')
818 if (i != 0)
819 operand_types[i] = NULL;
820 break;
824 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
825 name, operands, base_opcode, extension_opcode,
826 opcode_length);
828 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
830 process_i386_opcode_modifier (table, opcode_modifier, lineno);
832 fprintf (table, " { ");
834 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
836 if (operand_types[i] == NULL || *operand_types[i] == '0')
838 if (i == 0)
839 process_i386_operand_type (table, "0", 0, "\t ", lineno);
840 break;
843 if (i != 0)
844 fprintf (table, ",\n ");
846 process_i386_operand_type (table, operand_types[i], 0,
847 "\t ", lineno);
849 fprintf (table, " } },\n");
852 struct opcode_hash_entry
854 struct opcode_hash_entry *next;
855 char *name;
856 char *opcode;
857 int lineno;
860 /* Calculate the hash value of an opcode hash entry P. */
862 static hashval_t
863 opcode_hash_hash (const void *p)
865 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
866 return htab_hash_string (entry->name);
869 /* Compare a string Q against an opcode hash entry P. */
871 static int
872 opcode_hash_eq (const void *p, const void *q)
874 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
875 const char *name = (const char *) q;
876 return strcmp (name, entry->name) == 0;
879 static void
880 process_i386_opcodes (FILE *table)
882 FILE *fp;
883 char buf[2048];
884 unsigned int i, j;
885 char *str, *p, *last, *name;
886 struct opcode_hash_entry **hash_slot, **entry, *next;
887 htab_t opcode_hash_table;
888 struct opcode_hash_entry **opcode_array;
889 unsigned int opcode_array_size = 1024;
890 int lineno = 0;
892 filename = "i386-opc.tbl";
893 fp = fopen (filename, "r");
895 if (fp == NULL)
896 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
897 xstrerror (errno));
899 i = 0;
900 opcode_array = (struct opcode_hash_entry **)
901 xmalloc (sizeof (*opcode_array) * opcode_array_size);
903 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
904 opcode_hash_eq, NULL,
905 xcalloc, free);
907 fprintf (table, "\n/* i386 opcode table. */\n\n");
908 fprintf (table, "const insn_template i386_optab[] =\n{\n");
910 /* Put everything on opcode array. */
911 while (!feof (fp))
913 if (fgets (buf, sizeof (buf), fp) == NULL)
914 break;
916 lineno++;
918 p = remove_leading_whitespaces (buf);
920 /* Skip comments. */
921 str = strstr (p, "//");
922 if (str != NULL)
923 str[0] = '\0';
925 /* Remove trailing white spaces. */
926 remove_trailing_whitespaces (p);
928 switch (p[0])
930 case '#':
931 /* Ignore comments. */
932 case '\0':
933 continue;
934 break;
935 default:
936 break;
939 last = p + strlen (p);
941 /* Find name. */
942 name = next_field (p, ',', &str, last);
944 /* Get the slot in hash table. */
945 hash_slot = (struct opcode_hash_entry **)
946 htab_find_slot_with_hash (opcode_hash_table, name,
947 htab_hash_string (name),
948 INSERT);
950 if (*hash_slot == NULL)
952 /* It is the new one. Put it on opcode array. */
953 if (i >= opcode_array_size)
955 /* Grow the opcode array when needed. */
956 opcode_array_size += 1024;
957 opcode_array = (struct opcode_hash_entry **)
958 xrealloc (opcode_array,
959 sizeof (*opcode_array) * opcode_array_size);
962 opcode_array[i] = (struct opcode_hash_entry *)
963 xmalloc (sizeof (struct opcode_hash_entry));
964 opcode_array[i]->next = NULL;
965 opcode_array[i]->name = xstrdup (name);
966 opcode_array[i]->opcode = xstrdup (str);
967 opcode_array[i]->lineno = lineno;
968 *hash_slot = opcode_array[i];
969 i++;
971 else
973 /* Append it to the existing one. */
974 entry = hash_slot;
975 while ((*entry) != NULL)
976 entry = &(*entry)->next;
977 *entry = (struct opcode_hash_entry *)
978 xmalloc (sizeof (struct opcode_hash_entry));
979 (*entry)->next = NULL;
980 (*entry)->name = (*hash_slot)->name;
981 (*entry)->opcode = xstrdup (str);
982 (*entry)->lineno = lineno;
986 /* Process opcode array. */
987 for (j = 0; j < i; j++)
989 for (next = opcode_array[j]; next; next = next->next)
991 name = next->name;
992 str = next->opcode;
993 lineno = next->lineno;
994 last = str + strlen (str);
995 output_i386_opcode (table, name, str, last, lineno);
999 fclose (fp);
1001 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1003 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1005 process_i386_opcode_modifier (table, "0", -1);
1007 fprintf (table, " { ");
1008 process_i386_operand_type (table, "0", 0, "\t ", -1);
1009 fprintf (table, " } }\n");
1011 fprintf (table, "};\n");
1014 static void
1015 process_i386_registers (FILE *table)
1017 FILE *fp;
1018 char buf[2048];
1019 char *str, *p, *last;
1020 char *reg_name, *reg_type, *reg_flags, *reg_num;
1021 char *dw2_32_num, *dw2_64_num;
1022 int lineno = 0;
1024 filename = "i386-reg.tbl";
1025 fp = fopen (filename, "r");
1026 if (fp == NULL)
1027 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1028 xstrerror (errno));
1030 fprintf (table, "\n/* i386 register table. */\n\n");
1031 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1033 while (!feof (fp))
1035 if (fgets (buf, sizeof (buf), fp) == NULL)
1036 break;
1038 lineno++;
1040 p = remove_leading_whitespaces (buf);
1042 /* Skip comments. */
1043 str = strstr (p, "//");
1044 if (str != NULL)
1045 str[0] = '\0';
1047 /* Remove trailing white spaces. */
1048 remove_trailing_whitespaces (p);
1050 switch (p[0])
1052 case '#':
1053 fprintf (table, "%s\n", p);
1054 case '\0':
1055 continue;
1056 break;
1057 default:
1058 break;
1061 last = p + strlen (p);
1063 /* Find reg_name. */
1064 reg_name = next_field (p, ',', &str, last);
1066 /* Find reg_type. */
1067 reg_type = next_field (str, ',', &str, last);
1069 /* Find reg_flags. */
1070 reg_flags = next_field (str, ',', &str, last);
1072 /* Find reg_num. */
1073 reg_num = next_field (str, ',', &str, last);
1075 fprintf (table, " { \"%s\",\n ", reg_name);
1077 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1079 /* Find 32-bit Dwarf2 register number. */
1080 dw2_32_num = next_field (str, ',', &str, last);
1082 /* Find 64-bit Dwarf2 register number. */
1083 dw2_64_num = next_field (str, ',', &str, last);
1085 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1086 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1089 fclose (fp);
1091 fprintf (table, "};\n");
1093 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1096 static void
1097 process_i386_initializers (void)
1099 unsigned int i;
1100 FILE *fp = fopen ("i386-init.h", "w");
1101 char *init;
1103 if (fp == NULL)
1104 fail (_("can't create i386-init.h, errno = %s\n"),
1105 xstrerror (errno));
1107 process_copyright (fp);
1109 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1111 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1112 init = xstrdup (cpu_flag_init[i].init);
1113 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1114 free (init);
1117 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1119 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1120 init = xstrdup (operand_type_init[i].init);
1121 process_i386_operand_type (fp, init, 1, " ", -1);
1122 free (init);
1124 fprintf (fp, "\n");
1126 fclose (fp);
1129 /* Program options. */
1130 #define OPTION_SRCDIR 200
1132 struct option long_options[] =
1134 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1135 {"debug", no_argument, NULL, 'd'},
1136 {"version", no_argument, NULL, 'V'},
1137 {"help", no_argument, NULL, 'h'},
1138 {0, no_argument, NULL, 0}
1141 static void
1142 print_version (void)
1144 printf ("%s: version 1.0\n", program_name);
1145 xexit (0);
1148 static void
1149 usage (FILE * stream, int status)
1151 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1152 program_name);
1153 xexit (status);
1157 main (int argc, char **argv)
1159 extern int chdir (char *);
1160 char *srcdir = NULL;
1161 int c;
1162 FILE *table;
1164 program_name = *argv;
1165 xmalloc_set_program_name (program_name);
1167 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1168 switch (c)
1170 case OPTION_SRCDIR:
1171 srcdir = optarg;
1172 break;
1173 case 'V':
1174 case 'v':
1175 print_version ();
1176 break;
1177 case 'd':
1178 debug = 1;
1179 break;
1180 case 'h':
1181 case '?':
1182 usage (stderr, 0);
1183 default:
1184 case 0:
1185 break;
1188 if (optind != argc)
1189 usage (stdout, 1);
1191 if (srcdir != NULL)
1192 if (chdir (srcdir) != 0)
1193 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1194 srcdir, xstrerror (errno));
1196 /* Check the unused bitfield in i386_cpu_flags. */
1197 #ifndef CpuUnused
1198 c = CpuNumOfBits - CpuMax - 1;
1199 if (c)
1200 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1201 #endif
1203 /* Check the unused bitfield in i386_operand_type. */
1204 #ifndef OTUnused
1205 c = OTNumOfBits - OTMax - 1;
1206 if (c)
1207 fail (_("%d unused bits in i386_operand_type.\n"), c);
1208 #endif
1210 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1211 compare);
1213 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1214 sizeof (opcode_modifiers [0]), compare);
1216 qsort (operand_types, ARRAY_SIZE (operand_types),
1217 sizeof (operand_types [0]), compare);
1219 table = fopen ("i386-tbl.h", "w");
1220 if (table == NULL)
1221 fail (_("can't create i386-tbl.h, errno = %s\n"),
1222 xstrerror (errno));
1224 process_copyright (table);
1226 process_i386_opcodes (table);
1227 process_i386_registers (table);
1228 process_i386_initializers ();
1230 fclose (table);
1232 exit (0);