Remove ByteOkIntel.
[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 (ToDword),
348 BITFIELD (ToQword),
349 BITFIELD (AddrPrefixOp0),
350 BITFIELD (IsPrefix),
351 BITFIELD (ImmExt),
352 BITFIELD (NoRex64),
353 BITFIELD (Rex64),
354 BITFIELD (Ugh),
355 BITFIELD (Vex),
356 BITFIELD (VexNDS),
357 BITFIELD (VexNDD),
358 BITFIELD (VexLWP),
359 BITFIELD (VexW),
360 BITFIELD (VexOpcode),
361 BITFIELD (VexSources),
362 BITFIELD (VexImmExt),
363 BITFIELD (SSE2AVX),
364 BITFIELD (NoAVX),
365 BITFIELD (OldGcc),
366 BITFIELD (ATTMnemonic),
367 BITFIELD (ATTSyntax),
368 BITFIELD (IntelSyntax),
369 };
370
371 static bitfield operand_types[] =
372 {
373 BITFIELD (Reg8),
374 BITFIELD (Reg16),
375 BITFIELD (Reg32),
376 BITFIELD (Reg64),
377 BITFIELD (FloatReg),
378 BITFIELD (RegMMX),
379 BITFIELD (RegXMM),
380 BITFIELD (RegYMM),
381 BITFIELD (Imm8),
382 BITFIELD (Imm8S),
383 BITFIELD (Imm16),
384 BITFIELD (Imm32),
385 BITFIELD (Imm32S),
386 BITFIELD (Imm64),
387 BITFIELD (Imm1),
388 BITFIELD (BaseIndex),
389 BITFIELD (Disp8),
390 BITFIELD (Disp16),
391 BITFIELD (Disp32),
392 BITFIELD (Disp32S),
393 BITFIELD (Disp64),
394 BITFIELD (InOutPortReg),
395 BITFIELD (ShiftCount),
396 BITFIELD (Control),
397 BITFIELD (Debug),
398 BITFIELD (Test),
399 BITFIELD (SReg2),
400 BITFIELD (SReg3),
401 BITFIELD (Acc),
402 BITFIELD (FloatAcc),
403 BITFIELD (JumpAbsolute),
404 BITFIELD (EsSeg),
405 BITFIELD (RegMem),
406 BITFIELD (Mem),
407 BITFIELD (Byte),
408 BITFIELD (Word),
409 BITFIELD (Dword),
410 BITFIELD (Fword),
411 BITFIELD (Qword),
412 BITFIELD (Tbyte),
413 BITFIELD (Xmmword),
414 BITFIELD (Ymmword),
415 BITFIELD (Unspecified),
416 BITFIELD (Anysize),
417 #ifdef OTUnused
418 BITFIELD (OTUnused),
419 #endif
420 };
421
422 static const char *filename;
423
424 static int
425 compare (const void *x, const void *y)
426 {
427 const bitfield *xp = (const bitfield *) x;
428 const bitfield *yp = (const bitfield *) y;
429 return xp->position - yp->position;
430 }
431
432 static void
433 fail (const char *message, ...)
434 {
435 va_list args;
436
437 va_start (args, message);
438 fprintf (stderr, _("%s: Error: "), program_name);
439 vfprintf (stderr, message, args);
440 va_end (args);
441 xexit (1);
442 }
443
444 static void
445 process_copyright (FILE *fp)
446 {
447 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
448 /* Copyright 2007, 2008, 2009\n\
449 Free Software Foundation, Inc.\n\
450 \n\
451 This file is part of the GNU opcodes library.\n\
452 \n\
453 This library is free software; you can redistribute it and/or modify\n\
454 it under the terms of the GNU General Public License as published by\n\
455 the Free Software Foundation; either version 3, or (at your option)\n\
456 any later version.\n\
457 \n\
458 It is distributed in the hope that it will be useful, but WITHOUT\n\
459 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
460 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
461 License for more details.\n\
462 \n\
463 You should have received a copy of the GNU General Public License\n\
464 along with this program; if not, write to the Free Software\n\
465 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
466 MA 02110-1301, USA. */\n");
467 }
468
469 /* Remove leading white spaces. */
470
471 static char *
472 remove_leading_whitespaces (char *str)
473 {
474 while (ISSPACE (*str))
475 str++;
476 return str;
477 }
478
479 /* Remove trailing white spaces. */
480
481 static void
482 remove_trailing_whitespaces (char *str)
483 {
484 size_t last = strlen (str);
485
486 if (last == 0)
487 return;
488
489 do
490 {
491 last--;
492 if (ISSPACE (str [last]))
493 str[last] = '\0';
494 else
495 break;
496 }
497 while (last != 0);
498 }
499
500 /* Find next field separated by SEP and terminate it. Return a
501 pointer to the one after it. */
502
503 static char *
504 next_field (char *str, char sep, char **next, char *last)
505 {
506 char *p;
507
508 p = remove_leading_whitespaces (str);
509 for (str = p; *str != sep && *str != '\0'; str++);
510
511 *str = '\0';
512 remove_trailing_whitespaces (p);
513
514 *next = str + 1;
515
516 if (p >= last)
517 abort ();
518
519 return p;
520 }
521
522 static void
523 set_bitfield (const char *f, bitfield *array, int value,
524 unsigned int size, int lineno)
525 {
526 unsigned int i;
527
528 if (strcmp (f, "CpuFP") == 0)
529 {
530 set_bitfield("Cpu387", array, value, size, lineno);
531 set_bitfield("Cpu287", array, value, size, lineno);
532 f = "Cpu8087";
533 }
534 else if (strcmp (f, "Mmword") == 0)
535 f= "Qword";
536 else if (strcmp (f, "Oword") == 0)
537 f= "Xmmword";
538
539 for (i = 0; i < size; i++)
540 if (strcasecmp (array[i].name, f) == 0)
541 {
542 array[i].value = value;
543 return;
544 }
545
546 if (value)
547 {
548 const char *v = strchr (f, '=');
549
550 if (v)
551 {
552 size_t n = v - f;
553 char *end;
554
555 for (i = 0; i < size; i++)
556 if (strncasecmp (array[i].name, f, n) == 0)
557 {
558 value = strtol (v + 1, &end, 0);
559 if (*end == '\0')
560 {
561 array[i].value = value;
562 return;
563 }
564 break;
565 }
566 }
567 }
568
569 if (lineno != -1)
570 fail (_("%s: %d: Unknown bitfield: %s\n"), filename, lineno, f);
571 else
572 fail (_("Unknown bitfield: %s\n"), f);
573 }
574
575 static void
576 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
577 int macro, const char *comma, const char *indent)
578 {
579 unsigned int i;
580
581 fprintf (table, "%s{ { ", indent);
582
583 for (i = 0; i < size - 1; i++)
584 {
585 fprintf (table, "%d, ", flags[i].value);
586 if (((i + 1) % 20) == 0)
587 {
588 /* We need \\ for macro. */
589 if (macro)
590 fprintf (table, " \\\n %s", indent);
591 else
592 fprintf (table, "\n %s", indent);
593 }
594 }
595
596 fprintf (table, "%d } }%s\n", flags[i].value, comma);
597 }
598
599 static void
600 process_i386_cpu_flag (FILE *table, char *flag, int macro,
601 const char *comma, const char *indent,
602 int lineno)
603 {
604 char *str, *next, *last;
605 unsigned int i;
606 bitfield flags [ARRAY_SIZE (cpu_flags)];
607
608 /* Copy the default cpu flags. */
609 memcpy (flags, cpu_flags, sizeof (cpu_flags));
610
611 if (strcasecmp (flag, "unknown") == 0)
612 {
613 /* We turn on everything except for cpu64 in case of
614 CPU_UNKNOWN_FLAGS. */
615 for (i = 0; i < ARRAY_SIZE (flags); i++)
616 if (flags[i].position != Cpu64)
617 flags[i].value = 1;
618 }
619 else if (flag[0] == '~')
620 {
621 last = flag + strlen (flag);
622
623 if (flag[1] == '(')
624 {
625 last -= 1;
626 next = flag + 2;
627 if (*last != ')')
628 fail (_("%s: %d: Missing `)' in bitfield: %s\n"), filename,
629 lineno, flag);
630 *last = '\0';
631 }
632 else
633 next = flag + 1;
634
635 /* First we turn on everything except for cpu64. */
636 for (i = 0; i < ARRAY_SIZE (flags); i++)
637 if (flags[i].position != Cpu64)
638 flags[i].value = 1;
639
640 /* Turn off selective bits. */
641 for (; next && next < last; )
642 {
643 str = next_field (next, '|', &next, last);
644 if (str)
645 set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
646 }
647 }
648 else if (strcmp (flag, "0"))
649 {
650 /* Turn on selective bits. */
651 last = flag + strlen (flag);
652 for (next = flag; next && next < last; )
653 {
654 str = next_field (next, '|', &next, last);
655 if (str)
656 set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
657 }
658 }
659
660 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
661 comma, indent);
662 }
663
664 static void
665 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
666 {
667 unsigned int i;
668
669 fprintf (table, " { ");
670
671 for (i = 0; i < size - 1; i++)
672 {
673 fprintf (table, "%d, ", modifier[i].value);
674 if (((i + 1) % 20) == 0)
675 fprintf (table, "\n ");
676 }
677
678 fprintf (table, "%d },\n", modifier[i].value);
679 }
680
681 static void
682 process_i386_opcode_modifier (FILE *table, char *mod, int lineno)
683 {
684 char *str, *next, *last;
685 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
686
687 /* Copy the default opcode modifier. */
688 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
689
690 if (strcmp (mod, "0"))
691 {
692 last = mod + strlen (mod);
693 for (next = mod; next && next < last; )
694 {
695 str = next_field (next, '|', &next, last);
696 if (str)
697 set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers),
698 lineno);
699 }
700 }
701 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
702 }
703
704 static void
705 output_operand_type (FILE *table, bitfield *types, unsigned int size,
706 int macro, const char *indent)
707 {
708 unsigned int i;
709
710 fprintf (table, "{ { ");
711
712 for (i = 0; i < size - 1; i++)
713 {
714 fprintf (table, "%d, ", types[i].value);
715 if (((i + 1) % 20) == 0)
716 {
717 /* We need \\ for macro. */
718 if (macro)
719 fprintf (table, "\\\n%s", indent);
720 else
721 fprintf (table, "\n%s", indent);
722 }
723 }
724
725 fprintf (table, "%d } }", types[i].value);
726 }
727
728 static void
729 process_i386_operand_type (FILE *table, char *op, int macro,
730 const char *indent, int lineno)
731 {
732 char *str, *next, *last;
733 bitfield types [ARRAY_SIZE (operand_types)];
734
735 /* Copy the default operand type. */
736 memcpy (types, operand_types, sizeof (types));
737
738 if (strcmp (op, "0"))
739 {
740 last = op + strlen (op);
741 for (next = op; next && next < last; )
742 {
743 str = next_field (next, '|', &next, last);
744 if (str)
745 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
746 }
747 }
748 output_operand_type (table, types, ARRAY_SIZE (types), macro,
749 indent);
750 }
751
752 static void
753 output_i386_opcode (FILE *table, const char *name, char *str,
754 char *last, int lineno)
755 {
756 unsigned int i;
757 char *operands, *base_opcode, *extension_opcode, *opcode_length;
758 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
759
760 /* Find number of operands. */
761 operands = next_field (str, ',', &str, last);
762
763 /* Find base_opcode. */
764 base_opcode = next_field (str, ',', &str, last);
765
766 /* Find extension_opcode. */
767 extension_opcode = next_field (str, ',', &str, last);
768
769 /* Find opcode_length. */
770 opcode_length = next_field (str, ',', &str, last);
771
772 /* Find cpu_flags. */
773 cpu_flags = next_field (str, ',', &str, last);
774
775 /* Find opcode_modifier. */
776 opcode_modifier = next_field (str, ',', &str, last);
777
778 /* Remove the first {. */
779 str = remove_leading_whitespaces (str);
780 if (*str != '{')
781 abort ();
782 str = remove_leading_whitespaces (str + 1);
783
784 i = strlen (str);
785
786 /* There are at least "X}". */
787 if (i < 2)
788 abort ();
789
790 /* Remove trailing white spaces and }. */
791 do
792 {
793 i--;
794 if (ISSPACE (str[i]) || str[i] == '}')
795 str[i] = '\0';
796 else
797 break;
798 }
799 while (i != 0);
800
801 last = str + i;
802
803 /* Find operand_types. */
804 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
805 {
806 if (str >= last)
807 {
808 operand_types [i] = NULL;
809 break;
810 }
811
812 operand_types [i] = next_field (str, ',', &str, last);
813 if (*operand_types[i] == '0')
814 {
815 if (i != 0)
816 operand_types[i] = NULL;
817 break;
818 }
819 }
820
821 fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
822 name, operands, base_opcode, extension_opcode,
823 opcode_length);
824
825 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
826
827 process_i386_opcode_modifier (table, opcode_modifier, lineno);
828
829 fprintf (table, " { ");
830
831 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
832 {
833 if (operand_types[i] == NULL || *operand_types[i] == '0')
834 {
835 if (i == 0)
836 process_i386_operand_type (table, "0", 0, "\t ", lineno);
837 break;
838 }
839
840 if (i != 0)
841 fprintf (table, ",\n ");
842
843 process_i386_operand_type (table, operand_types[i], 0,
844 "\t ", lineno);
845 }
846 fprintf (table, " } },\n");
847 }
848
849 struct opcode_hash_entry
850 {
851 struct opcode_hash_entry *next;
852 char *name;
853 char *opcode;
854 int lineno;
855 };
856
857 /* Calculate the hash value of an opcode hash entry P. */
858
859 static hashval_t
860 opcode_hash_hash (const void *p)
861 {
862 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
863 return htab_hash_string (entry->name);
864 }
865
866 /* Compare a string Q against an opcode hash entry P. */
867
868 static int
869 opcode_hash_eq (const void *p, const void *q)
870 {
871 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
872 const char *name = (const char *) q;
873 return strcmp (name, entry->name) == 0;
874 }
875
876 static void
877 process_i386_opcodes (FILE *table)
878 {
879 FILE *fp;
880 char buf[2048];
881 unsigned int i, j;
882 char *str, *p, *last, *name;
883 struct opcode_hash_entry **hash_slot, **entry, *next;
884 htab_t opcode_hash_table;
885 struct opcode_hash_entry **opcode_array;
886 unsigned int opcode_array_size = 1024;
887 int lineno = 0;
888
889 filename = "i386-opc.tbl";
890 fp = fopen (filename, "r");
891
892 if (fp == NULL)
893 fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
894 xstrerror (errno));
895
896 i = 0;
897 opcode_array = (struct opcode_hash_entry **)
898 xmalloc (sizeof (*opcode_array) * opcode_array_size);
899
900 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
901 opcode_hash_eq, NULL,
902 xcalloc, free);
903
904 fprintf (table, "\n/* i386 opcode table. */\n\n");
905 fprintf (table, "const insn_template i386_optab[] =\n{\n");
906
907 /* Put everything on opcode array. */
908 while (!feof (fp))
909 {
910 if (fgets (buf, sizeof (buf), fp) == NULL)
911 break;
912
913 lineno++;
914
915 p = remove_leading_whitespaces (buf);
916
917 /* Skip comments. */
918 str = strstr (p, "//");
919 if (str != NULL)
920 str[0] = '\0';
921
922 /* Remove trailing white spaces. */
923 remove_trailing_whitespaces (p);
924
925 switch (p[0])
926 {
927 case '#':
928 /* Ignore comments. */
929 case '\0':
930 continue;
931 break;
932 default:
933 break;
934 }
935
936 last = p + strlen (p);
937
938 /* Find name. */
939 name = next_field (p, ',', &str, last);
940
941 /* Get the slot in hash table. */
942 hash_slot = (struct opcode_hash_entry **)
943 htab_find_slot_with_hash (opcode_hash_table, name,
944 htab_hash_string (name),
945 INSERT);
946
947 if (*hash_slot == NULL)
948 {
949 /* It is the new one. Put it on opcode array. */
950 if (i >= opcode_array_size)
951 {
952 /* Grow the opcode array when needed. */
953 opcode_array_size += 1024;
954 opcode_array = (struct opcode_hash_entry **)
955 xrealloc (opcode_array,
956 sizeof (*opcode_array) * opcode_array_size);
957 }
958
959 opcode_array[i] = (struct opcode_hash_entry *)
960 xmalloc (sizeof (struct opcode_hash_entry));
961 opcode_array[i]->next = NULL;
962 opcode_array[i]->name = xstrdup (name);
963 opcode_array[i]->opcode = xstrdup (str);
964 opcode_array[i]->lineno = lineno;
965 *hash_slot = opcode_array[i];
966 i++;
967 }
968 else
969 {
970 /* Append it to the existing one. */
971 entry = hash_slot;
972 while ((*entry) != NULL)
973 entry = &(*entry)->next;
974 *entry = (struct opcode_hash_entry *)
975 xmalloc (sizeof (struct opcode_hash_entry));
976 (*entry)->next = NULL;
977 (*entry)->name = (*hash_slot)->name;
978 (*entry)->opcode = xstrdup (str);
979 (*entry)->lineno = lineno;
980 }
981 }
982
983 /* Process opcode array. */
984 for (j = 0; j < i; j++)
985 {
986 for (next = opcode_array[j]; next; next = next->next)
987 {
988 name = next->name;
989 str = next->opcode;
990 lineno = next->lineno;
991 last = str + strlen (str);
992 output_i386_opcode (table, name, str, last, lineno);
993 }
994 }
995
996 fclose (fp);
997
998 fprintf (table, " { NULL, 0, 0, 0, 0,\n");
999
1000 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1001
1002 process_i386_opcode_modifier (table, "0", -1);
1003
1004 fprintf (table, " { ");
1005 process_i386_operand_type (table, "0", 0, "\t ", -1);
1006 fprintf (table, " } }\n");
1007
1008 fprintf (table, "};\n");
1009 }
1010
1011 static void
1012 process_i386_registers (FILE *table)
1013 {
1014 FILE *fp;
1015 char buf[2048];
1016 char *str, *p, *last;
1017 char *reg_name, *reg_type, *reg_flags, *reg_num;
1018 char *dw2_32_num, *dw2_64_num;
1019 int lineno = 0;
1020
1021 filename = "i386-reg.tbl";
1022 fp = fopen (filename, "r");
1023 if (fp == NULL)
1024 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1025 xstrerror (errno));
1026
1027 fprintf (table, "\n/* i386 register table. */\n\n");
1028 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1029
1030 while (!feof (fp))
1031 {
1032 if (fgets (buf, sizeof (buf), fp) == NULL)
1033 break;
1034
1035 lineno++;
1036
1037 p = remove_leading_whitespaces (buf);
1038
1039 /* Skip comments. */
1040 str = strstr (p, "//");
1041 if (str != NULL)
1042 str[0] = '\0';
1043
1044 /* Remove trailing white spaces. */
1045 remove_trailing_whitespaces (p);
1046
1047 switch (p[0])
1048 {
1049 case '#':
1050 fprintf (table, "%s\n", p);
1051 case '\0':
1052 continue;
1053 break;
1054 default:
1055 break;
1056 }
1057
1058 last = p + strlen (p);
1059
1060 /* Find reg_name. */
1061 reg_name = next_field (p, ',', &str, last);
1062
1063 /* Find reg_type. */
1064 reg_type = next_field (str, ',', &str, last);
1065
1066 /* Find reg_flags. */
1067 reg_flags = next_field (str, ',', &str, last);
1068
1069 /* Find reg_num. */
1070 reg_num = next_field (str, ',', &str, last);
1071
1072 fprintf (table, " { \"%s\",\n ", reg_name);
1073
1074 process_i386_operand_type (table, reg_type, 0, "\t", lineno);
1075
1076 /* Find 32-bit Dwarf2 register number. */
1077 dw2_32_num = next_field (str, ',', &str, last);
1078
1079 /* Find 64-bit Dwarf2 register number. */
1080 dw2_64_num = next_field (str, ',', &str, last);
1081
1082 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1083 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1084 }
1085
1086 fclose (fp);
1087
1088 fprintf (table, "};\n");
1089
1090 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1091 }
1092
1093 static void
1094 process_i386_initializers (void)
1095 {
1096 unsigned int i;
1097 FILE *fp = fopen ("i386-init.h", "w");
1098 char *init;
1099
1100 if (fp == NULL)
1101 fail (_("can't create i386-init.h, errno = %s\n"),
1102 xstrerror (errno));
1103
1104 process_copyright (fp);
1105
1106 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1107 {
1108 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1109 init = xstrdup (cpu_flag_init[i].init);
1110 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1111 free (init);
1112 }
1113
1114 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
1115 {
1116 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
1117 init = xstrdup (operand_type_init[i].init);
1118 process_i386_operand_type (fp, init, 1, " ", -1);
1119 free (init);
1120 }
1121 fprintf (fp, "\n");
1122
1123 fclose (fp);
1124 }
1125
1126 /* Program options. */
1127 #define OPTION_SRCDIR 200
1128
1129 struct option long_options[] =
1130 {
1131 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1132 {"debug", no_argument, NULL, 'd'},
1133 {"version", no_argument, NULL, 'V'},
1134 {"help", no_argument, NULL, 'h'},
1135 {0, no_argument, NULL, 0}
1136 };
1137
1138 static void
1139 print_version (void)
1140 {
1141 printf ("%s: version 1.0\n", program_name);
1142 xexit (0);
1143 }
1144
1145 static void
1146 usage (FILE * stream, int status)
1147 {
1148 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1149 program_name);
1150 xexit (status);
1151 }
1152
1153 int
1154 main (int argc, char **argv)
1155 {
1156 extern int chdir (char *);
1157 char *srcdir = NULL;
1158 int c;
1159 FILE *table;
1160
1161 program_name = *argv;
1162 xmalloc_set_program_name (program_name);
1163
1164 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
1165 switch (c)
1166 {
1167 case OPTION_SRCDIR:
1168 srcdir = optarg;
1169 break;
1170 case 'V':
1171 case 'v':
1172 print_version ();
1173 break;
1174 case 'd':
1175 debug = 1;
1176 break;
1177 case 'h':
1178 case '?':
1179 usage (stderr, 0);
1180 default:
1181 case 0:
1182 break;
1183 }
1184
1185 if (optind != argc)
1186 usage (stdout, 1);
1187
1188 if (srcdir != NULL)
1189 if (chdir (srcdir) != 0)
1190 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1191 srcdir, xstrerror (errno));
1192
1193 /* Check the unused bitfield in i386_cpu_flags. */
1194 #ifndef CpuUnused
1195 c = CpuNumOfBits - CpuMax - 1;
1196 if (c)
1197 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
1198 #endif
1199
1200 /* Check the unused bitfield in i386_operand_type. */
1201 #ifndef OTUnused
1202 c = OTNumOfBits - OTMax - 1;
1203 if (c)
1204 fail (_("%d unused bits in i386_operand_type.\n"), c);
1205 #endif
1206
1207 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
1208 compare);
1209
1210 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
1211 sizeof (opcode_modifiers [0]), compare);
1212
1213 qsort (operand_types, ARRAY_SIZE (operand_types),
1214 sizeof (operand_types [0]), compare);
1215
1216 table = fopen ("i386-tbl.h", "w");
1217 if (table == NULL)
1218 fail (_("can't create i386-tbl.h, errno = %s\n"),
1219 xstrerror (errno));
1220
1221 process_copyright (table);
1222
1223 process_i386_opcodes (table);
1224 process_i386_registers (table);
1225 process_i386_initializers ();
1226
1227 fclose (table);
1228
1229 exit (0);
1230 }
This page took 0.054086 seconds and 4 git commands to generate.