Replace Vex0F, Vex0F38, Vex0F3A, XOP08, XOP09 and XOP0A with VexOpcode.
[deliverable/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" },
133 { "CPU_LWP_FLAGS",
134 "CpuLWP" },
135 { "CPU_MOVBE_FLAGS",
136 "CpuMovbe" },
137 { "CPU_RDTSCP_FLAGS",
138 "CpuRdtscp" },
139 { "CPU_EPT_FLAGS",
140 "CpuEPT" },
141 { "CPU_3DNOW_FLAGS",
142 "CpuMMX|Cpu3dnow" },
143 { "CPU_3DNOWA_FLAGS",
144 "CpuMMX|Cpu3dnow|Cpu3dnowA" },
145 { "CPU_PADLOCK_FLAGS",
146 "CpuPadLock" },
147 { "CPU_SVME_FLAGS",
148 "CpuSVME" },
149 { "CPU_SSE4A_FLAGS",
150 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a" },
151 { "CPU_ABM_FLAGS",
152 "CpuABM" },
153 { "CPU_AVX_FLAGS",
154 "CpuMMX|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1|CpuSSE4_2|CpuAVX" },
155 { "CPU_ANY_AVX_FLAGS",
156 "CpuAVX" },
157 { "CPU_L1OM_FLAGS",
158 "unknown" },
159 };
160
161 static initializer operand_type_init[] =
162 {
163 { "OPERAND_TYPE_NONE",
164 "0" },
165 { "OPERAND_TYPE_REG8",
166 "Reg8" },
167 { "OPERAND_TYPE_REG16",
168 "Reg16" },
169 { "OPERAND_TYPE_REG32",
170 "Reg32" },
171 { "OPERAND_TYPE_REG64",
172 "Reg64" },
173 { "OPERAND_TYPE_IMM1",
174 "Imm1" },
175 { "OPERAND_TYPE_IMM8",
176 "Imm8" },
177 { "OPERAND_TYPE_IMM8S",
178 "Imm8S" },
179 { "OPERAND_TYPE_IMM16",
180 "Imm16" },
181 { "OPERAND_TYPE_IMM32",
182 "Imm32" },
183 { "OPERAND_TYPE_IMM32S",
184 "Imm32S" },
185 { "OPERAND_TYPE_IMM64",
186 "Imm64" },
187 { "OPERAND_TYPE_BASEINDEX",
188 "BaseIndex" },
189 { "OPERAND_TYPE_DISP8",
190 "Disp8" },
191 { "OPERAND_TYPE_DISP16",
192 "Disp16" },
193 { "OPERAND_TYPE_DISP32",
194 "Disp32" },
195 { "OPERAND_TYPE_DISP32S",
196 "Disp32S" },
197 { "OPERAND_TYPE_DISP64",
198 "Disp64" },
199 { "OPERAND_TYPE_INOUTPORTREG",
200 "InOutPortReg" },
201 { "OPERAND_TYPE_SHIFTCOUNT",
202 "ShiftCount" },
203 { "OPERAND_TYPE_CONTROL",
204 "Control" },
205 { "OPERAND_TYPE_TEST",
206 "Test" },
207 { "OPERAND_TYPE_DEBUG",
208 "FloatReg" },
209 { "OPERAND_TYPE_FLOATREG",
210 "FloatReg" },
211 { "OPERAND_TYPE_FLOATACC",
212 "FloatAcc" },
213 { "OPERAND_TYPE_SREG2",
214 "SReg2" },
215 { "OPERAND_TYPE_SREG3",
216 "SReg3" },
217 { "OPERAND_TYPE_ACC",
218 "Acc" },
219 { "OPERAND_TYPE_JUMPABSOLUTE",
220 "JumpAbsolute" },
221 { "OPERAND_TYPE_REGMMX",
222 "RegMMX" },
223 { "OPERAND_TYPE_REGXMM",
224 "RegXMM" },
225 { "OPERAND_TYPE_REGYMM",
226 "RegYMM" },
227 { "OPERAND_TYPE_ESSEG",
228 "EsSeg" },
229 { "OPERAND_TYPE_ACC32",
230 "Reg32|Acc|Dword" },
231 { "OPERAND_TYPE_ACC64",
232 "Reg64|Acc|Qword" },
233 { "OPERAND_TYPE_INOUTPORTREG",
234 "InOutPortReg" },
235 { "OPERAND_TYPE_REG16_INOUTPORTREG",
236 "Reg16|InOutPortReg" },
237 { "OPERAND_TYPE_DISP16_32",
238 "Disp16|Disp32" },
239 { "OPERAND_TYPE_ANYDISP",
240 "Disp8|Disp16|Disp32|Disp32S|Disp64" },
241 { "OPERAND_TYPE_IMM16_32",
242 "Imm16|Imm32" },
243 { "OPERAND_TYPE_IMM16_32S",
244 "Imm16|Imm32S" },
245 { "OPERAND_TYPE_IMM16_32_32S",
246 "Imm16|Imm32|Imm32S" },
247 { "OPERAND_TYPE_IMM32_32S_DISP32",
248 "Imm32|Imm32S|Disp32" },
249 { "OPERAND_TYPE_IMM64_DISP64",
250 "Imm64|Disp64" },
251 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
252 "Imm32|Imm32S|Imm64|Disp32" },
253 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
254 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
255 };
256
257 typedef struct bitfield
258 {
259 int position;
260 int value;
261 const char *name;
262 } bitfield;
263
264 #define BITFIELD(n) { n, 0, #n }
265
266 static bitfield cpu_flags[] =
267 {
268 BITFIELD (Cpu186),
269 BITFIELD (Cpu286),
270 BITFIELD (Cpu386),
271 BITFIELD (Cpu486),
272 BITFIELD (Cpu586),
273 BITFIELD (Cpu686),
274 BITFIELD (CpuClflush),
275 BITFIELD (CpuSYSCALL),
276 BITFIELD (Cpu8087),
277 BITFIELD (Cpu287),
278 BITFIELD (Cpu387),
279 BITFIELD (Cpu687),
280 BITFIELD (CpuFISTTP),
281 BITFIELD (CpuMMX),
282 BITFIELD (CpuSSE),
283 BITFIELD (CpuSSE2),
284 BITFIELD (CpuSSE3),
285 BITFIELD (CpuSSSE3),
286 BITFIELD (CpuSSE4_1),
287 BITFIELD (CpuSSE4_2),
288 BITFIELD (CpuAVX),
289 BITFIELD (CpuL1OM),
290 BITFIELD (CpuSSE4a),
291 BITFIELD (Cpu3dnow),
292 BITFIELD (Cpu3dnowA),
293 BITFIELD (CpuPadLock),
294 BITFIELD (CpuSVME),
295 BITFIELD (CpuVMX),
296 BITFIELD (CpuSMX),
297 BITFIELD (CpuABM),
298 BITFIELD (CpuXsave),
299 BITFIELD (CpuAES),
300 BITFIELD (CpuPCLMUL),
301 BITFIELD (CpuFMA),
302 BITFIELD (CpuFMA4),
303 BITFIELD (CpuXOP),
304 BITFIELD (CpuLWP),
305 BITFIELD (CpuLM),
306 BITFIELD (CpuMovbe),
307 BITFIELD (CpuEPT),
308 BITFIELD (CpuRdtscp),
309 BITFIELD (Cpu64),
310 BITFIELD (CpuNo64),
311 #ifdef CpuUnused
312 BITFIELD (CpuUnused),
313 #endif
314 };
315
316 static bitfield opcode_modifiers[] =
317 {
318 BITFIELD (D),
319 BITFIELD (W),
320 BITFIELD (S),
321 BITFIELD (Modrm),
322 BITFIELD (ShortForm),
323 BITFIELD (Jump),
324 BITFIELD (JumpDword),
325 BITFIELD (JumpByte),
326 BITFIELD (JumpInterSegment),
327 BITFIELD (FloatMF),
328 BITFIELD (FloatR),
329 BITFIELD (FloatD),
330 BITFIELD (Size16),
331 BITFIELD (Size32),
332 BITFIELD (Size64),
333 BITFIELD (IgnoreSize),
334 BITFIELD (DefaultSize),
335 BITFIELD (No_bSuf),
336 BITFIELD (No_wSuf),
337 BITFIELD (No_lSuf),
338 BITFIELD (No_sSuf),
339 BITFIELD (No_qSuf),
340 BITFIELD (No_ldSuf),
341 BITFIELD (FWait),
342 BITFIELD (IsString),
343 BITFIELD (IsLockable),
344 BITFIELD (RegKludge),
345 BITFIELD (FirstXmm0),
346 BITFIELD (Implicit1stXmm0),
347 BITFIELD (ByteOkIntel),
348 BITFIELD (ToDword),
349 BITFIELD (ToQword),
350 BITFIELD (AddrPrefixOp0),
351 BITFIELD (IsPrefix),
352 BITFIELD (ImmExt),
353 BITFIELD (NoRex64),
354 BITFIELD (Rex64),
355 BITFIELD (Ugh),
356 BITFIELD (Vex),
357 BITFIELD (VexNDS),
358 BITFIELD (VexNDD),
359 BITFIELD (VexLWP),
360 BITFIELD (VexW),
361 BITFIELD (VexOpcode),
362 BITFIELD (VexSources),
363 BITFIELD (VexImmExt),
364 BITFIELD (SSE2AVX),
365 BITFIELD (NoAVX),
366 BITFIELD (OldGcc),
367 BITFIELD (ATTMnemonic),
368 BITFIELD (ATTSyntax),
369 BITFIELD (IntelSyntax),
370 };
371
372 static bitfield operand_types[] =
373 {
374 BITFIELD (Reg8),
375 BITFIELD (Reg16),
376 BITFIELD (Reg32),
377 BITFIELD (Reg64),
378 BITFIELD (FloatReg),
379 BITFIELD (RegMMX),
380 BITFIELD (RegXMM),
381 BITFIELD (RegYMM),
382 BITFIELD (Imm8),
383 BITFIELD (Imm8S),
384 BITFIELD (Imm16),
385 BITFIELD (Imm32),
386 BITFIELD (Imm32S),
387 BITFIELD (Imm64),
388 BITFIELD (Imm1),
389 BITFIELD (BaseIndex),
390 BITFIELD (Disp8),
391 BITFIELD (Disp16),
392 BITFIELD (Disp32),
393 BITFIELD (Disp32S),
394 BITFIELD (Disp64),
395 BITFIELD (InOutPortReg),
396 BITFIELD (ShiftCount),
397 BITFIELD (Control),
398 BITFIELD (Debug),
399 BITFIELD (Test),
400 BITFIELD (SReg2),
401 BITFIELD (SReg3),
402 BITFIELD (Acc),
403 BITFIELD (FloatAcc),
404 BITFIELD (JumpAbsolute),
405 BITFIELD (EsSeg),
406 BITFIELD (RegMem),
407 BITFIELD (Mem),
408 BITFIELD (Byte),
409 BITFIELD (Word),
410 BITFIELD (Dword),
411 BITFIELD (Fword),
412 BITFIELD (Qword),
413 BITFIELD (Tbyte),
414 BITFIELD (Xmmword),
415 BITFIELD (Ymmword),
416 BITFIELD (Unspecified),
417 BITFIELD (Anysize),
418 #ifdef OTUnused
419 BITFIELD (OTUnused),
420 #endif
421 };
422
423 static const char *filename;
424
425 static int
426 compare (const void *x, const void *y)
427 {
428 const bitfield *xp = (const bitfield *) x;
429 const bitfield *yp = (const bitfield *) y;
430 return xp->position - yp->position;
431 }
432
433 static void
434 fail (const char *message, ...)
435 {
436 va_list args;
437
438 va_start (args, message);
439 fprintf (stderr, _("%s: Error: "), program_name);
440 vfprintf (stderr, message, args);
441 va_end (args);
442 xexit (1);
443 }
444
445 static void
446 process_copyright (FILE *fp)
447 {
448 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
449 /* Copyright 2007, 2008, 2009\n\
450 Free Software Foundation, Inc.\n\
451 \n\
452 This file is part of the GNU opcodes library.\n\
453 \n\
454 This library is free software; you can redistribute it and/or modify\n\
455 it under the terms of the GNU General Public License as published by\n\
456 the Free Software Foundation; either version 3, or (at your option)\n\
457 any later version.\n\
458 \n\
459 It is distributed in the hope that it will be useful, but WITHOUT\n\
460 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
461 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
462 License for more details.\n\
463 \n\
464 You should have received a copy of the GNU General Public License\n\
465 along with this program; if not, write to the Free Software\n\
466 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
467 MA 02110-1301, USA. */\n");
468 }
469
470 /* Remove leading white spaces. */
471
472 static char *
473 remove_leading_whitespaces (char *str)
474 {
475 while (ISSPACE (*str))
476 str++;
477 return str;
478 }
479
480 /* Remove trailing white spaces. */
481
482 static void
483 remove_trailing_whitespaces (char *str)
484 {
485 size_t last = strlen (str);
486
487 if (last == 0)
488 return;
489
490 do
491 {
492 last--;
493 if (ISSPACE (str [last]))
494 str[last] = '\0';
495 else
496 break;
497 }
498 while (last != 0);
499 }
500
501 /* Find next field separated by SEP and terminate it. Return a
502 pointer to the one after it. */
503
504 static char *
505 next_field (char *str, char sep, char **next, char *last)
506 {
507 char *p;
508
509 p = remove_leading_whitespaces (str);
510 for (str = p; *str != sep && *str != '\0'; str++);
511
512 *str = '\0';
513 remove_trailing_whitespaces (p);
514
515 *next = str + 1;
516
517 if (p >= last)
518 abort ();
519
520 return p;
521 }
522
523 static void
524 set_bitfield (const char *f, bitfield *array, int value,
525 unsigned int size, int lineno)
526 {
527 unsigned int i;
528
529 if (strcmp (f, "CpuFP") == 0)
530 {
531 set_bitfield("Cpu387", array, value, size, lineno);
532 set_bitfield("Cpu287", array, value, size, lineno);
533 f = "Cpu8087";
534 }
535 else if (strcmp (f, "Mmword") == 0)
536 f= "Qword";
537 else if (strcmp (f, "Oword") == 0)
538 f= "Xmmword";
539
540 for (i = 0; i < size; i++)
541 if (strcasecmp (array[i].name, f) == 0)
542 {
543 array[i].value = value;
544 return;
545 }
546
547 if (value)
548 {
549 const char *v = strchr (f, '=');
550
551 if (v)
552 {
553 size_t n = v - f;
554 char *end;
555
556 for (i = 0; i < size; i++)
557 if (strncasecmp (array[i].name, f, n) == 0)
558 {
559 value = strtol (v + 1, &end, 0);
560 if (*end == '\0')
561 {
562 array[i].value = value;
563 return;
564 }
565 break;
566 }
567 }
568 }
569
570 if (lineno != -1)
571 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
572 else
573 fail (_("Unknown bitfield: %s\n"), f);
574 }
575
576 static void
577 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
578 int macro, const char *comma, const char *indent)
579 {
580 unsigned int i;
581
582 fprintf (table, "%s{ { ", indent);
583
584 for (i = 0; i < size - 1; i++)
585 {
586 fprintf (table, "%d, ", flags[i].value);
587 if (((i + 1) % 20) == 0)
588 {
589 /* We need \\ for macro. */
590 if (macro)
591 fprintf (table, " \\\n %s", indent);
592 else
593 fprintf (table, "\n %s", indent);
594 }
595 }
596
597 fprintf (table, "%d } }%s\n", flags[i].value, comma);
598 }
599
600 static void
601 process_i386_cpu_flag (FILE *table, char *flag, int macro,
602 const char *comma, const char *indent,
603 int lineno)
604 {
605 char *str, *next, *last;
606 unsigned int i;
607 bitfield flags [ARRAY_SIZE (cpu_flags)];
608
609 /* Copy the default cpu flags. */
610 memcpy (flags, cpu_flags, sizeof (cpu_flags));
611
612 if (strcasecmp (flag, "unknown") == 0)
613 {
614 /* We turn on everything except for cpu64 in case of
615 CPU_UNKNOWN_FLAGS. */
616 for (i = 0; i < ARRAY_SIZE (flags); i++)
617 if (flags[i].position != Cpu64)
618 flags[i].value = 1;
619 }
620 else if (flag[0] == '~')
621 {
622 last = flag + strlen (flag);
623
624 if (flag[1] == '(')
625 {
626 last -= 1;
627 next = flag + 2;
628 if (*last != ')')
629 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
630 lineno, flag);
631 *last = '\0';
632 }
633 else
634 next = flag + 1;
635
636 /* First we turn on everything except for cpu64. */
637 for (i = 0; i < ARRAY_SIZE (flags); i++)
638 if (flags[i].position != Cpu64)
639 flags[i].value = 1;
640
641 /* Turn off selective bits. */
642 for (; next && next < last; )
643 {
644 str = next_field (next, '|', &next, last);
645 if (str)
646 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
647 }
648 }
649 else if (strcmp (flag, "0"))
650 {
651 /* Turn on selective bits. */
652 last = flag + strlen (flag);
653 for (next = flag; next && next < last; )
654 {
655 str = next_field (next, '|', &next, last);
656 if (str)
657 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
658 }
659 }
660
661 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
662 comma, indent);
663 }
664
665 static void
666 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
667 {
668 unsigned int i;
669
670 fprintf (table, " { ");
671
672 for (i = 0; i < size - 1; i++)
673 {
674 fprintf (table, "%d, ", modifier[i].value);
675 if (((i + 1) % 20) == 0)
676 fprintf (table, "\n ");
677 }
678
679 fprintf (table, "%d },\n", modifier[i].value);
680 }
681
682 static void
683 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
684 {
685 char *str, *next, *last;
686 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
687
688 /* Copy the default opcode modifier. */
689 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
690
691 if (strcmp (mod, "0"))
692 {
693 last = mod + strlen (mod);
694 for (next = mod; next && next < last; )
695 {
696 str = next_field (next, '|', &next, last);
697 if (str)
698 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
699 lineno);
700 }
701 }
702 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
703 }
704
705 static void
706 output_operand_type (FILE *table, bitfield *types, unsigned int size,
707 int macro, const char *indent)
708 {
709 unsigned int i;
710
711 fprintf (table, "{ { ");
712
713 for (i = 0; i < size - 1; i++)
714 {
715 fprintf (table, "%d, ", types[i].value);
716 if (((i + 1) % 20) == 0)
717 {
718 /* We need \\ for macro. */
719 if (macro)
720 fprintf (table, "\\\n%s", indent);
721 else
722 fprintf (table, "\n%s", indent);
723 }
724 }
725
726 fprintf (table, "%d } }", types[i].value);
727 }
728
729 static void
730 process_i386_operand_type (FILE *table, char *op, int macro,
731 const char *indent, int lineno)
732 {
733 char *str, *next, *last;
734 bitfield types [ARRAY_SIZE (operand_types)];
735
736 /* Copy the default operand type. */
737 memcpy (types, operand_types, sizeof (types));
738
739 if (strcmp (op, "0"))
740 {
741 last = op + strlen (op);
742 for (next = op; next && next < last; )
743 {
744 str = next_field (next, '|', &next, last);
745 if (str)
746 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
747 }
748 }
749 output_operand_type (table, types, ARRAY_SIZE (types), macro,
750 indent);
751 }
752
753 static void
754 output_i386_opcode (FILE *table, const char *name, char *str,
755 char *last, int lineno)
756 {
757 unsigned int i;
758 char *operands, *base_opcode, *extension_opcode, *opcode_length;
759 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
760
761 /* Find number of operands. */
762 operands = next_field (str, ',', &str, last);
763
764 /* Find base_opcode. */
765 base_opcode = next_field (str, ',', &str, last);
766
767 /* Find extension_opcode. */
768 extension_opcode = next_field (str, ',', &str, last);
769
770 /* Find opcode_length. */
771 opcode_length = next_field (str, ',', &str, last);
772
773 /* Find cpu_flags. */
774 cpu_flags = next_field (str, ',', &str, last);
775
776 /* Find opcode_modifier. */
777 opcode_modifier = next_field (str, ',', &str, last);
778
779 /* Remove the first {. */
780 str = remove_leading_whitespaces (str);
781 if (*str != '{')
782 abort ();
783 str = remove_leading_whitespaces (str + 1);
784
785 i = strlen (str);
786
787 /* There are at least "X}". */
788 if (i < 2)
789 abort ();
790
791 /* Remove trailing white spaces and }. */
792 do
793 {
794 i--;
795 if (ISSPACE (str[i]) || str[i] == '}')
796 str[i] = '\0';
797 else
798 break;
799 }
800 while (i != 0);
801
802 last = str + i;
803
804 /* Find operand_types. */
805 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
806 {
807 if (str >= last)
808 {
809 operand_types [i] = NULL;
810 break;
811 }
812
813 operand_types [i] = next_field (str, ',', &str, last);
814 if (*operand_types[i] == '0')
815 {
816 if (i != 0)
817 operand_types[i] = NULL;
818 break;
819 }
820 }
821
822 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
823 name, operands, base_opcode, extension_opcode,
824 opcode_length);
825
826 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
827
828 process_i386_opcode_modifier (table, opcode_modifier, lineno);
829
830 fprintf (table, " { ");
831
832 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
833 {
834 if (operand_types[i] == NULL || *operand_types[i] == '0')
835 {
836 if (i == 0)
837 process_i386_operand_type (table, "0", 0, "\t ", lineno);
838 break;
839 }
840
841 if (i != 0)
842 fprintf (table, ",\n ");
843
844 process_i386_operand_type (table, operand_types[i], 0,
845 "\t ", lineno);
846 }
847 fprintf (table, " } },\n");
848 }
849
850 struct opcode_hash_entry
851 {
852 struct opcode_hash_entry *next;
853 char *name;
854 char *opcode;
855 int lineno;
856 };
857
858 /* Calculate the hash value of an opcode hash entry P. */
859
860 static hashval_t
861 opcode_hash_hash (const void *p)
862 {
863 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
864 return htab_hash_string (entry->name);
865 }
866
867 /* Compare a string Q against an opcode hash entry P. */
868
869 static int
870 opcode_hash_eq (const void *p, const void *q)
871 {
872 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
873 const char *name = (const char *) q;
874 return strcmp (name, entry->name) == 0;
875 }
876
877 static void
878 process_i386_opcodes (FILE *table)
879 {
880 FILE *fp;
881 char buf[2048];
882 unsigned int i, j;
883 char *str, *p, *last, *name;
884 struct opcode_hash_entry **hash_slot, **entry, *next;
885 htab_t opcode_hash_table;
886 struct opcode_hash_entry **opcode_array;
887 unsigned int opcode_array_size = 1024;
888 int lineno = 0;
889
890 filename = "i386-opc.tbl";
891 fp = fopen (filename, "r");
892
893 if (fp == NULL)
894 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
895 xstrerror (errno));
896
897 i = 0;
898 opcode_array = (struct opcode_hash_entry **)
899 xmalloc (sizeof (*opcode_array) * opcode_array_size);
900
901 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
902 opcode_hash_eq, NULL,
903 xcalloc, free);
904
905 fprintf (table, "\n/* i386 opcode table. */\n\n");
906 fprintf (table, "const insn_template i386_optab[] =\n{\n");
907
908 /* Put everything on opcode array. */
909 while (!feof (fp))
910 {
911 if (fgets (buf, sizeof (buf), fp) == NULL)
912 break;
913
914 lineno++;
915
916 p = remove_leading_whitespaces (buf);
917
918 /* Skip comments. */
919 str = strstr (p, "//");
920 if (str != NULL)
921 str[0] = '\0';
922
923 /* Remove trailing white spaces. */
924 remove_trailing_whitespaces (p);
925
926 switch (p[0])
927 {
928 case '#':
929 /* Ignore comments. */
930 case '\0':
931 continue;
932 break;
933 default:
934 break;
935 }
936
937 last = p + strlen (p);
938
939 /* Find name. */
940 name = next_field (p, ',', &str, last);
941
942 /* Get the slot in hash table. */
943 hash_slot = (struct opcode_hash_entry **)
944 htab_find_slot_with_hash (opcode_hash_table, name,
945 htab_hash_string (name),
946 INSERT);
947
948 if (*hash_slot == NULL)
949 {
950 /* It is the new one. Put it on opcode array. */
951 if (i >= opcode_array_size)
952 {
953 /* Grow the opcode array when needed. */
954 opcode_array_size += 1024;
955 opcode_array = (struct opcode_hash_entry **)
956 xrealloc (opcode_array,
957 sizeof (*opcode_array) * opcode_array_size);
958 }
959
960 opcode_array[i] = (struct opcode_hash_entry *)
961 xmalloc (sizeof (struct opcode_hash_entry));
962 opcode_array[i]->next = NULL;
963 opcode_array[i]->name = xstrdup (name);
964 opcode_array[i]->opcode = xstrdup (str);
965 opcode_array[i]->lineno = lineno;
966 *hash_slot = opcode_array[i];
967 i++;
968 }
969 else
970 {
971 /* Append it to the existing one. */
972 entry = hash_slot;
973 while ((*entry) != NULL)
974 entry = &(*entry)->next;
975 *entry = (struct opcode_hash_entry *)
976 xmalloc (sizeof (struct opcode_hash_entry));
977 (*entry)->next = NULL;
978 (*entry)->name = (*hash_slot)->name;
979 (*entry)->opcode = xstrdup (str);
980 (*entry)->lineno = lineno;
981 }
982 }
983
984 /* Process opcode array. */
985 for (j = 0; j < i; j++)
986 {
987 for (next = opcode_array[j]; next; next = next->next)
988 {
989 name = next->name;
990 str = next->opcode;
991 lineno = next->lineno;
992 last = str + strlen (str);
993 output_i386_opcode (table, name, str, last, lineno);
994 }
995 }
996
997 fclose (fp);
998
999 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
1000
1001 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1002
1003 process_i386_opcode_modifier (table, "0", -1);
1004
1005 fprintf (table, " { ");
1006 process_i386_operand_type (table, "0", 0, "\t ", -1);
1007 fprintf (table, " } }\n");
1008
1009 fprintf (table, "};\n");
1010 }
1011
1012 static void
1013 process_i386_registers (FILE *table)
1014 {
1015 FILE *fp;
1016 char buf[2048];
1017 char *str, *p, *last;
1018 char *reg_name, *reg_type, *reg_flags, *reg_num;
1019 char *dw2_32_num, *dw2_64_num;
1020 int lineno = 0;
1021
1022 filename = "i386-reg.tbl";
1023 fp = fopen (filename, "r");
1024 if (fp == NULL)
1025 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1026 xstrerror (errno));
1027
1028 fprintf (table, "\n/* i386 register table. */\n\n");
1029 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1030
1031 while (!feof (fp))
1032 {
1033 if (fgets (buf, sizeof (buf), fp) == NULL)
1034 break;
1035
1036 lineno++;
1037
1038 p = remove_leading_whitespaces (buf);
1039
1040 /* Skip comments. */
1041 str = strstr (p, "//");
1042 if (str != NULL)
1043 str[0] = '\0';
1044
1045 /* Remove trailing white spaces. */
1046 remove_trailing_whitespaces (p);
1047
1048 switch (p[0])
1049 {
1050 case '#':
1051 fprintf (table, "%s\n", p);
1052 case '\0':
1053 continue;
1054 break;
1055 default:
1056 break;
1057 }
1058
1059 last = p + strlen (p);
1060
1061 /* Find reg_name. */
1062 reg_name = next_field (p, ',', &str, last);
1063
1064 /* Find reg_type. */
1065 reg_type = next_field (str, ',', &str, last);
1066
1067 /* Find reg_flags. */
1068 reg_flags = next_field (str, ',', &str, last);
1069
1070 /* Find reg_num. */
1071 reg_num = next_field (str, ',', &str, last);
1072
1073 fprintf (table, " { \"%s\",\n ", reg_name);
1074
1075 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1076
1077 /* Find 32-bit Dwarf2 register number. */
1078 dw2_32_num = next_field (str, ',', &str, last);
1079
1080 /* Find 64-bit Dwarf2 register number. */
1081 dw2_64_num = next_field (str, ',', &str, last);
1082
1083 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1084 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1085 }
1086
1087 fclose (fp);
1088
1089 fprintf (table, "};\n");
1090
1091 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1092 }
1093
1094 static void
1095 process_i386_initializers (void)
1096 {
1097 unsigned int i;
1098 FILE *fp = fopen ("i386-init.h", "w");
1099 char *init;
1100
1101 if (fp == NULL)
1102 fail (_("can't create i386-init.h, errno = %s\n"),
1103 xstrerror (errno));
1104
1105 process_copyright (fp);
1106
1107 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1108 {
1109 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1110 init = xstrdup (cpu_flag_init[i].init);
1111 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1112 free (init);
1113 }
1114
1115 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1116 {
1117 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1118 init = xstrdup (operand_type_init[i].init);
1119 process_i386_operand_type (fp, init, 1, " ", -1);
1120 free (init);
1121 }
1122 fprintf (fp, "\n");
1123
1124 fclose (fp);
1125 }
1126
1127 /* Program options. */
1128 #define OPTION_SRCDIR 200
1129
1130 struct option long_options[] =
1131 {
1132 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1133 {"debug", no_argument, NULL, 'd'},
1134 {"version", no_argument, NULL, 'V'},
1135 {"help", no_argument, NULL, 'h'},
1136 {0, no_argument, NULL, 0}
1137 };
1138
1139 static void
1140 print_version (void)
1141 {
1142 printf ("%s: version 1.0\n", program_name);
1143 xexit (0);
1144 }
1145
1146 static void
1147 usage (FILE * stream, int status)
1148 {
1149 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1150 program_name);
1151 xexit (status);
1152 }
1153
1154 int
1155 main (int argc, char **argv)
1156 {
1157 extern int chdir (char *);
1158 char *srcdir = NULL;
1159 int c;
1160 FILE *table;
1161
1162 program_name = *argv;
1163 xmalloc_set_program_name (program_name);
1164
1165 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1166 switch (c)
1167 {
1168 case OPTION_SRCDIR:
1169 srcdir = optarg;
1170 break;
1171 case 'V':
1172 case 'v':
1173 print_version ();
1174 break;
1175 case 'd':
1176 debug = 1;
1177 break;
1178 case 'h':
1179 case '?':
1180 usage (stderr, 0);
1181 default:
1182 case 0:
1183 break;
1184 }
1185
1186 if (optind != argc)
1187 usage (stdout, 1);
1188
1189 if (srcdir != NULL)
1190 if (chdir (srcdir) != 0)
1191 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1192 srcdir, xstrerror (errno));
1193
1194 /* Check the unused bitfield in i386_cpu_flags. */
1195 #ifndef CpuUnused
1196 c = CpuNumOfBits - CpuMax - 1;
1197 if (c)
1198 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1199 #endif
1200
1201 /* Check the unused bitfield in i386_operand_type. */
1202 #ifndef OTUnused
1203 c = OTNumOfBits - OTMax - 1;
1204 if (c)
1205 fail (_("%d unused bits in i386_operand_type.\n"), c);
1206 #endif
1207
1208 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1209 compare);
1210
1211 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1212 sizeof (opcode_modifiers [0]), compare);
1213
1214 qsort (operand_types, ARRAY_SIZE (operand_types),
1215 sizeof (operand_types [0]), compare);
1216
1217 table = fopen ("i386-tbl.h", "w");
1218 if (table == NULL)
1219 fail (_("can't create i386-tbl.h, errno = %s\n"),
1220 xstrerror (errno));
1221
1222 process_copyright (table);
1223
1224 process_i386_opcodes (table);
1225 process_i386_registers (table);
1226 process_i386_initializers ();
1227
1228 fclose (table);
1229
1230 exit (0);
1231 }
This page took 0.06405 seconds and 5 git commands to generate.