Add tbm flag and TBM instruction pattern.
[binutils.git] / opcodes / i386-gen.c
blobe791c610379912e8ac4075a51f6b68c781dc8bd2
1 /* Copyright 2007, 2008, 2009, 2010, 2011
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|CpuNop|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_PENTIUMPRO_FLAGS",
66 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop" },
67 { "CPU_P2_FLAGS",
68 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX" },
69 { "CPU_P3_FLAGS",
70 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE" },
71 { "CPU_P4_FLAGS",
72 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuNop|CpuMMX|CpuSSE|CpuSSE2" },
73 { "CPU_NOCONA_FLAGS",
74 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuLM" },
75 { "CPU_CORE_FLAGS",
76 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
77 { "CPU_CORE2_FLAGS",
78 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuLM" },
79 { "CPU_COREI7_FLAGS",
80 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuClflush|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuRdtscp|CpuLM" },
81 { "CPU_K6_FLAGS",
82 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuMMX" },
83 { "CPU_K6_2_FLAGS",
84 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CpuNop|CpuMMX|Cpu3dnow" },
85 { "CPU_ATHLON_FLAGS",
86 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA" },
87 { "CPU_K8_FLAGS",
88 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuLM" },
89 { "CPU_AMDFAM10_FLAGS",
90 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM" },
91 { "CPU_BDVER1_FLAGS",
92 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuSYSCALL|CpuRdtscp|Cpu387|Cpu687|CpuFISTTP|CpuNop|CpuMMX|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a|CpuABM|CpuLM|CpuFMA4|CpuXOP|CpuLWP" },
93 { "CPU_8087_FLAGS",
94 "Cpu8087" },
95 { "CPU_287_FLAGS",
96 "Cpu287" },
97 { "CPU_387_FLAGS",
98 "Cpu387" },
99 { "CPU_ANY87_FLAGS",
100 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
101 { "CPU_CLFLUSH_FLAGS",
102 "CpuClflush" },
103 { "CPU_NOP_FLAGS",
104 "CpuNop" },
105 { "CPU_SYSCALL_FLAGS",
106 "CpuSYSCALL" },
107 { "CPU_MMX_FLAGS",
108 "CpuMMX" },
109 { "CPU_SSE_FLAGS",
110 "CpuMMX|CpuSSE" },
111 { "CPU_SSE2_FLAGS",
112 "CpuMMX|CpuSSE|CpuSSE2" },
113 { "CPU_SSE3_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
115 { "CPU_SSSE3_FLAGS",
116 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
117 { "CPU_SSE4_1_FLAGS",
118 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
119 { "CPU_SSE4_2_FLAGS",
120 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
121 { "CPU_ANY_SSE_FLAGS",
122 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX" },
123 { "CPU_VMX_FLAGS",
124 "CpuVMX" },
125 { "CPU_SMX_FLAGS",
126 "CpuSMX" },
127 { "CPU_XSAVE_FLAGS",
128 "CpuXsave" },
129 { "CPU_XSAVEOPT_FLAGS",
130 "CpuXsaveopt" },
131 { "CPU_AES_FLAGS",
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
133 { "CPU_PCLMUL_FLAGS",
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
135 { "CPU_FMA_FLAGS",
136 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
137 { "CPU_FMA4_FLAGS",
138 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
139 { "CPU_XOP_FLAGS",
140 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP" },
141 { "CPU_LWP_FLAGS",
142 "CpuLWP" },
143 { "CPU_BMI_FLAGS",
144 "CpuBMI" },
145 { "CPU_TBM_FLAGS",
146 "CpuTBM" },
147 { "CPU_MOVBE_FLAGS",
148 "CpuMovbe" },
149 { "CPU_RDTSCP_FLAGS",
150 "CpuRdtscp" },
151 { "CPU_EPT_FLAGS",
152 "CpuEPT" },
153 { "CPU_FSGSBASE_FLAGS",
154 "CpuFSGSBase" },
155 { "CPU_RDRND_FLAGS",
156 "CpuRdRnd" },
157 { "CPU_F16C_FLAGS",
158 "CpuF16C" },
159 { "CPU_3DNOW_FLAGS",
160 "CpuMMX|Cpu3dnow" },
161 { "CPU_3DNOWA_FLAGS",
162 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
163 { "CPU_PADLOCK_FLAGS",
164 "CpuPadLock" },
165 { "CPU_SVME_FLAGS",
166 "CpuSVME" },
167 { "CPU_SSE4A_FLAGS",
168 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
169 { "CPU_ABM_FLAGS",
170 "CpuABM" },
171 { "CPU_AVX_FLAGS",
172 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
173 { "CPU_ANY_AVX_FLAGS",
174 "CpuAVX" },
175 { "CPU_L1OM_FLAGS",
176 "unknown" },
179 static initializer operand_type_init[] =
181 { "OPERAND_TYPE_NONE",
182 "0" },
183 { "OPERAND_TYPE_REG8",
184 "Reg8" },
185 { "OPERAND_TYPE_REG16",
186 "Reg16" },
187 { "OPERAND_TYPE_REG32",
188 "Reg32" },
189 { "OPERAND_TYPE_REG64",
190 "Reg64" },
191 { "OPERAND_TYPE_IMM1",
192 "Imm1" },
193 { "OPERAND_TYPE_IMM8",
194 "Imm8" },
195 { "OPERAND_TYPE_IMM8S",
196 "Imm8S" },
197 { "OPERAND_TYPE_IMM16",
198 "Imm16" },
199 { "OPERAND_TYPE_IMM32",
200 "Imm32" },
201 { "OPERAND_TYPE_IMM32S",
202 "Imm32S" },
203 { "OPERAND_TYPE_IMM64",
204 "Imm64" },
205 { "OPERAND_TYPE_BASEINDEX",
206 "BaseIndex" },
207 { "OPERAND_TYPE_DISP8",
208 "Disp8" },
209 { "OPERAND_TYPE_DISP16",
210 "Disp16" },
211 { "OPERAND_TYPE_DISP32",
212 "Disp32" },
213 { "OPERAND_TYPE_DISP32S",
214 "Disp32S" },
215 { "OPERAND_TYPE_DISP64",
216 "Disp64" },
217 { "OPERAND_TYPE_INOUTPORTREG",
218 "InOutPortReg" },
219 { "OPERAND_TYPE_SHIFTCOUNT",
220 "ShiftCount" },
221 { "OPERAND_TYPE_CONTROL",
222 "Control" },
223 { "OPERAND_TYPE_TEST",
224 "Test" },
225 { "OPERAND_TYPE_DEBUG",
226 "FloatReg" },
227 { "OPERAND_TYPE_FLOATREG",
228 "FloatReg" },
229 { "OPERAND_TYPE_FLOATACC",
230 "FloatAcc" },
231 { "OPERAND_TYPE_SREG2",
232 "SReg2" },
233 { "OPERAND_TYPE_SREG3",
234 "SReg3" },
235 { "OPERAND_TYPE_ACC",
236 "Acc" },
237 { "OPERAND_TYPE_JUMPABSOLUTE",
238 "JumpAbsolute" },
239 { "OPERAND_TYPE_REGMMX",
240 "RegMMX" },
241 { "OPERAND_TYPE_REGXMM",
242 "RegXMM" },
243 { "OPERAND_TYPE_REGYMM",
244 "RegYMM" },
245 { "OPERAND_TYPE_ESSEG",
246 "EsSeg" },
247 { "OPERAND_TYPE_ACC32",
248 "Reg32|Acc|Dword" },
249 { "OPERAND_TYPE_ACC64",
250 "Reg64|Acc|Qword" },
251 { "OPERAND_TYPE_INOUTPORTREG",
252 "InOutPortReg" },
253 { "OPERAND_TYPE_REG16_INOUTPORTREG",
254 "Reg16|InOutPortReg" },
255 { "OPERAND_TYPE_DISP16_32",
256 "Disp16|Disp32" },
257 { "OPERAND_TYPE_ANYDISP",
258 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
259 { "OPERAND_TYPE_IMM16_32",
260 "Imm16|Imm32" },
261 { "OPERAND_TYPE_IMM16_32S",
262 "Imm16|Imm32S" },
263 { "OPERAND_TYPE_IMM16_32_32S",
264 "Imm16|Imm32|Imm32S" },
265 { "OPERAND_TYPE_IMM32_32S_DISP32",
266 "Imm32|Imm32S|Disp32" },
267 { "OPERAND_TYPE_IMM64_DISP64",
268 "Imm64|Disp64" },
269 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
270 "Imm32|Imm32S|Imm64|Disp32" },
271 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
272 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
273 { "OPERAND_TYPE_VEC_IMM4",
274 "Vec_Imm4" },
277 typedef struct bitfield
279 int position;
280 int value;
281 const char *name;
282 } bitfield;
284 #define BITFIELD(n) { n, 0, #n }
286 static bitfield cpu_flags[] =
288 BITFIELD (Cpu186),
289 BITFIELD (Cpu286),
290 BITFIELD (Cpu386),
291 BITFIELD (Cpu486),
292 BITFIELD (Cpu586),
293 BITFIELD (Cpu686),
294 BITFIELD (CpuClflush),
295 BITFIELD (CpuNop),
296 BITFIELD (CpuSYSCALL),
297 BITFIELD (Cpu8087),
298 BITFIELD (Cpu287),
299 BITFIELD (Cpu387),
300 BITFIELD (Cpu687),
301 BITFIELD (CpuFISTTP),
302 BITFIELD (CpuMMX),
303 BITFIELD (CpuSSE),
304 BITFIELD (CpuSSE2),
305 BITFIELD (CpuSSE3),
306 BITFIELD (CpuSSSE3),
307 BITFIELD (CpuSSE4_1),
308 BITFIELD (CpuSSE4_2),
309 BITFIELD (CpuAVX),
310 BITFIELD (CpuL1OM),
311 BITFIELD (CpuSSE4a),
312 BITFIELD (Cpu3dnow),
313 BITFIELD (Cpu3dnowA),
314 BITFIELD (CpuPadLock),
315 BITFIELD (CpuSVME),
316 BITFIELD (CpuVMX),
317 BITFIELD (CpuSMX),
318 BITFIELD (CpuABM),
319 BITFIELD (CpuXsave),
320 BITFIELD (CpuXsaveopt),
321 BITFIELD (CpuAES),
322 BITFIELD (CpuPCLMUL),
323 BITFIELD (CpuFMA),
324 BITFIELD (CpuFMA4),
325 BITFIELD (CpuXOP),
326 BITFIELD (CpuLWP),
327 BITFIELD (CpuBMI),
328 BITFIELD (CpuTBM),
329 BITFIELD (CpuLM),
330 BITFIELD (CpuMovbe),
331 BITFIELD (CpuEPT),
332 BITFIELD (CpuRdtscp),
333 BITFIELD (CpuFSGSBase),
334 BITFIELD (CpuRdRnd),
335 BITFIELD (CpuF16C),
336 BITFIELD (Cpu64),
337 BITFIELD (CpuNo64),
338 #ifdef CpuUnused
339 BITFIELD (CpuUnused),
340 #endif
343 static bitfield opcode_modifiers[] =
345 BITFIELD (D),
346 BITFIELD (W),
347 BITFIELD (S),
348 BITFIELD (Modrm),
349 BITFIELD (ShortForm),
350 BITFIELD (Jump),
351 BITFIELD (JumpDword),
352 BITFIELD (JumpByte),
353 BITFIELD (JumpInterSegment),
354 BITFIELD (FloatMF),
355 BITFIELD (FloatR),
356 BITFIELD (FloatD),
357 BITFIELD (Size16),
358 BITFIELD (Size32),
359 BITFIELD (Size64),
360 BITFIELD (CheckRegSize),
361 BITFIELD (IgnoreSize),
362 BITFIELD (DefaultSize),
363 BITFIELD (No_bSuf),
364 BITFIELD (No_wSuf),
365 BITFIELD (No_lSuf),
366 BITFIELD (No_sSuf),
367 BITFIELD (No_qSuf),
368 BITFIELD (No_ldSuf),
369 BITFIELD (FWait),
370 BITFIELD (IsString),
371 BITFIELD (IsLockable),
372 BITFIELD (RegKludge),
373 BITFIELD (FirstXmm0),
374 BITFIELD (Implicit1stXmm0),
375 BITFIELD (ToDword),
376 BITFIELD (ToQword),
377 BITFIELD (AddrPrefixOp0),
378 BITFIELD (IsPrefix),
379 BITFIELD (ImmExt),
380 BITFIELD (NoRex64),
381 BITFIELD (Rex64),
382 BITFIELD (Ugh),
383 BITFIELD (Vex),
384 BITFIELD (VexVVVV),
385 BITFIELD (VexW),
386 BITFIELD (VexOpcode),
387 BITFIELD (VexSources),
388 BITFIELD (VexImmExt),
389 BITFIELD (SSE2AVX),
390 BITFIELD (NoAVX),
391 BITFIELD (OldGcc),
392 BITFIELD (ATTMnemonic),
393 BITFIELD (ATTSyntax),
394 BITFIELD (IntelSyntax),
397 static bitfield operand_types[] =
399 BITFIELD (Reg8),
400 BITFIELD (Reg16),
401 BITFIELD (Reg32),
402 BITFIELD (Reg64),
403 BITFIELD (FloatReg),
404 BITFIELD (RegMMX),
405 BITFIELD (RegXMM),
406 BITFIELD (RegYMM),
407 BITFIELD (Imm1),
408 BITFIELD (Imm8),
409 BITFIELD (Imm8S),
410 BITFIELD (Imm16),
411 BITFIELD (Imm32),
412 BITFIELD (Imm32S),
413 BITFIELD (Imm64),
414 BITFIELD (BaseIndex),
415 BITFIELD (Disp8),
416 BITFIELD (Disp16),
417 BITFIELD (Disp32),
418 BITFIELD (Disp32S),
419 BITFIELD (Disp64),
420 BITFIELD (InOutPortReg),
421 BITFIELD (ShiftCount),
422 BITFIELD (Control),
423 BITFIELD (Debug),
424 BITFIELD (Test),
425 BITFIELD (SReg2),
426 BITFIELD (SReg3),
427 BITFIELD (Acc),
428 BITFIELD (FloatAcc),
429 BITFIELD (JumpAbsolute),
430 BITFIELD (EsSeg),
431 BITFIELD (RegMem),
432 BITFIELD (Mem),
433 BITFIELD (Byte),
434 BITFIELD (Word),
435 BITFIELD (Dword),
436 BITFIELD (Fword),
437 BITFIELD (Qword),
438 BITFIELD (Tbyte),
439 BITFIELD (Xmmword),
440 BITFIELD (Ymmword),
441 BITFIELD (Unspecified),
442 BITFIELD (Anysize),
443 BITFIELD (Vec_Imm4),
444 #ifdef OTUnused
445 BITFIELD (OTUnused),
446 #endif
449 static const char *filename;
451 static int
452 compare (const void *x, const void *y)
454 const bitfield *xp = (const bitfield *) x;
455 const bitfield *yp = (const bitfield *) y;
456 return xp->position - yp->position;
459 static void
460 fail (const char *message, ...)
462 va_list args;
464 va_start (args, message);
465 fprintf (stderr, _("%s: Error: "), program_name);
466 vfprintf (stderr, message, args);
467 va_end (args);
468 xexit (1);
471 static void
472 process_copyright (FILE *fp)
474 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
475 /* Copyright 2007, 2008, 2009, 2010, 2011\n\
476 Free Software Foundation, Inc.\n\
478 This file is part of the GNU opcodes library.\n\
480 This library is free software; you can redistribute it and/or modify\n\
481 it under the terms of the GNU General Public License as published by\n\
482 the Free Software Foundation; either version 3, or (at your option)\n\
483 any later version.\n\
485 It is distributed in the hope that it will be useful, but WITHOUT\n\
486 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
487 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
488 License for more details.\n\
490 You should have received a copy of the GNU General Public License\n\
491 along with this program; if not, write to the Free Software\n\
492 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
493 MA 02110-1301, USA. */\n");
496 /* Remove leading white spaces. */
498 static char *
499 remove_leading_whitespaces (char *str)
501 while (ISSPACE (*str))
502 str++;
503 return str;
506 /* Remove trailing white spaces. */
508 static void
509 remove_trailing_whitespaces (char *str)
511 size_t last = strlen (str);
513 if (last == 0)
514 return;
518 last--;
519 if (ISSPACE (str [last]))
520 str[last] = '\0';
521 else
522 break;
524 while (last != 0);
527 /* Find next field separated by SEP and terminate it. Return a
528 pointer to the one after it. */
530 static char *
531 next_field (char *str, char sep, char **next, char *last)
533 char *p;
535 p = remove_leading_whitespaces (str);
536 for (str = p; *str != sep && *str != '\0'; str++);
538 *str = '\0';
539 remove_trailing_whitespaces (p);
541 *next = str + 1;
543 if (p >= last)
544 abort ();
546 return p;
549 static void
550 set_bitfield (const char *f, bitfield *array, int value,
551 unsigned int size, int lineno)
553 unsigned int i;
555 if (strcmp (f, "CpuFP") == 0)
557 set_bitfield("Cpu387", array, value, size, lineno);
558 set_bitfield("Cpu287", array, value, size, lineno);
559 f = "Cpu8087";
561 else if (strcmp (f, "Mmword") == 0)
562 f= "Qword";
563 else if (strcmp (f, "Oword") == 0)
564 f= "Xmmword";
566 for (i = 0; i < size; i++)
567 if (strcasecmp (array[i].name, f) == 0)
569 array[i].value = value;
570 return;
573 if (value)
575 const char *v = strchr (f, '=');
577 if (v)
579 size_t n = v - f;
580 char *end;
582 for (i = 0; i < size; i++)
583 if (strncasecmp (array[i].name, f, n) == 0)
585 value = strtol (v + 1, &end, 0);
586 if (*end == '\0')
588 array[i].value = value;
589 return;
591 break;
596 if (lineno != -1)
597 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
598 else
599 fail (_("Unknown bitfield: %s\n"), f);
602 static void
603 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
604 int macro, const char *comma, const char *indent)
606 unsigned int i;
608 fprintf (table, "%s{ { ", indent);
610 for (i = 0; i < size - 1; i++)
612 fprintf (table, "%d, ", flags[i].value);
613 if (((i + 1) % 20) == 0)
615 /* We need \\ for macro. */
616 if (macro)
617 fprintf (table, " \\\n %s", indent);
618 else
619 fprintf (table, "\n %s", indent);
623 fprintf (table, "%d } }%s\n", flags[i].value, comma);
626 static void
627 process_i386_cpu_flag (FILE *table, char *flag, int macro,
628 const char *comma, const char *indent,
629 int lineno)
631 char *str, *next, *last;
632 unsigned int i;
633 bitfield flags [ARRAY_SIZE (cpu_flags)];
635 /* Copy the default cpu flags. */
636 memcpy (flags, cpu_flags, sizeof (cpu_flags));
638 if (strcasecmp (flag, "unknown") == 0)
640 /* We turn on everything except for cpu64 in case of
641 CPU_UNKNOWN_FLAGS. */
642 for (i = 0; i < ARRAY_SIZE (flags); i++)
643 if (flags[i].position != Cpu64)
644 flags[i].value = 1;
646 else if (flag[0] == '~')
648 last = flag + strlen (flag);
650 if (flag[1] == '(')
652 last -= 1;
653 next = flag + 2;
654 if (*last != ')')
655 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
656 lineno, flag);
657 *last = '\0';
659 else
660 next = flag + 1;
662 /* First we turn on everything except for cpu64. */
663 for (i = 0; i < ARRAY_SIZE (flags); i++)
664 if (flags[i].position != Cpu64)
665 flags[i].value = 1;
667 /* Turn off selective bits. */
668 for (; next && next < last; )
670 str = next_field (next, '|', &next, last);
671 if (str)
672 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
675 else if (strcmp (flag, "0"))
677 /* Turn on selective bits. */
678 last = flag + strlen (flag);
679 for (next = flag; next && next < last; )
681 str = next_field (next, '|', &next, last);
682 if (str)
683 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
687 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
688 comma, indent);
691 static void
692 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
694 unsigned int i;
696 fprintf (table, " { ");
698 for (i = 0; i < size - 1; i++)
700 fprintf (table, "%d, ", modifier[i].value);
701 if (((i + 1) % 20) == 0)
702 fprintf (table, "\n ");
705 fprintf (table, "%d },\n", modifier[i].value);
708 static void
709 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
711 char *str, *next, *last;
712 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
714 /* Copy the default opcode modifier. */
715 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
717 if (strcmp (mod, "0"))
719 last = mod + strlen (mod);
720 for (next = mod; next && next < last; )
722 str = next_field (next, '|', &next, last);
723 if (str)
724 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
725 lineno);
728 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
731 static void
732 output_operand_type (FILE *table, bitfield *types, unsigned int size,
733 int macro, const char *indent)
735 unsigned int i;
737 fprintf (table, "{ { ");
739 for (i = 0; i < size - 1; i++)
741 fprintf (table, "%d, ", types[i].value);
742 if (((i + 1) % 20) == 0)
744 /* We need \\ for macro. */
745 if (macro)
746 fprintf (table, "\\\n%s", indent);
747 else
748 fprintf (table, "\n%s", indent);
752 fprintf (table, "%d } }", types[i].value);
755 static void
756 process_i386_operand_type (FILE *table, char *op, int macro,
757 const char *indent, int lineno)
759 char *str, *next, *last;
760 bitfield types [ARRAY_SIZE (operand_types)];
762 /* Copy the default operand type. */
763 memcpy (types, operand_types, sizeof (types));
765 if (strcmp (op, "0"))
767 last = op + strlen (op);
768 for (next = op; next && next < last; )
770 str = next_field (next, '|', &next, last);
771 if (str)
772 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
775 output_operand_type (table, types, ARRAY_SIZE (types), macro,
776 indent);
779 static void
780 output_i386_opcode (FILE *table, const char *name, char *str,
781 char *last, int lineno)
783 unsigned int i;
784 char *operands, *base_opcode, *extension_opcode, *opcode_length;
785 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
787 /* Find number of operands. */
788 operands = next_field (str, ',', &str, last);
790 /* Find base_opcode. */
791 base_opcode = next_field (str, ',', &str, last);
793 /* Find extension_opcode. */
794 extension_opcode = next_field (str, ',', &str, last);
796 /* Find opcode_length. */
797 opcode_length = next_field (str, ',', &str, last);
799 /* Find cpu_flags. */
800 cpu_flags = next_field (str, ',', &str, last);
802 /* Find opcode_modifier. */
803 opcode_modifier = next_field (str, ',', &str, last);
805 /* Remove the first {. */
806 str = remove_leading_whitespaces (str);
807 if (*str != '{')
808 abort ();
809 str = remove_leading_whitespaces (str + 1);
811 i = strlen (str);
813 /* There are at least "X}". */
814 if (i < 2)
815 abort ();
817 /* Remove trailing white spaces and }. */
820 i--;
821 if (ISSPACE (str[i]) || str[i] == '}')
822 str[i] = '\0';
823 else
824 break;
826 while (i != 0);
828 last = str + i;
830 /* Find operand_types. */
831 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
833 if (str >= last)
835 operand_types [i] = NULL;
836 break;
839 operand_types [i] = next_field (str, ',', &str, last);
840 if (*operand_types[i] == '0')
842 if (i != 0)
843 operand_types[i] = NULL;
844 break;
848 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
849 name, operands, base_opcode, extension_opcode,
850 opcode_length);
852 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
854 process_i386_opcode_modifier (table, opcode_modifier, lineno);
856 fprintf (table, " { ");
858 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
860 if (operand_types[i] == NULL || *operand_types[i] == '0')
862 if (i == 0)
863 process_i386_operand_type (table, "0", 0, "\t ", lineno);
864 break;
867 if (i != 0)
868 fprintf (table, ",\n ");
870 process_i386_operand_type (table, operand_types[i], 0,
871 "\t ", lineno);
873 fprintf (table, " } },\n");
876 struct opcode_hash_entry
878 struct opcode_hash_entry *next;
879 char *name;
880 char *opcode;
881 int lineno;
884 /* Calculate the hash value of an opcode hash entry P. */
886 static hashval_t
887 opcode_hash_hash (const void *p)
889 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
890 return htab_hash_string (entry->name);
893 /* Compare a string Q against an opcode hash entry P. */
895 static int
896 opcode_hash_eq (const void *p, const void *q)
898 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
899 const char *name = (const char *) q;
900 return strcmp (name, entry->name) == 0;
903 static void
904 process_i386_opcodes (FILE *table)
906 FILE *fp;
907 char buf[2048];
908 unsigned int i, j;
909 char *str, *p, *last, *name;
910 struct opcode_hash_entry **hash_slot, **entry, *next;
911 htab_t opcode_hash_table;
912 struct opcode_hash_entry **opcode_array;
913 unsigned int opcode_array_size = 1024;
914 int lineno = 0;
916 filename = "i386-opc.tbl";
917 fp = fopen (filename, "r");
919 if (fp == NULL)
920 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
921 xstrerror (errno));
923 i = 0;
924 opcode_array = (struct opcode_hash_entry **)
925 xmalloc (sizeof (*opcode_array) * opcode_array_size);
927 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
928 opcode_hash_eq, NULL,
929 xcalloc, free);
931 fprintf (table, "\n/* i386 opcode table. */\n\n");
932 fprintf (table, "const insn_template i386_optab[] =\n{\n");
934 /* Put everything on opcode array. */
935 while (!feof (fp))
937 if (fgets (buf, sizeof (buf), fp) == NULL)
938 break;
940 lineno++;
942 p = remove_leading_whitespaces (buf);
944 /* Skip comments. */
945 str = strstr (p, "//");
946 if (str != NULL)
947 str[0] = '\0';
949 /* Remove trailing white spaces. */
950 remove_trailing_whitespaces (p);
952 switch (p[0])
954 case '#':
955 /* Ignore comments. */
956 case '\0':
957 continue;
958 break;
959 default:
960 break;
963 last = p + strlen (p);
965 /* Find name. */
966 name = next_field (p, ',', &str, last);
968 /* Get the slot in hash table. */
969 hash_slot = (struct opcode_hash_entry **)
970 htab_find_slot_with_hash (opcode_hash_table, name,
971 htab_hash_string (name),
972 INSERT);
974 if (*hash_slot == NULL)
976 /* It is the new one. Put it on opcode array. */
977 if (i >= opcode_array_size)
979 /* Grow the opcode array when needed. */
980 opcode_array_size += 1024;
981 opcode_array = (struct opcode_hash_entry **)
982 xrealloc (opcode_array,
983 sizeof (*opcode_array) * opcode_array_size);
986 opcode_array[i] = (struct opcode_hash_entry *)
987 xmalloc (sizeof (struct opcode_hash_entry));
988 opcode_array[i]->next = NULL;
989 opcode_array[i]->name = xstrdup (name);
990 opcode_array[i]->opcode = xstrdup (str);
991 opcode_array[i]->lineno = lineno;
992 *hash_slot = opcode_array[i];
993 i++;
995 else
997 /* Append it to the existing one. */
998 entry = hash_slot;
999 while ((*entry) != NULL)
1000 entry = &(*entry)->next;
1001 *entry = (struct opcode_hash_entry *)
1002 xmalloc (sizeof (struct opcode_hash_entry));
1003 (*entry)->next = NULL;
1004 (*entry)->name = (*hash_slot)->name;
1005 (*entry)->opcode = xstrdup (str);
1006 (*entry)->lineno = lineno;
1010 /* Process opcode array. */
1011 for (j = 0; j < i; j++)
1013 for (next = opcode_array[j]; next; next = next->next)
1015 name = next->name;
1016 str = next->opcode;
1017 lineno = next->lineno;
1018 last = str + strlen (str);
1019 output_i386_opcode (table, name, str, last, lineno);
1023 fclose (fp);
1025 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1027 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1029 process_i386_opcode_modifier (table, "0", -1);
1031 fprintf (table, " { ");
1032 process_i386_operand_type (table, "0", 0, "\t ", -1);
1033 fprintf (table, " } }\n");
1035 fprintf (table, "};\n");
1038 static void
1039 process_i386_registers (FILE *table)
1041 FILE *fp;
1042 char buf[2048];
1043 char *str, *p, *last;
1044 char *reg_name, *reg_type, *reg_flags, *reg_num;
1045 char *dw2_32_num, *dw2_64_num;
1046 int lineno = 0;
1048 filename = "i386-reg.tbl";
1049 fp = fopen (filename, "r");
1050 if (fp == NULL)
1051 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1052 xstrerror (errno));
1054 fprintf (table, "\n/* i386 register table. */\n\n");
1055 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1057 while (!feof (fp))
1059 if (fgets (buf, sizeof (buf), fp) == NULL)
1060 break;
1062 lineno++;
1064 p = remove_leading_whitespaces (buf);
1066 /* Skip comments. */
1067 str = strstr (p, "//");
1068 if (str != NULL)
1069 str[0] = '\0';
1071 /* Remove trailing white spaces. */
1072 remove_trailing_whitespaces (p);
1074 switch (p[0])
1076 case '#':
1077 fprintf (table, "%s\n", p);
1078 case '\0':
1079 continue;
1080 break;
1081 default:
1082 break;
1085 last = p + strlen (p);
1087 /* Find reg_name. */
1088 reg_name = next_field (p, ',', &str, last);
1090 /* Find reg_type. */
1091 reg_type = next_field (str, ',', &str, last);
1093 /* Find reg_flags. */
1094 reg_flags = next_field (str, ',', &str, last);
1096 /* Find reg_num. */
1097 reg_num = next_field (str, ',', &str, last);
1099 fprintf (table, " { \"%s\",\n ", reg_name);
1101 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1103 /* Find 32-bit Dwarf2 register number. */
1104 dw2_32_num = next_field (str, ',', &str, last);
1106 /* Find 64-bit Dwarf2 register number. */
1107 dw2_64_num = next_field (str, ',', &str, last);
1109 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1110 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1113 fclose (fp);
1115 fprintf (table, "};\n");
1117 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1120 static void
1121 process_i386_initializers (void)
1123 unsigned int i;
1124 FILE *fp = fopen ("i386-init.h", "w");
1125 char *init;
1127 if (fp == NULL)
1128 fail (_("can't create i386-init.h, errno = %s\n"),
1129 xstrerror (errno));
1131 process_copyright (fp);
1133 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1135 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1136 init = xstrdup (cpu_flag_init[i].init);
1137 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1138 free (init);
1141 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1143 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1144 init = xstrdup (operand_type_init[i].init);
1145 process_i386_operand_type (fp, init, 1, " ", -1);
1146 free (init);
1148 fprintf (fp, "\n");
1150 fclose (fp);
1153 /* Program options. */
1154 #define OPTION_SRCDIR 200
1156 struct option long_options[] =
1158 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1159 {"debug", no_argument, NULL, 'd'},
1160 {"version", no_argument, NULL, 'V'},
1161 {"help", no_argument, NULL, 'h'},
1162 {0, no_argument, NULL, 0}
1165 static void
1166 print_version (void)
1168 printf ("%s: version 1.0\n", program_name);
1169 xexit (0);
1172 static void
1173 usage (FILE * stream, int status)
1175 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1176 program_name);
1177 xexit (status);
1181 main (int argc, char **argv)
1183 extern int chdir (char *);
1184 char *srcdir = NULL;
1185 int c;
1186 FILE *table;
1188 program_name = *argv;
1189 xmalloc_set_program_name (program_name);
1191 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1192 switch (c)
1194 case OPTION_SRCDIR:
1195 srcdir = optarg;
1196 break;
1197 case 'V':
1198 case 'v':
1199 print_version ();
1200 break;
1201 case 'd':
1202 debug = 1;
1203 break;
1204 case 'h':
1205 case '?':
1206 usage (stderr, 0);
1207 default:
1208 case 0:
1209 break;
1212 if (optind != argc)
1213 usage (stdout, 1);
1215 if (srcdir != NULL)
1216 if (chdir (srcdir) != 0)
1217 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1218 srcdir, xstrerror (errno));
1220 /* Check the unused bitfield in i386_cpu_flags. */
1221 #ifndef CpuUnused
1222 c = CpuNumOfBits - CpuMax - 1;
1223 if (c)
1224 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1225 #endif
1227 /* Check the unused bitfield in i386_operand_type. */
1228 #ifndef OTUnused
1229 c = OTNumOfBits - OTMax - 1;
1230 if (c)
1231 fail (_("%d unused bits in i386_operand_type.\n"), c);
1232 #endif
1234 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1235 compare);
1237 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1238 sizeof (opcode_modifiers [0]), compare);
1240 qsort (operand_types, ARRAY_SIZE (operand_types),
1241 sizeof (operand_types [0]), compare);
1243 table = fopen ("i386-tbl.h", "w");
1244 if (table == NULL)
1245 fail (_("can't create i386-tbl.h, errno = %s\n"),
1246 xstrerror (errno));
1248 process_copyright (table);
1250 process_i386_opcodes (table);
1251 process_i386_registers (table);
1252 process_i386_initializers ();
1254 fclose (table);
1256 exit (0);