2009-11-17 Sebastian Pop <sebastian.pop@amd.com>
[binutils.git] / opcodes / i386-gen.c
blob0e0eb8e44f5481273dc5ef3623193feb1f57ce46
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 "~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_8087_FLAGS",
90 "Cpu8087" },
91 { "CPU_287_FLAGS",
92 "Cpu287" },
93 { "CPU_387_FLAGS",
94 "Cpu387" },
95 { "CPU_ANY87_FLAGS",
96 "Cpu8087|Cpu287|Cpu387|Cpu687|CpuFISTTP" },
97 { "CPU_CLFLUSH_FLAGS",
98 "CpuClflush" },
99 { "CPU_SYSCALL_FLAGS",
100 "CpuSYSCALL" },
101 { "CPU_MMX_FLAGS",
102 "CpuMMX" },
103 { "CPU_SSE_FLAGS",
104 "CpuMMX|CpuSSE" },
105 { "CPU_SSE2_FLAGS",
106 "CpuMMX|CpuSSE|CpuSSE2" },
107 { "CPU_SSE3_FLAGS",
108 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3" },
109 { "CPU_SSSE3_FLAGS",
110 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3" },
111 { "CPU_SSE4_1_FLAGS",
112 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1" },
113 { "CPU_SSE4_2_FLAGS",
114 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2" },
115 { "CPU_ANY_SSE_FLAGS",
116 "CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuAVX" },
117 { "CPU_VMX_FLAGS",
118 "CpuVMX" },
119 { "CPU_SMX_FLAGS",
120 "CpuSMX" },
121 { "CPU_XSAVE_FLAGS",
122 "CpuXsave" },
123 { "CPU_AES_FLAGS",
124 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAES" },
125 { "CPU_PCLMUL_FLAGS",
126 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuPCLMUL" },
127 { "CPU_FMA_FLAGS",
128 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA" },
129 { "CPU_FMA4_FLAGS",
130 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX|CpuFMA4" },
131 { "CPU_XOP_FLAGS",
132 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP|CpuCVT16" },
133 { "CPU_CVT16_FLAGS",
134 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuSSE4a|CpuABM|CpuAVX|CpuFMA4|CpuXOP|CpuCVT16" },
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" },
259 typedef struct bitfield
261 int position;
262 int value;
263 const char *name;
264 } bitfield;
266 #define BITFIELD(n) { n, 0, #n }
268 static bitfield cpu_flags[] =
270 BITFIELD (Cpu186),
271 BITFIELD (Cpu286),
272 BITFIELD (Cpu386),
273 BITFIELD (Cpu486),
274 BITFIELD (Cpu586),
275 BITFIELD (Cpu686),
276 BITFIELD (CpuClflush),
277 BITFIELD (CpuSYSCALL),
278 BITFIELD (Cpu8087),
279 BITFIELD (Cpu287),
280 BITFIELD (Cpu387),
281 BITFIELD (Cpu687),
282 BITFIELD (CpuFISTTP),
283 BITFIELD (CpuMMX),
284 BITFIELD (CpuSSE),
285 BITFIELD (CpuSSE2),
286 BITFIELD (CpuSSE3),
287 BITFIELD (CpuSSSE3),
288 BITFIELD (CpuSSE4_1),
289 BITFIELD (CpuSSE4_2),
290 BITFIELD (CpuAVX),
291 BITFIELD (CpuL1OM),
292 BITFIELD (CpuSSE4a),
293 BITFIELD (Cpu3dnow),
294 BITFIELD (Cpu3dnowA),
295 BITFIELD (CpuPadLock),
296 BITFIELD (CpuSVME),
297 BITFIELD (CpuVMX),
298 BITFIELD (CpuSMX),
299 BITFIELD (CpuABM),
300 BITFIELD (CpuXsave),
301 BITFIELD (CpuAES),
302 BITFIELD (CpuPCLMUL),
303 BITFIELD (CpuFMA),
304 BITFIELD (CpuFMA4),
305 BITFIELD (CpuXOP),
306 BITFIELD (CpuCVT16),
307 BITFIELD (CpuLWP),
308 BITFIELD (CpuLM),
309 BITFIELD (CpuMovbe),
310 BITFIELD (CpuEPT),
311 BITFIELD (CpuRdtscp),
312 BITFIELD (Cpu64),
313 BITFIELD (CpuNo64),
314 #ifdef CpuUnused
315 BITFIELD (CpuUnused),
316 #endif
319 static bitfield opcode_modifiers[] =
321 BITFIELD (D),
322 BITFIELD (W),
323 BITFIELD (S),
324 BITFIELD (Modrm),
325 BITFIELD (ShortForm),
326 BITFIELD (Jump),
327 BITFIELD (JumpDword),
328 BITFIELD (JumpByte),
329 BITFIELD (JumpInterSegment),
330 BITFIELD (FloatMF),
331 BITFIELD (FloatR),
332 BITFIELD (FloatD),
333 BITFIELD (Size16),
334 BITFIELD (Size32),
335 BITFIELD (Size64),
336 BITFIELD (IgnoreSize),
337 BITFIELD (DefaultSize),
338 BITFIELD (No_bSuf),
339 BITFIELD (No_wSuf),
340 BITFIELD (No_lSuf),
341 BITFIELD (No_sSuf),
342 BITFIELD (No_qSuf),
343 BITFIELD (No_ldSuf),
344 BITFIELD (FWait),
345 BITFIELD (IsString),
346 BITFIELD (IsLockable),
347 BITFIELD (RegKludge),
348 BITFIELD (FirstXmm0),
349 BITFIELD (Implicit1stXmm0),
350 BITFIELD (ByteOkIntel),
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 (VexNDS),
361 BITFIELD (VexNDD),
362 BITFIELD (VexLWP),
363 BITFIELD (VexW0),
364 BITFIELD (VexW1),
365 BITFIELD (Vex0F),
366 BITFIELD (Vex0F38),
367 BITFIELD (Vex0F3A),
368 BITFIELD (XOP08),
369 BITFIELD (XOP09),
370 BITFIELD (XOP0A),
371 BITFIELD (Vex3Sources),
372 BITFIELD (Vex2Sources),
373 BITFIELD (VexImmExt),
374 BITFIELD (SSE2AVX),
375 BITFIELD (NoAVX),
376 BITFIELD (OldGcc),
377 BITFIELD (ATTMnemonic),
378 BITFIELD (ATTSyntax),
379 BITFIELD (IntelSyntax),
382 static bitfield operand_types[] =
384 BITFIELD (Reg8),
385 BITFIELD (Reg16),
386 BITFIELD (Reg32),
387 BITFIELD (Reg64),
388 BITFIELD (FloatReg),
389 BITFIELD (RegMMX),
390 BITFIELD (RegXMM),
391 BITFIELD (RegYMM),
392 BITFIELD (Imm8),
393 BITFIELD (Imm8S),
394 BITFIELD (Imm16),
395 BITFIELD (Imm32),
396 BITFIELD (Imm32S),
397 BITFIELD (Imm64),
398 BITFIELD (Imm1),
399 BITFIELD (BaseIndex),
400 BITFIELD (Disp8),
401 BITFIELD (Disp16),
402 BITFIELD (Disp32),
403 BITFIELD (Disp32S),
404 BITFIELD (Disp64),
405 BITFIELD (InOutPortReg),
406 BITFIELD (ShiftCount),
407 BITFIELD (Control),
408 BITFIELD (Debug),
409 BITFIELD (Test),
410 BITFIELD (SReg2),
411 BITFIELD (SReg3),
412 BITFIELD (Acc),
413 BITFIELD (FloatAcc),
414 BITFIELD (JumpAbsolute),
415 BITFIELD (EsSeg),
416 BITFIELD (RegMem),
417 BITFIELD (Mem),
418 BITFIELD (Byte),
419 BITFIELD (Word),
420 BITFIELD (Dword),
421 BITFIELD (Fword),
422 BITFIELD (Qword),
423 BITFIELD (Tbyte),
424 BITFIELD (Xmmword),
425 BITFIELD (Ymmword),
426 BITFIELD (Unspecified),
427 BITFIELD (Anysize),
428 #ifdef OTUnused
429 BITFIELD (OTUnused),
430 #endif
433 static const char *filename;
435 static int
436 compare (const void *x, const void *y)
438 const bitfield *xp = (const bitfield *) x;
439 const bitfield *yp = (const bitfield *) y;
440 return xp->position - yp->position;
443 static void
444 fail (const char *message, ...)
446 va_list args;
448 va_start (args, message);
449 fprintf (stderr, _("%s: Error: "), program_name);
450 vfprintf (stderr, message, args);
451 va_end (args);
452 xexit (1);
455 static void
456 process_copyright (FILE *fp)
458 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
459 /* Copyright 2007, 2008, 2009\n\
460 Free Software Foundation, Inc.\n\
462 This file is part of the GNU opcodes library.\n\
464 This library is free software; you can redistribute it and/or modify\n\
465 it under the terms of the GNU General Public License as published by\n\
466 the Free Software Foundation; either version 3, or (at your option)\n\
467 any later version.\n\
469 It is distributed in the hope that it will be useful, but WITHOUT\n\
470 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
471 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
472 License for more details.\n\
474 You should have received a copy of the GNU General Public License\n\
475 along with this program; if not, write to the Free Software\n\
476 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
477 MA 02110-1301, USA. */\n");
480 /* Remove leading white spaces. */
482 static char *
483 remove_leading_whitespaces (char *str)
485 while (ISSPACE (*str))
486 str++;
487 return str;
490 /* Remove trailing white spaces. */
492 static void
493 remove_trailing_whitespaces (char *str)
495 size_t last = strlen (str);
497 if (last == 0)
498 return;
502 last--;
503 if (ISSPACE (str [last]))
504 str[last] = '\0';
505 else
506 break;
508 while (last != 0);
511 /* Find next field separated by SEP and terminate it. Return a
512 pointer to the one after it. */
514 static char *
515 next_field (char *str, char sep, char **next, char *last)
517 char *p;
519 p = remove_leading_whitespaces (str);
520 for (str = p; *str != sep && *str != '\0'; str++);
522 *str = '\0';
523 remove_trailing_whitespaces (p);
525 *next = str + 1;
527 if (p >= last)
528 abort ();
530 return p;
533 static void
534 set_bitfield (const char *f, bitfield *array, int value,
535 unsigned int size, int lineno)
537 unsigned int i;
539 if (strcmp (f, "CpuFP") == 0)
541 set_bitfield("Cpu387", array, value, size, lineno);
542 set_bitfield("Cpu287", array, value, size, lineno);
543 f = "Cpu8087";
545 else if (strcmp (f, "Mmword") == 0)
546 f= "Qword";
547 else if (strcmp (f, "Oword") == 0)
548 f= "Xmmword";
550 for (i = 0; i < size; i++)
551 if (strcasecmp (array[i].name, f) == 0)
553 array[i].value = value;
554 return;
557 if (value)
559 const char *v = strchr (f, '=');
561 if (v)
563 size_t n = v - f;
564 char *end;
566 for (i = 0; i < size; i++)
567 if (strncasecmp (array[i].name, f, n) == 0)
569 value = strtol (v + 1, &end, 0);
570 if (*end == '\0')
572 array[i].value = value;
573 return;
575 break;
580 if (lineno != -1)
581 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
582 else
583 fail (_("Unknown bitfield: %s\n"), f);
586 static void
587 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
588 int macro, const char *comma, const char *indent)
590 unsigned int i;
592 fprintf (table, "%s{ { ", indent);
594 for (i = 0; i < size - 1; i++)
596 fprintf (table, "%d, ", flags[i].value);
597 if (((i + 1) % 20) == 0)
599 /* We need \\ for macro. */
600 if (macro)
601 fprintf (table, " \\\n %s", indent);
602 else
603 fprintf (table, "\n %s", indent);
607 fprintf (table, "%d } }%s\n", flags[i].value, comma);
610 static void
611 process_i386_cpu_flag (FILE *table, char *flag, int macro,
612 const char *comma, const char *indent,
613 int lineno)
615 char *str, *next, *last;
616 unsigned int i;
617 bitfield flags [ARRAY_SIZE (cpu_flags)];
619 /* Copy the default cpu flags. */
620 memcpy (flags, cpu_flags, sizeof (cpu_flags));
622 if (strcasecmp (flag, "unknown") == 0)
624 /* We turn on everything except for cpu64 in case of
625 CPU_UNKNOWN_FLAGS. */
626 for (i = 0; i < ARRAY_SIZE (flags); i++)
627 if (flags[i].position != Cpu64)
628 flags[i].value = 1;
630 else if (flag[0] == '~')
632 last = flag + strlen (flag);
634 if (flag[1] == '(')
636 last -= 1;
637 next = flag + 2;
638 if (*last != ')')
639 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
640 lineno, flag);
641 *last = '\0';
643 else
644 next = flag + 1;
646 /* First we turn on everything except for cpu64. */
647 for (i = 0; i < ARRAY_SIZE (flags); i++)
648 if (flags[i].position != Cpu64)
649 flags[i].value = 1;
651 /* Turn off selective bits. */
652 for (; next && next < last; )
654 str = next_field (next, '|', &next, last);
655 if (str)
656 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
659 else if (strcmp (flag, "0"))
661 /* Turn on selective bits. */
662 last = flag + strlen (flag);
663 for (next = flag; next && next < last; )
665 str = next_field (next, '|', &next, last);
666 if (str)
667 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
671 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
672 comma, indent);
675 static void
676 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
678 unsigned int i;
680 fprintf (table, " { ");
682 for (i = 0; i < size - 1; i++)
684 fprintf (table, "%d, ", modifier[i].value);
685 if (((i + 1) % 20) == 0)
686 fprintf (table, "\n ");
689 fprintf (table, "%d },\n", modifier[i].value);
692 static void
693 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
695 char *str, *next, *last;
696 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
698 /* Copy the default opcode modifier. */
699 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
701 if (strcmp (mod, "0"))
703 last = mod + strlen (mod);
704 for (next = mod; next && next < last; )
706 str = next_field (next, '|', &next, last);
707 if (str)
708 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
709 lineno);
712 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
715 static void
716 output_operand_type (FILE *table, bitfield *types, unsigned int size,
717 int macro, const char *indent)
719 unsigned int i;
721 fprintf (table, "{ { ");
723 for (i = 0; i < size - 1; i++)
725 fprintf (table, "%d, ", types[i].value);
726 if (((i + 1) % 20) == 0)
728 /* We need \\ for macro. */
729 if (macro)
730 fprintf (table, "\\\n%s", indent);
731 else
732 fprintf (table, "\n%s", indent);
736 fprintf (table, "%d } }", types[i].value);
739 static void
740 process_i386_operand_type (FILE *table, char *op, int macro,
741 const char *indent, int lineno)
743 char *str, *next, *last;
744 bitfield types [ARRAY_SIZE (operand_types)];
746 /* Copy the default operand type. */
747 memcpy (types, operand_types, sizeof (types));
749 if (strcmp (op, "0"))
751 last = op + strlen (op);
752 for (next = op; next && next < last; )
754 str = next_field (next, '|', &next, last);
755 if (str)
756 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
759 output_operand_type (table, types, ARRAY_SIZE (types), macro,
760 indent);
763 static void
764 output_i386_opcode (FILE *table, const char *name, char *str,
765 char *last, int lineno)
767 unsigned int i;
768 char *operands, *base_opcode, *extension_opcode, *opcode_length;
769 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
771 /* Find number of operands. */
772 operands = next_field (str, ',', &str, last);
774 /* Find base_opcode. */
775 base_opcode = next_field (str, ',', &str, last);
777 /* Find extension_opcode. */
778 extension_opcode = next_field (str, ',', &str, last);
780 /* Find opcode_length. */
781 opcode_length = next_field (str, ',', &str, last);
783 /* Find cpu_flags. */
784 cpu_flags = next_field (str, ',', &str, last);
786 /* Find opcode_modifier. */
787 opcode_modifier = next_field (str, ',', &str, last);
789 /* Remove the first {. */
790 str = remove_leading_whitespaces (str);
791 if (*str != '{')
792 abort ();
793 str = remove_leading_whitespaces (str + 1);
795 i = strlen (str);
797 /* There are at least "X}". */
798 if (i < 2)
799 abort ();
801 /* Remove trailing white spaces and }. */
804 i--;
805 if (ISSPACE (str[i]) || str[i] == '}')
806 str[i] = '\0';
807 else
808 break;
810 while (i != 0);
812 last = str + i;
814 /* Find operand_types. */
815 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
817 if (str >= last)
819 operand_types [i] = NULL;
820 break;
823 operand_types [i] = next_field (str, ',', &str, last);
824 if (*operand_types[i] == '0')
826 if (i != 0)
827 operand_types[i] = NULL;
828 break;
832 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
833 name, operands, base_opcode, extension_opcode,
834 opcode_length);
836 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
838 process_i386_opcode_modifier (table, opcode_modifier, lineno);
840 fprintf (table, " { ");
842 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
844 if (operand_types[i] == NULL || *operand_types[i] == '0')
846 if (i == 0)
847 process_i386_operand_type (table, "0", 0, "\t ", lineno);
848 break;
851 if (i != 0)
852 fprintf (table, ",\n ");
854 process_i386_operand_type (table, operand_types[i], 0,
855 "\t ", lineno);
857 fprintf (table, " } },\n");
860 struct opcode_hash_entry
862 struct opcode_hash_entry *next;
863 char *name;
864 char *opcode;
865 int lineno;
868 /* Calculate the hash value of an opcode hash entry P. */
870 static hashval_t
871 opcode_hash_hash (const void *p)
873 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
874 return htab_hash_string (entry->name);
877 /* Compare a string Q against an opcode hash entry P. */
879 static int
880 opcode_hash_eq (const void *p, const void *q)
882 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
883 const char *name = (const char *) q;
884 return strcmp (name, entry->name) == 0;
887 static void
888 process_i386_opcodes (FILE *table)
890 FILE *fp;
891 char buf[2048];
892 unsigned int i, j;
893 char *str, *p, *last, *name;
894 struct opcode_hash_entry **hash_slot, **entry, *next;
895 htab_t opcode_hash_table;
896 struct opcode_hash_entry **opcode_array;
897 unsigned int opcode_array_size = 1024;
898 int lineno = 0;
900 filename = "i386-opc.tbl";
901 fp = fopen (filename, "r");
903 if (fp == NULL)
904 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
905 xstrerror (errno));
907 i = 0;
908 opcode_array = (struct opcode_hash_entry **)
909 xmalloc (sizeof (*opcode_array) * opcode_array_size);
911 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
912 opcode_hash_eq, NULL,
913 xcalloc, free);
915 fprintf (table, "\n/* i386 opcode table. */\n\n");
916 fprintf (table, "const insn_template i386_optab[] =\n{\n");
918 /* Put everything on opcode array. */
919 while (!feof (fp))
921 if (fgets (buf, sizeof (buf), fp) == NULL)
922 break;
924 lineno++;
926 p = remove_leading_whitespaces (buf);
928 /* Skip comments. */
929 str = strstr (p, "//");
930 if (str != NULL)
931 str[0] = '\0';
933 /* Remove trailing white spaces. */
934 remove_trailing_whitespaces (p);
936 switch (p[0])
938 case '#':
939 /* Ignore comments. */
940 case '\0':
941 continue;
942 break;
943 default:
944 break;
947 last = p + strlen (p);
949 /* Find name. */
950 name = next_field (p, ',', &str, last);
952 /* Get the slot in hash table. */
953 hash_slot = (struct opcode_hash_entry **)
954 htab_find_slot_with_hash (opcode_hash_table, name,
955 htab_hash_string (name),
956 INSERT);
958 if (*hash_slot == NULL)
960 /* It is the new one. Put it on opcode array. */
961 if (i >= opcode_array_size)
963 /* Grow the opcode array when needed. */
964 opcode_array_size += 1024;
965 opcode_array = (struct opcode_hash_entry **)
966 xrealloc (opcode_array,
967 sizeof (*opcode_array) * opcode_array_size);
970 opcode_array[i] = (struct opcode_hash_entry *)
971 xmalloc (sizeof (struct opcode_hash_entry));
972 opcode_array[i]->next = NULL;
973 opcode_array[i]->name = xstrdup (name);
974 opcode_array[i]->opcode = xstrdup (str);
975 opcode_array[i]->lineno = lineno;
976 *hash_slot = opcode_array[i];
977 i++;
979 else
981 /* Append it to the existing one. */
982 entry = hash_slot;
983 while ((*entry) != NULL)
984 entry = &(*entry)->next;
985 *entry = (struct opcode_hash_entry *)
986 xmalloc (sizeof (struct opcode_hash_entry));
987 (*entry)->next = NULL;
988 (*entry)->name = (*hash_slot)->name;
989 (*entry)->opcode = xstrdup (str);
990 (*entry)->lineno = lineno;
994 /* Process opcode array. */
995 for (j = 0; j < i; j++)
997 for (next = opcode_array[j]; next; next = next->next)
999 name = next->name;
1000 str = next->opcode;
1001 lineno = next->lineno;
1002 last = str + strlen (str);
1003 output_i386_opcode (table, name, str, last, lineno);
1007 fclose (fp);
1009 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1011 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1013 process_i386_opcode_modifier (table, "0", -1);
1015 fprintf (table, " { ");
1016 process_i386_operand_type (table, "0", 0, "\t ", -1);
1017 fprintf (table, " } }\n");
1019 fprintf (table, "};\n");
1022 static void
1023 process_i386_registers (FILE *table)
1025 FILE *fp;
1026 char buf[2048];
1027 char *str, *p, *last;
1028 char *reg_name, *reg_type, *reg_flags, *reg_num;
1029 char *dw2_32_num, *dw2_64_num;
1030 int lineno = 0;
1032 filename = "i386-reg.tbl";
1033 fp = fopen (filename, "r");
1034 if (fp == NULL)
1035 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1036 xstrerror (errno));
1038 fprintf (table, "\n/* i386 register table. */\n\n");
1039 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1041 while (!feof (fp))
1043 if (fgets (buf, sizeof (buf), fp) == NULL)
1044 break;
1046 lineno++;
1048 p = remove_leading_whitespaces (buf);
1050 /* Skip comments. */
1051 str = strstr (p, "//");
1052 if (str != NULL)
1053 str[0] = '\0';
1055 /* Remove trailing white spaces. */
1056 remove_trailing_whitespaces (p);
1058 switch (p[0])
1060 case '#':
1061 fprintf (table, "%s\n", p);
1062 case '\0':
1063 continue;
1064 break;
1065 default:
1066 break;
1069 last = p + strlen (p);
1071 /* Find reg_name. */
1072 reg_name = next_field (p, ',', &str, last);
1074 /* Find reg_type. */
1075 reg_type = next_field (str, ',', &str, last);
1077 /* Find reg_flags. */
1078 reg_flags = next_field (str, ',', &str, last);
1080 /* Find reg_num. */
1081 reg_num = next_field (str, ',', &str, last);
1083 fprintf (table, " { \"%s\",\n ", reg_name);
1085 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1087 /* Find 32-bit Dwarf2 register number. */
1088 dw2_32_num = next_field (str, ',', &str, last);
1090 /* Find 64-bit Dwarf2 register number. */
1091 dw2_64_num = next_field (str, ',', &str, last);
1093 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1094 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1097 fclose (fp);
1099 fprintf (table, "};\n");
1101 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1104 static void
1105 process_i386_initializers (void)
1107 unsigned int i;
1108 FILE *fp = fopen ("i386-init.h", "w");
1109 char *init;
1111 if (fp == NULL)
1112 fail (_("can't create i386-init.h, errno = %s\n"),
1113 xstrerror (errno));
1115 process_copyright (fp);
1117 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1119 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1120 init = xstrdup (cpu_flag_init[i].init);
1121 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1122 free (init);
1125 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1127 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1128 init = xstrdup (operand_type_init[i].init);
1129 process_i386_operand_type (fp, init, 1, " ", -1);
1130 free (init);
1132 fprintf (fp, "\n");
1134 fclose (fp);
1137 /* Program options. */
1138 #define OPTION_SRCDIR 200
1140 struct option long_options[] =
1142 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1143 {"debug", no_argument, NULL, 'd'},
1144 {"version", no_argument, NULL, 'V'},
1145 {"help", no_argument, NULL, 'h'},
1146 {0, no_argument, NULL, 0}
1149 static void
1150 print_version (void)
1152 printf ("%s: version 1.0\n", program_name);
1153 xexit (0);
1156 static void
1157 usage (FILE * stream, int status)
1159 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1160 program_name);
1161 xexit (status);
1165 main (int argc, char **argv)
1167 extern int chdir (char *);
1168 char *srcdir = NULL;
1169 int c;
1170 FILE *table;
1172 program_name = *argv;
1173 xmalloc_set_program_name (program_name);
1175 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1176 switch (c)
1178 case OPTION_SRCDIR:
1179 srcdir = optarg;
1180 break;
1181 case 'V':
1182 case 'v':
1183 print_version ();
1184 break;
1185 case 'd':
1186 debug = 1;
1187 break;
1188 case 'h':
1189 case '?':
1190 usage (stderr, 0);
1191 default:
1192 case 0:
1193 break;
1196 if (optind != argc)
1197 usage (stdout, 1);
1199 if (srcdir != NULL)
1200 if (chdir (srcdir) != 0)
1201 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1202 srcdir, xstrerror (errno));
1204 /* Check the unused bitfield in i386_cpu_flags. */
1205 #ifndef CpuUnused
1206 c = CpuNumOfBits - CpuMax - 1;
1207 if (c)
1208 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1209 #endif
1211 /* Check the unused bitfield in i386_operand_type. */
1212 #ifndef OTUnused
1213 c = OTNumOfBits - OTMax - 1;
1214 if (c)
1215 fail (_("%d unused bits in i386_operand_type.\n"), c);
1216 #endif
1218 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1219 compare);
1221 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1222 sizeof (opcode_modifiers [0]), compare);
1224 qsort (operand_types, ARRAY_SIZE (operand_types),
1225 sizeof (operand_types [0]), compare);
1227 table = fopen ("i386-tbl.h", "w");
1228 if (table == NULL)
1229 fail (_("can't create i386-tbl.h, errno = %s\n"),
1230 xstrerror (errno));
1232 process_copyright (table);
1234 process_i386_opcodes (table);
1235 process_i386_registers (table);
1236 process_i386_initializers ();
1238 fclose (table);
1240 exit (0);