2009-11-17 Sebastian Pop <sebastian.pop@amd.com>
[binutils-gdb.git] / opcodes / i386-gen.c
1 /* Copyright 2007, 2008, 2009
2 Free Software Foundation, Inc.
3
4 This file is part of the GNU opcodes library.
5
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.
10
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.
15
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. */
20
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"
28
29 #include "i386-opc.h"
30
31 #include <libintl.h>
32 #define _(String) gettext (String)
33
34 static const char *program_name = NULL;
35 static int debug = 0;
36
37 typedef struct initializer
38 {
39 const char *name;
40 const char *init;
41 } initializer;
42
43 static initializer cpu_flag_init[] =
44 {
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" },
161 };
162
163 static initializer operand_type_init[] =
164 {
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 };
258
259 typedef struct bitfield
260 {
261 int position;
262 int value;
263 const char *name;
264 } bitfield;
265
266 #define BITFIELD(n) { n, 0, #n }
267
268 static bitfield cpu_flags[] =
269 {
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
317 };
318
319 static bitfield opcode_modifiers[] =
320 {
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),
380 };
381
382 static bitfield operand_types[] =
383 {
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
431 };
432
433 static const char *filename;
434
435 static int
436 compare (const void *x, const void *y)
437 {
438 const bitfield *xp = (const bitfield *) x;
439 const bitfield *yp = (const bitfield *) y;
440 return xp->position - yp->position;
441 }
442
443 static void
444 fail (const char *message, ...)
445 {
446 va_list args;
447
448 va_start (args, message);
449 fprintf (stderr, _("%s: Error: "), program_name);
450 vfprintf (stderr, message, args);
451 va_end (args);
452 xexit (1);
453 }
454
455 static void
456 process_copyright (FILE *fp)
457 {
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\
461 \n\
462 This file is part of the GNU opcodes library.\n\
463 \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\
468 \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\
473 \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");
478 }
479
480 /* Remove leading white spaces. */
481
482 static char *
483 remove_leading_whitespaces (char *str)
484 {
485 while (ISSPACE (*str))
486 str++;
487 return str;
488 }
489
490 /* Remove trailing white spaces. */
491
492 static void
493 remove_trailing_whitespaces (char *str)
494 {
495 size_t last = strlen (str);
496
497 if (last == 0)
498 return;
499
500 do
501 {
502 last--;
503 if (ISSPACE (str [last]))
504 str[last] = '\0';
505 else
506 break;
507 }
508 while (last != 0);
509 }
510
511 /* Find next field separated by SEP and terminate it. Return a
512 pointer to the one after it. */
513
514 static char *
515 next_field (char *str, char sep, char **next, char *last)
516 {
517 char *p;
518
519 p = remove_leading_whitespaces (str);
520 for (str = p; *str != sep && *str != '\0'; str++);
521
522 *str = '\0';
523 remove_trailing_whitespaces (p);
524
525 *next = str + 1;
526
527 if (p >= last)
528 abort ();
529
530 return p;
531 }
532
533 static void
534 set_bitfield (const char *f, bitfield *array, int value,
535 unsigned int size, int lineno)
536 {
537 unsigned int i;
538
539 if (strcmp (f, "CpuFP") == 0)
540 {
541 set_bitfield("Cpu387", array, value, size, lineno);
542 set_bitfield("Cpu287", array, value, size, lineno);
543 f = "Cpu8087";
544 }
545 else if (strcmp (f, "Mmword") == 0)
546 f= "Qword";
547 else if (strcmp (f, "Oword") == 0)
548 f= "Xmmword";
549
550 for (i = 0; i < size; i++)
551 if (strcasecmp (array[i].name, f) == 0)
552 {
553 array[i].value = value;
554 return;
555 }
556
557 if (value)
558 {
559 const char *v = strchr (f, '=');
560
561 if (v)
562 {
563 size_t n = v - f;
564 char *end;
565
566 for (i = 0; i < size; i++)
567 if (strncasecmp (array[i].name, f, n) == 0)
568 {
569 value = strtol (v + 1, &end, 0);
570 if (*end == '\0')
571 {
572 array[i].value = value;
573 return;
574 }
575 break;
576 }
577 }
578 }
579
580 if (lineno != -1)
581 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
582 else
583 fail (_("Unknown bitfield: %s\n"), f);
584 }
585
586 static void
587 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
588 int macro, const char *comma, const char *indent)
589 {
590 unsigned int i;
591
592 fprintf (table, "%s{ { ", indent);
593
594 for (i = 0; i < size - 1; i++)
595 {
596 fprintf (table, "%d, ", flags[i].value);
597 if (((i + 1) % 20) == 0)
598 {
599 /* We need \\ for macro. */
600 if (macro)
601 fprintf (table, " \\\n %s", indent);
602 else
603 fprintf (table, "\n %s", indent);
604 }
605 }
606
607 fprintf (table, "%d } }%s\n", flags[i].value, comma);
608 }
609
610 static void
611 process_i386_cpu_flag (FILE *table, char *flag, int macro,
612 const char *comma, const char *indent,
613 int lineno)
614 {
615 char *str, *next, *last;
616 unsigned int i;
617 bitfield flags [ARRAY_SIZE (cpu_flags)];
618
619 /* Copy the default cpu flags. */
620 memcpy (flags, cpu_flags, sizeof (cpu_flags));
621
622 if (strcasecmp (flag, "unknown") == 0)
623 {
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;
629 }
630 else if (flag[0] == '~')
631 {
632 last = flag + strlen (flag);
633
634 if (flag[1] == '(')
635 {
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';
642 }
643 else
644 next = flag + 1;
645
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;
650
651 /* Turn off selective bits. */
652 for (; next && next < last; )
653 {
654 str = next_field (next, '|', &next, last);
655 if (str)
656 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
657 }
658 }
659 else if (strcmp (flag, "0"))
660 {
661 /* Turn on selective bits. */
662 last = flag + strlen (flag);
663 for (next = flag; next && next < last; )
664 {
665 str = next_field (next, '|', &next, last);
666 if (str)
667 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
668 }
669 }
670
671 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
672 comma, indent);
673 }
674
675 static void
676 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
677 {
678 unsigned int i;
679
680 fprintf (table, " { ");
681
682 for (i = 0; i < size - 1; i++)
683 {
684 fprintf (table, "%d, ", modifier[i].value);
685 if (((i + 1) % 20) == 0)
686 fprintf (table, "\n ");
687 }
688
689 fprintf (table, "%d },\n", modifier[i].value);
690 }
691
692 static void
693 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
694 {
695 char *str, *next, *last;
696 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
697
698 /* Copy the default opcode modifier. */
699 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
700
701 if (strcmp (mod, "0"))
702 {
703 last = mod + strlen (mod);
704 for (next = mod; next && next < last; )
705 {
706 str = next_field (next, '|', &next, last);
707 if (str)
708 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
709 lineno);
710 }
711 }
712 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
713 }
714
715 static void
716 output_operand_type (FILE *table, bitfield *types, unsigned int size,
717 int macro, const char *indent)
718 {
719 unsigned int i;
720
721 fprintf (table, "{ { ");
722
723 for (i = 0; i < size - 1; i++)
724 {
725 fprintf (table, "%d, ", types[i].value);
726 if (((i + 1) % 20) == 0)
727 {
728 /* We need \\ for macro. */
729 if (macro)
730 fprintf (table, "\\\n%s", indent);
731 else
732 fprintf (table, "\n%s", indent);
733 }
734 }
735
736 fprintf (table, "%d } }", types[i].value);
737 }
738
739 static void
740 process_i386_operand_type (FILE *table, char *op, int macro,
741 const char *indent, int lineno)
742 {
743 char *str, *next, *last;
744 bitfield types [ARRAY_SIZE (operand_types)];
745
746 /* Copy the default operand type. */
747 memcpy (types, operand_types, sizeof (types));
748
749 if (strcmp (op, "0"))
750 {
751 last = op + strlen (op);
752 for (next = op; next && next < last; )
753 {
754 str = next_field (next, '|', &next, last);
755 if (str)
756 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
757 }
758 }
759 output_operand_type (table, types, ARRAY_SIZE (types), macro,
760 indent);
761 }
762
763 static void
764 output_i386_opcode (FILE *table, const char *name, char *str,
765 char *last, int lineno)
766 {
767 unsigned int i;
768 char *operands, *base_opcode, *extension_opcode, *opcode_length;
769 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
770
771 /* Find number of operands. */
772 operands = next_field (str, ',', &str, last);
773
774 /* Find base_opcode. */
775 base_opcode = next_field (str, ',', &str, last);
776
777 /* Find extension_opcode. */
778 extension_opcode = next_field (str, ',', &str, last);
779
780 /* Find opcode_length. */
781 opcode_length = next_field (str, ',', &str, last);
782
783 /* Find cpu_flags. */
784 cpu_flags = next_field (str, ',', &str, last);
785
786 /* Find opcode_modifier. */
787 opcode_modifier = next_field (str, ',', &str, last);
788
789 /* Remove the first {. */
790 str = remove_leading_whitespaces (str);
791 if (*str != '{')
792 abort ();
793 str = remove_leading_whitespaces (str + 1);
794
795 i = strlen (str);
796
797 /* There are at least "X}". */
798 if (i < 2)
799 abort ();
800
801 /* Remove trailing white spaces and }. */
802 do
803 {
804 i--;
805 if (ISSPACE (str[i]) || str[i] == '}')
806 str[i] = '\0';
807 else
808 break;
809 }
810 while (i != 0);
811
812 last = str + i;
813
814 /* Find operand_types. */
815 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
816 {
817 if (str >= last)
818 {
819 operand_types [i] = NULL;
820 break;
821 }
822
823 operand_types [i] = next_field (str, ',', &str, last);
824 if (*operand_types[i] == '0')
825 {
826 if (i != 0)
827 operand_types[i] = NULL;
828 break;
829 }
830 }
831
832 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
833 name, operands, base_opcode, extension_opcode,
834 opcode_length);
835
836 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
837
838 process_i386_opcode_modifier (table, opcode_modifier, lineno);
839
840 fprintf (table, " { ");
841
842 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
843 {
844 if (operand_types[i] == NULL || *operand_types[i] == '0')
845 {
846 if (i == 0)
847 process_i386_operand_type (table, "0", 0, "\t ", lineno);
848 break;
849 }
850
851 if (i != 0)
852 fprintf (table, ",\n ");
853
854 process_i386_operand_type (table, operand_types[i], 0,
855 "\t ", lineno);
856 }
857 fprintf (table, " } },\n");
858 }
859
860 struct opcode_hash_entry
861 {
862 struct opcode_hash_entry *next;
863 char *name;
864 char *opcode;
865 int lineno;
866 };
867
868 /* Calculate the hash value of an opcode hash entry P. */
869
870 static hashval_t
871 opcode_hash_hash (const void *p)
872 {
873 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
874 return htab_hash_string (entry->name);
875 }
876
877 /* Compare a string Q against an opcode hash entry P. */
878
879 static int
880 opcode_hash_eq (const void *p, const void *q)
881 {
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;
885 }
886
887 static void
888 process_i386_opcodes (FILE *table)
889 {
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;
899
900 filename = "i386-opc.tbl";
901 fp = fopen (filename, "r");
902
903 if (fp == NULL)
904 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
905 xstrerror (errno));
906
907 i = 0;
908 opcode_array = (struct opcode_hash_entry **)
909 xmalloc (sizeof (*opcode_array) * opcode_array_size);
910
911 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
912 opcode_hash_eq, NULL,
913 xcalloc, free);
914
915 fprintf (table, "\n/* i386 opcode table. */\n\n");
916 fprintf (table, "const insn_template i386_optab[] =\n{\n");
917
918 /* Put everything on opcode array. */
919 while (!feof (fp))
920 {
921 if (fgets (buf, sizeof (buf), fp) == NULL)
922 break;
923
924 lineno++;
925
926 p = remove_leading_whitespaces (buf);
927
928 /* Skip comments. */
929 str = strstr (p, "//");
930 if (str != NULL)
931 str[0] = '\0';
932
933 /* Remove trailing white spaces. */
934 remove_trailing_whitespaces (p);
935
936 switch (p[0])
937 {
938 case '#':
939 /* Ignore comments. */
940 case '\0':
941 continue;
942 break;
943 default:
944 break;
945 }
946
947 last = p + strlen (p);
948
949 /* Find name. */
950 name = next_field (p, ',', &str, last);
951
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);
957
958 if (*hash_slot == NULL)
959 {
960 /* It is the new one. Put it on opcode array. */
961 if (i >= opcode_array_size)
962 {
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);
968 }
969
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++;
978 }
979 else
980 {
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;
991 }
992 }
993
994 /* Process opcode array. */
995 for (j = 0; j < i; j++)
996 {
997 for (next = opcode_array[j]; next; next = next->next)
998 {
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);
1004 }
1005 }
1006
1007 fclose (fp);
1008
1009 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1010
1011 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1012
1013 process_i386_opcode_modifier (table, "0", -1);
1014
1015 fprintf (table, " { ");
1016 process_i386_operand_type (table, "0", 0, "\t ", -1);
1017 fprintf (table, " } }\n");
1018
1019 fprintf (table, "};\n");
1020 }
1021
1022 static void
1023 process_i386_registers (FILE *table)
1024 {
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;
1031
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));
1037
1038 fprintf (table, "\n/* i386 register table. */\n\n");
1039 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1040
1041 while (!feof (fp))
1042 {
1043 if (fgets (buf, sizeof (buf), fp) == NULL)
1044 break;
1045
1046 lineno++;
1047
1048 p = remove_leading_whitespaces (buf);
1049
1050 /* Skip comments. */
1051 str = strstr (p, "//");
1052 if (str != NULL)
1053 str[0] = '\0';
1054
1055 /* Remove trailing white spaces. */
1056 remove_trailing_whitespaces (p);
1057
1058 switch (p[0])
1059 {
1060 case '#':
1061 fprintf (table, "%s\n", p);
1062 case '\0':
1063 continue;
1064 break;
1065 default:
1066 break;
1067 }
1068
1069 last = p + strlen (p);
1070
1071 /* Find reg_name. */
1072 reg_name = next_field (p, ',', &str, last);
1073
1074 /* Find reg_type. */
1075 reg_type = next_field (str, ',', &str, last);
1076
1077 /* Find reg_flags. */
1078 reg_flags = next_field (str, ',', &str, last);
1079
1080 /* Find reg_num. */
1081 reg_num = next_field (str, ',', &str, last);
1082
1083 fprintf (table, " { \"%s\",\n ", reg_name);
1084
1085 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1086
1087 /* Find 32-bit Dwarf2 register number. */
1088 dw2_32_num = next_field (str, ',', &str, last);
1089
1090 /* Find 64-bit Dwarf2 register number. */
1091 dw2_64_num = next_field (str, ',', &str, last);
1092
1093 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1094 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1095 }
1096
1097 fclose (fp);
1098
1099 fprintf (table, "};\n");
1100
1101 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1102 }
1103
1104 static void
1105 process_i386_initializers (void)
1106 {
1107 unsigned int i;
1108 FILE *fp = fopen ("i386-init.h", "w");
1109 char *init;
1110
1111 if (fp == NULL)
1112 fail (_("can't create i386-init.h, errno = %s\n"),
1113 xstrerror (errno));
1114
1115 process_copyright (fp);
1116
1117 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1118 {
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);
1123 }
1124
1125 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1126 {
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);
1131 }
1132 fprintf (fp, "\n");
1133
1134 fclose (fp);
1135 }
1136
1137 /* Program options. */
1138 #define OPTION_SRCDIR 200
1139
1140 struct option long_options[] =
1141 {
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}
1147 };
1148
1149 static void
1150 print_version (void)
1151 {
1152 printf ("%s: version 1.0\n", program_name);
1153 xexit (0);
1154 }
1155
1156 static void
1157 usage (FILE * stream, int status)
1158 {
1159 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1160 program_name);
1161 xexit (status);
1162 }
1163
1164 int
1165 main (int argc, char **argv)
1166 {
1167 extern int chdir (char *);
1168 char *srcdir = NULL;
1169 int c;
1170 FILE *table;
1171
1172 program_name = *argv;
1173 xmalloc_set_program_name (program_name);
1174
1175 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1176 switch (c)
1177 {
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;
1194 }
1195
1196 if (optind != argc)
1197 usage (stdout, 1);
1198
1199 if (srcdir != NULL)
1200 if (chdir (srcdir) != 0)
1201 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1202 srcdir, xstrerror (errno));
1203
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
1210
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
1217
1218 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1219 compare);
1220
1221 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1222 sizeof (opcode_modifiers [0]), compare);
1223
1224 qsort (operand_types, ARRAY_SIZE (operand_types),
1225 sizeof (operand_types [0]), compare);
1226
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));
1231
1232 process_copyright (table);
1233
1234 process_i386_opcodes (table);
1235 process_i386_registers (table);
1236 process_i386_initializers ();
1237
1238 fclose (table);
1239
1240 exit (0);
1241 }