2.41 Release sources
[binutils-gdb.git] / opcodes / i386-gen.c
blob1db555d86156770917652fe16556d541e7b2fce2
1 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
20 #include "sysdep.h"
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include "getopt.h"
25 #include "libiberty.h"
26 #include "hashtab.h"
27 #include "safe-ctype.h"
29 #include "i386-opc.h"
31 /* Build-time checks are preferrable over runtime ones. Use this construct
32 in preference where possible. */
33 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
35 static const char *program_name = NULL;
36 static int debug = 0;
38 typedef struct dependency
40 const char *name;
41 /* Note: Only direct dependencies should be enumerated. */
42 const char *deps;
43 } dependency;
45 static const dependency isa_dependencies[] =
47 { "UNKNOWN",
48 "~IAMCU" },
49 { "GENERIC32",
50 "386" },
51 { "GENERIC64",
52 "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" },
53 { "NONE",
54 "0" },
55 { "PENTIUMPRO",
56 "686|Nop" },
57 { "P2",
58 "PENTIUMPRO|MMX" },
59 { "P3",
60 "P2|SSE" },
61 { "P4",
62 "P3|Clflush|SSE2" },
63 { "NOCONA",
64 "GENERIC64|FISTTP|SSE3|MONITOR|CX16" },
65 { "CORE",
66 "P4|FISTTP|SSE3|MONITOR|CX16" },
67 { "CORE2",
68 "NOCONA|SSSE3" },
69 { "COREI7",
70 "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" },
71 { "K6",
72 "186|286|386|486|586|SYSCALL|387|MMX" },
73 { "K6_2",
74 "K6|3dnow" },
75 { "ATHLON",
76 "K6_2|686:min|687|Nop|3dnowA" },
77 { "K8",
78 "ATHLON|Rdtscp|SSE2|LM" },
79 { "AMDFAM10",
80 "K8|FISTTP|SSE4A|ABM|MONITOR" },
81 { "BDVER1",
82 "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMUL|PRFCHW" },
83 { "BDVER2",
84 "BDVER1|FMA|BMI|TBM|F16C" },
85 { "BDVER3",
86 "BDVER2|Xsaveopt|FSGSBase" },
87 { "BDVER4",
88 "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" },
89 { "ZNVER1",
90 "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|AVX2|SSE4A|ABM|SVME|AES|PCLMUL|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" },
91 { "ZNVER2",
92 "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" },
93 { "ZNVER3",
94 "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" },
95 { "ZNVER4",
96 "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" },
97 { "BTVER1",
98 "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" },
99 { "BTVER2",
100 "BTVER1|AVX|BMI|F16C|AES|PCLMUL|Movbe|Xsaveopt|PRFCHW" },
101 { "286",
102 "186" },
103 { "386",
104 "286" },
105 { "486",
106 "386" },
107 { "586",
108 "486|387" },
109 { "586:nofpu",
110 "486" },
111 { "686",
112 "586|687|CMOV|FXSR" },
113 { "686:min",
114 "586|687" },
115 { "687",
116 "387" },
117 { "FISTTP",
118 "687" },
119 { "SSE",
120 "FXSR" },
121 { "SSE2",
122 "SSE" },
123 { "SSE3",
124 "SSE2" },
125 { "SSSE3",
126 "SSE3" },
127 { "SSE4_1",
128 "SSSE3" },
129 { "SSE4_2",
130 "SSE4_1|POPCNT" },
131 { "Xsaveopt",
132 "XSAVE" },
133 { "AES",
134 "SSE2" },
135 { "PCLMUL",
136 "SSE2" },
137 { "FMA",
138 "AVX" },
139 { "FMA4",
140 "AVX" },
141 { "XOP",
142 "SSE4A|FMA4" },
143 { "LWP",
144 "XSAVE" },
145 { "F16C",
146 "AVX" },
147 { "3dnow",
148 "MMX" },
149 { "3dnowA",
150 "3dnow" },
151 { "SSE4a",
152 "SSE3" },
153 { "ABM",
154 "LZCNT|POPCNT" },
155 { "AVX",
156 "SSE4_2|XSAVE" },
157 { "AVX2",
158 "AVX" },
159 { "AVX_VNNI",
160 "AVX2" },
161 { "AVX_IFMA",
162 "AVX2" },
163 { "AVX_VNNI_INT8",
164 "AVX2" },
165 { "AVX_NE_CONVERT",
166 "AVX2" },
167 { "FRED",
168 "LKGS" },
169 { "AVX512F",
170 "AVX2" },
171 { "AVX512CD",
172 "AVX512F" },
173 { "AVX512ER",
174 "AVX512F" },
175 { "AVX512PF",
176 "AVX512F" },
177 { "AVX512DQ",
178 "AVX512F" },
179 { "AVX512BW",
180 "AVX512F" },
181 { "AVX512VL",
182 "AVX512F" },
183 { "AVX512IFMA",
184 "AVX512F" },
185 { "AVX512VBMI",
186 "AVX512BW" },
187 { "AVX512_4FMAPS",
188 "AVX512F" },
189 { "AVX512_4VNNIW",
190 "AVX512F" },
191 { "AVX512_VPOPCNTDQ",
192 "AVX512F" },
193 { "AVX512_VBMI2",
194 "AVX512BW" },
195 { "AVX512_VNNI",
196 "AVX512F" },
197 { "AVX512_BITALG",
198 "AVX512BW" },
199 { "AVX512_VP2INTERSECT",
200 "AVX512F" },
201 { "AVX512_BF16",
202 "AVX512BW" },
203 { "AVX512_FP16",
204 "AVX512BW" },
205 { "IAMCU",
206 "586:nofpu" },
207 { "EPT",
208 "VMX" },
209 { "VMFUNC",
210 "VMX" },
211 { "MPX",
212 "XSAVE" },
213 { "SHA",
214 "SSE2" },
215 { "XSAVES",
216 "XSAVEC" },
217 { "XSAVEC",
218 "XSAVE" },
219 { "OSPKE",
220 "XSAVE" },
221 { "GFNI",
222 "SSE2" },
223 { "VAES",
224 "AVX2" },
225 { "VPCLMULQDQ",
226 "AVX2" },
227 { "SEV_ES",
228 "SVME" },
229 { "SNP",
230 "SEV_ES" },
231 { "RMPQUERY",
232 "SNP" },
233 { "TSX",
234 "RTM|HLE" },
235 { "TSXLDTRK",
236 "RTM" },
237 { "AMX_TILE",
238 "XSAVE" },
239 { "AMX_INT8",
240 "AMX_TILE" },
241 { "AMX_BF16",
242 "AMX_TILE" },
243 { "AMX_FP16",
244 "AMX_TILE" },
245 { "AMX_COMPLEX",
246 "AMX_TILE" },
247 { "KL",
248 "SSE2" },
249 { "WIDEKL",
250 "KL" },
253 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
254 static unsigned char isa_reverse_deps[Cpu64][Cpu64];
256 typedef struct bitfield
258 int position;
259 int value;
260 const char *name;
261 } bitfield;
263 #define BITFIELD(n) { Cpu##n, 0, #n }
265 static bitfield cpu_flags[] =
267 BITFIELD (186),
268 BITFIELD (286),
269 BITFIELD (386),
270 BITFIELD (486),
271 BITFIELD (586),
272 BITFIELD (686),
273 BITFIELD (CMOV),
274 BITFIELD (FXSR),
275 BITFIELD (Clflush),
276 BITFIELD (Nop),
277 BITFIELD (SYSCALL),
278 BITFIELD (8087),
279 BITFIELD (287),
280 BITFIELD (387),
281 BITFIELD (687),
282 BITFIELD (FISTTP),
283 BITFIELD (MMX),
284 BITFIELD (SSE),
285 BITFIELD (SSE2),
286 BITFIELD (SSE3),
287 BITFIELD (SSSE3),
288 BITFIELD (SSE4_1),
289 BITFIELD (SSE4_2),
290 BITFIELD (AVX),
291 BITFIELD (AVX2),
292 BITFIELD (AVX512F),
293 BITFIELD (AVX512CD),
294 BITFIELD (AVX512ER),
295 BITFIELD (AVX512PF),
296 BITFIELD (AVX512VL),
297 BITFIELD (AVX512DQ),
298 BITFIELD (AVX512BW),
299 BITFIELD (IAMCU),
300 BITFIELD (SSE4a),
301 BITFIELD (3dnow),
302 BITFIELD (3dnowA),
303 BITFIELD (PadLock),
304 BITFIELD (SVME),
305 BITFIELD (VMX),
306 BITFIELD (SMX),
307 BITFIELD (Xsave),
308 BITFIELD (Xsaveopt),
309 BITFIELD (AES),
310 BITFIELD (PCLMUL),
311 BITFIELD (FMA),
312 BITFIELD (FMA4),
313 BITFIELD (XOP),
314 BITFIELD (LWP),
315 BITFIELD (BMI),
316 BITFIELD (TBM),
317 BITFIELD (LM),
318 BITFIELD (Movbe),
319 BITFIELD (CX16),
320 BITFIELD (LAHF_SAHF),
321 BITFIELD (EPT),
322 BITFIELD (Rdtscp),
323 BITFIELD (FSGSBase),
324 BITFIELD (RdRnd),
325 BITFIELD (F16C),
326 BITFIELD (BMI2),
327 BITFIELD (LZCNT),
328 BITFIELD (POPCNT),
329 BITFIELD (MONITOR),
330 BITFIELD (HLE),
331 BITFIELD (RTM),
332 BITFIELD (INVPCID),
333 BITFIELD (VMFUNC),
334 BITFIELD (RDSEED),
335 BITFIELD (ADX),
336 BITFIELD (PRFCHW),
337 BITFIELD (SMAP),
338 BITFIELD (SHA),
339 BITFIELD (ClflushOpt),
340 BITFIELD (XSAVES),
341 BITFIELD (XSAVEC),
342 BITFIELD (PREFETCHWT1),
343 BITFIELD (SE1),
344 BITFIELD (CLWB),
345 BITFIELD (MPX),
346 BITFIELD (AVX512IFMA),
347 BITFIELD (AVX512VBMI),
348 BITFIELD (AVX512_4FMAPS),
349 BITFIELD (AVX512_4VNNIW),
350 BITFIELD (AVX512_VPOPCNTDQ),
351 BITFIELD (AVX512_VBMI2),
352 BITFIELD (AVX512_VNNI),
353 BITFIELD (AVX512_BITALG),
354 BITFIELD (AVX512_BF16),
355 BITFIELD (AVX512_VP2INTERSECT),
356 BITFIELD (TDX),
357 BITFIELD (AVX_VNNI),
358 BITFIELD (AVX512_FP16),
359 BITFIELD (PREFETCHI),
360 BITFIELD (AVX_IFMA),
361 BITFIELD (AVX_VNNI_INT8),
362 BITFIELD (CMPCCXADD),
363 BITFIELD (WRMSRNS),
364 BITFIELD (MSRLIST),
365 BITFIELD (AVX_NE_CONVERT),
366 BITFIELD (RAO_INT),
367 BITFIELD (FRED),
368 BITFIELD (LKGS),
369 BITFIELD (MWAITX),
370 BITFIELD (CLZERO),
371 BITFIELD (OSPKE),
372 BITFIELD (RDPID),
373 BITFIELD (PTWRITE),
374 BITFIELD (IBT),
375 BITFIELD (SHSTK),
376 BITFIELD (GFNI),
377 BITFIELD (VAES),
378 BITFIELD (VPCLMULQDQ),
379 BITFIELD (WBNOINVD),
380 BITFIELD (PCONFIG),
381 BITFIELD (WAITPKG),
382 BITFIELD (UINTR),
383 BITFIELD (CLDEMOTE),
384 BITFIELD (AMX_INT8),
385 BITFIELD (AMX_BF16),
386 BITFIELD (AMX_FP16),
387 BITFIELD (AMX_COMPLEX),
388 BITFIELD (AMX_TILE),
389 BITFIELD (MOVDIRI),
390 BITFIELD (MOVDIR64B),
391 BITFIELD (ENQCMD),
392 BITFIELD (SERIALIZE),
393 BITFIELD (RDPRU),
394 BITFIELD (MCOMMIT),
395 BITFIELD (SEV_ES),
396 BITFIELD (TSXLDTRK),
397 BITFIELD (KL),
398 BITFIELD (WideKL),
399 BITFIELD (HRESET),
400 BITFIELD (INVLPGB),
401 BITFIELD (TLBSYNC),
402 BITFIELD (SNP),
403 BITFIELD (RMPQUERY),
404 BITFIELD (64),
405 BITFIELD (No64),
406 #ifdef CpuUnused
407 BITFIELD (Unused),
408 #endif
411 #undef BITFIELD
412 #define BITFIELD(n) { n, 0, #n }
414 static bitfield opcode_modifiers[] =
416 BITFIELD (D),
417 BITFIELD (W),
418 BITFIELD (Load),
419 BITFIELD (Modrm),
420 BITFIELD (Jump),
421 BITFIELD (FloatMF),
422 BITFIELD (Size),
423 BITFIELD (CheckOperandSize),
424 BITFIELD (OperandConstraint),
425 BITFIELD (MnemonicSize),
426 BITFIELD (No_bSuf),
427 BITFIELD (No_wSuf),
428 BITFIELD (No_lSuf),
429 BITFIELD (No_sSuf),
430 BITFIELD (No_qSuf),
431 BITFIELD (FWait),
432 BITFIELD (IsString),
433 BITFIELD (RegMem),
434 BITFIELD (BNDPrefixOk),
435 BITFIELD (PrefixOk),
436 BITFIELD (IsPrefix),
437 BITFIELD (ImmExt),
438 BITFIELD (NoRex64),
439 BITFIELD (Vex),
440 BITFIELD (VexVVVV),
441 BITFIELD (VexW),
442 BITFIELD (OpcodePrefix),
443 BITFIELD (SIB),
444 BITFIELD (SSE2AVX),
445 BITFIELD (EVex),
446 BITFIELD (Masking),
447 BITFIELD (Broadcast),
448 BITFIELD (StaticRounding),
449 BITFIELD (SAE),
450 BITFIELD (Disp8MemShift),
451 BITFIELD (Optimize),
452 BITFIELD (ATTMnemonic),
453 BITFIELD (ATTSyntax),
454 BITFIELD (IntelSyntax),
455 BITFIELD (ISA64),
458 #define CLASS(n) #n, n
460 static const struct {
461 const char *name;
462 enum operand_class value;
463 } operand_classes[] = {
464 CLASS (Reg),
465 CLASS (SReg),
466 CLASS (RegCR),
467 CLASS (RegDR),
468 CLASS (RegTR),
469 CLASS (RegMMX),
470 CLASS (RegSIMD),
471 CLASS (RegMask),
472 CLASS (RegBND),
475 #undef CLASS
477 #define INSTANCE(n) #n, n
479 static const struct {
480 const char *name;
481 enum operand_instance value;
482 } operand_instances[] = {
483 INSTANCE (Accum),
484 INSTANCE (RegC),
485 INSTANCE (RegD),
486 INSTANCE (RegB),
489 #undef INSTANCE
491 static bitfield operand_types[] =
493 BITFIELD (Imm1),
494 BITFIELD (Imm8),
495 BITFIELD (Imm8S),
496 BITFIELD (Imm16),
497 BITFIELD (Imm32),
498 BITFIELD (Imm32S),
499 BITFIELD (Imm64),
500 BITFIELD (BaseIndex),
501 BITFIELD (Disp8),
502 BITFIELD (Disp16),
503 BITFIELD (Disp32),
504 BITFIELD (Disp64),
505 BITFIELD (Byte),
506 BITFIELD (Word),
507 BITFIELD (Dword),
508 BITFIELD (Fword),
509 BITFIELD (Qword),
510 BITFIELD (Tbyte),
511 BITFIELD (Xmmword),
512 BITFIELD (Ymmword),
513 BITFIELD (Zmmword),
514 BITFIELD (Tmmword),
515 BITFIELD (Unspecified),
516 #ifdef OTUnused
517 BITFIELD (OTUnused),
518 #endif
521 static const char *filename;
522 static i386_cpu_flags active_cpu_flags;
523 static int active_isstring;
525 struct template_arg {
526 const struct template_arg *next;
527 const char *val;
530 struct template_instance {
531 const struct template_instance *next;
532 const char *name;
533 const struct template_arg *args;
536 struct template_param {
537 const struct template_param *next;
538 const char *name;
541 struct template {
542 struct template *next;
543 const char *name;
544 const struct template_instance *instances;
545 const struct template_param *params;
548 static struct template *templates;
550 static int
551 compare (const void *x, const void *y)
553 const bitfield *xp = (const bitfield *) x;
554 const bitfield *yp = (const bitfield *) y;
555 return xp->position - yp->position;
558 static void
559 fail (const char *message, ...)
561 va_list args;
563 va_start (args, message);
564 fprintf (stderr, "%s: error: ", program_name);
565 vfprintf (stderr, message, args);
566 va_end (args);
567 xexit (1);
570 static void
571 process_copyright (FILE *fp)
573 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
574 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
576 This file is part of the GNU opcodes library.\n\
578 This library is free software; you can redistribute it and/or modify\n\
579 it under the terms of the GNU General Public License as published by\n\
580 the Free Software Foundation; either version 3, or (at your option)\n\
581 any later version.\n\
583 It is distributed in the hope that it will be useful, but WITHOUT\n\
584 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
585 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
586 License for more details.\n\
588 You should have received a copy of the GNU General Public License\n\
589 along with this program; if not, write to the Free Software\n\
590 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
591 MA 02110-1301, USA. */\n");
594 /* Remove leading white spaces. */
596 static char *
597 remove_leading_whitespaces (char *str)
599 while (ISSPACE (*str))
600 str++;
601 return str;
604 /* Remove trailing white spaces. */
606 static void
607 remove_trailing_whitespaces (char *str)
609 size_t last = strlen (str);
611 if (last == 0)
612 return;
616 last--;
617 if (ISSPACE (str [last]))
618 str[last] = '\0';
619 else
620 break;
622 while (last != 0);
625 /* Find next field separated by SEP and terminate it. Return a
626 pointer to the one after it. */
628 static char *
629 next_field (char *str, char sep, char **next, char *last)
631 char *p;
633 p = remove_leading_whitespaces (str);
634 for (str = p; *str != sep && *str != '\0'; str++);
636 *str = '\0';
637 remove_trailing_whitespaces (p);
639 *next = str + 1;
641 if (p >= last)
642 abort ();
644 return p;
647 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
649 static void
650 set_bitfield (char *f, bitfield *array, int value,
651 unsigned int size, int lineno)
653 unsigned int i;
655 /* Ignore empty fields; they may result from template expansions. */
656 if (*f == '\0')
657 return;
659 for (i = 0; i < size; i++)
660 if (strcasecmp (array[i].name, f) == 0)
662 array[i].value = value;
663 return;
666 if (value)
668 const char *v = strchr (f, '=');
670 if (v)
672 size_t n = v - f;
673 char *end;
675 for (i = 0; i < size; i++)
676 if (strncasecmp (array[i].name, f, n) == 0)
678 value = strtol (v + 1, &end, 0);
679 if (*end == '\0')
681 array[i].value = value;
682 return;
684 break;
689 if (lineno != -1)
690 fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f);
691 else
692 fail ("unknown bitfield: %s\n", f);
695 static void
696 add_isa_dependencies (bitfield *flags, const char *f, int value,
697 unsigned int reverse)
699 unsigned int i;
700 char *str = NULL;
701 const char *isa = f;
702 bool is_isa = false, is_avx = false;
704 /* Need to find base entry for references to auxiliary ones. */
705 if (strchr (f, ':'))
707 str = xstrdup (f);
708 *strchr (str, ':') = '\0';
709 isa = str;
711 for (i = 0; i < Cpu64; ++i)
712 if (strcasecmp (flags[i].name, isa) == 0)
714 flags[i].value = value;
715 if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
716 /* Don't record the feature itself here. */
717 && reverse != i
718 /* Don't record base architectures. */
719 && reverse > Cpu686)
720 isa_reverse_deps[i][reverse] = 1;
721 is_isa = true;
722 if (i == CpuAVX || i == CpuXOP)
723 is_avx = true;
724 break;
726 free (str);
728 /* Do not turn off dependencies. */
729 if (is_isa && !value)
730 return;
732 for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i)
733 if (strcasecmp (isa_dependencies[i].name, f) == 0)
735 char *deps = xstrdup (isa_dependencies[i].deps);
736 char *next = deps;
737 char *last = deps + strlen (deps);
739 for (; next && next < last; )
741 char *str = next_field (next, '|', &next, last);
743 /* No AVX/XOP -> SSE reverse dependencies. */
744 if (is_avx && strncmp (str, "SSE", 3) == 0)
745 add_isa_dependencies (flags, str, value, CpuMax);
746 else
747 add_isa_dependencies (flags, str, value, reverse);
749 free (deps);
751 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
752 if (reverse < ARRAY_SIZE (isa_reverse_deps[0]))
753 isa_reverse_deps[reverse][reverse] = 1;
755 return;
758 if (!is_isa)
759 fail ("unknown bitfield: %s\n", f);
762 static void
763 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
764 int macro, const char *comma, const char *indent)
766 unsigned int i;
768 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
770 fprintf (table, "%s{ { ", indent);
772 for (i = 0; i < size - 1; i++)
774 if (((i + 1) % 20) != 0)
775 fprintf (table, "%d, ", flags[i].value);
776 else
777 fprintf (table, "%d,", flags[i].value);
778 if (((i + 1) % 20) == 0)
780 /* We need \\ for macro. */
781 if (macro)
782 fprintf (table, " \\\n %s", indent);
783 else
784 fprintf (table, "\n %s", indent);
786 if (flags[i].value)
787 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
790 fprintf (table, "%d } }%s\n", flags[i].value, comma);
793 static void
794 process_i386_cpu_flag (FILE *table, char *flag,
795 const char *name,
796 const char *comma, const char *indent,
797 int lineno, unsigned int reverse)
799 char *str, *next = flag, *last;
800 unsigned int i;
801 int value = 1;
802 bool is_isa = false;
803 bitfield flags [ARRAY_SIZE (cpu_flags)];
805 /* Copy the default cpu flags. */
806 memcpy (flags, cpu_flags, sizeof (cpu_flags));
808 if (flag == NULL)
810 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
811 flags[i].value = isa_reverse_deps[reverse][i];
812 goto output;
815 if (flag[0] == '~')
817 last = flag + strlen (flag);
819 if (flag[1] == '(')
821 last -= 1;
822 next = flag + 2;
823 if (*last != ')')
824 fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
825 lineno, flag);
826 *last = '\0';
828 else
829 next = flag + 1;
831 /* First we turn on everything except for cpu64, cpuno64, and - if
832 present - the padding field. */
833 for (i = 0; i < ARRAY_SIZE (flags); i++)
834 if (flags[i].position < Cpu64)
835 flags[i].value = 1;
837 /* Turn off selective bits. */
838 value = 0;
841 if (name != NULL && value != 0)
843 for (i = 0; i < ARRAY_SIZE (flags); i++)
844 if (strcasecmp (flags[i].name, name) == 0)
846 add_isa_dependencies (flags, name, 1, reverse);
847 is_isa = true;
848 break;
852 if (strcmp (flag, "0"))
854 if (is_isa)
855 return;
857 /* Turn on/off selective bits. */
858 last = flag + strlen (flag);
859 for (; next && next < last; )
861 str = next_field (next, '|', &next, last);
862 if (name == NULL)
863 set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
864 else
865 add_isa_dependencies (flags, str, value, reverse);
869 output:
870 if (name != NULL)
872 size_t len = strlen (name);
873 char *upper = xmalloc (len + 1);
875 for (i = 0; i < len; ++i)
877 /* Don't emit #define-s for auxiliary entries. */
878 if (name[i] == ':')
879 return;
880 upper[i] = TOUPPER (name[i]);
882 upper[i] = '\0';
883 fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n",
884 flag != NULL ? "": "ANY_", upper);
885 free (upper);
888 output_cpu_flags (table, flags, ARRAY_SIZE (flags), name != NULL,
889 comma, indent);
892 static void
893 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
895 unsigned int i;
897 fprintf (table, " { ");
899 for (i = 0; i < size - 1; i++)
901 if (((i + 1) % 20) != 0)
902 fprintf (table, "%d, ", modifier[i].value);
903 else
904 fprintf (table, "%d,", modifier[i].value);
905 if (((i + 1) % 20) == 0)
906 fprintf (table, "\n ");
909 fprintf (table, "%d },\n", modifier[i].value);
912 /* Returns LOG2 of element size. */
913 static int
914 get_element_size (char **opnd, int lineno)
916 char *str, *next, *last, *op;
917 const char *full = opnd[0];
918 int elem_size = INT_MAX;
920 /* Find the memory operand. */
921 while (full != NULL && strstr(full, "BaseIndex") == NULL)
922 full = *++opnd;
923 if (full == NULL)
924 fail ("%s: %d: no memory operand\n", filename, lineno);
926 op = xstrdup (full);
927 last = op + strlen (op);
928 for (next = op; next && next < last; )
930 str = next_field (next, '|', &next, last);
931 if (str)
933 if (strcasecmp(str, "Byte") == 0)
935 /* The smallest element size, no need to check
936 further. */
937 elem_size = 0;
938 break;
940 else if (strcasecmp(str, "Word") == 0)
942 if (elem_size > 1)
943 elem_size = 1;
945 else if (strcasecmp(str, "Dword") == 0)
947 if (elem_size > 2)
948 elem_size = 2;
950 else if (strcasecmp(str, "Qword") == 0)
952 if (elem_size > 3)
953 elem_size = 3;
957 free (op);
959 if (elem_size == INT_MAX)
960 fail ("%s: %d: unknown element size: %s\n", filename, lineno, full);
962 return elem_size;
965 static void
966 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
967 unsigned int prefix, const char *extension_opcode,
968 char **opnd, int lineno)
970 char *str, *next, *last;
971 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
972 static const char *const spaces[] = {
973 #define SPACE(n) [SPACE_##n] = #n
974 SPACE(BASE),
975 SPACE(0F),
976 SPACE(0F38),
977 SPACE(0F3A),
978 SPACE(EVEXMAP5),
979 SPACE(EVEXMAP6),
980 SPACE(XOP08),
981 SPACE(XOP09),
982 SPACE(XOP0A),
983 #undef SPACE
986 active_isstring = 0;
988 /* Copy the default opcode modifier. */
989 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
991 if (strcmp (mod, "0"))
993 unsigned int have_w = 0, bwlq_suf = 0xf;
995 last = mod + strlen (mod);
996 for (next = mod; next && next < last; )
998 str = next_field (next, '|', &next, last);
999 if (str)
1001 int val = 1;
1003 if (strncmp(str, "OpcodeSpace", 11) == 0)
1005 char *end;
1007 if (str[11] != '=')
1008 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1009 filename, lineno);
1011 val = strtol (str + 12, &end, 0);
1012 if (*end)
1013 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1014 filename, lineno, end);
1016 if (space)
1018 if (val != space)
1019 fail ("%s:%d: Conflicting opcode space specifications\n",
1020 filename, lineno);
1021 fprintf (stderr,
1022 "%s:%d: Warning: redundant opcode space specification\n",
1023 filename, lineno);
1026 space = val;
1027 continue;
1030 if (strcasecmp(str, "Broadcast") == 0)
1031 val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1032 else if (strcasecmp(str, "Disp8MemShift") == 0)
1033 val = get_element_size (opnd, lineno);
1035 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1036 lineno);
1037 if (strcasecmp(str, "IsString") == 0)
1038 active_isstring = 1;
1040 if (strcasecmp(str, "W") == 0)
1041 have_w = 1;
1043 if (strcasecmp(str, "No_bSuf") == 0)
1044 bwlq_suf &= ~1;
1045 if (strcasecmp(str, "No_wSuf") == 0)
1046 bwlq_suf &= ~2;
1047 if (strcasecmp(str, "No_lSuf") == 0)
1048 bwlq_suf &= ~4;
1049 if (strcasecmp(str, "No_qSuf") == 0)
1050 bwlq_suf &= ~8;
1054 if (prefix)
1056 if (!modifiers[OpcodePrefix].value)
1057 modifiers[OpcodePrefix].value = prefix;
1058 else if (modifiers[OpcodePrefix].value != prefix)
1059 fail ("%s:%d: Conflicting prefix specifications\n",
1060 filename, lineno);
1061 else
1062 fprintf (stderr,
1063 "%s:%d: Warning: redundant prefix specification\n",
1064 filename, lineno);
1067 if (have_w && !bwlq_suf)
1068 fail ("%s: %d: stray W modifier\n", filename, lineno);
1069 if (have_w && !(bwlq_suf & 1))
1070 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1071 filename, lineno);
1072 if (have_w && !(bwlq_suf & ~1))
1073 fprintf (stderr,
1074 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1075 filename, lineno);
1078 if (space >= ARRAY_SIZE (spaces) || !spaces[space])
1079 fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
1081 fprintf (table, " SPACE_%s, %s,\n",
1082 spaces[space], extension_opcode ? extension_opcode : "None");
1084 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1087 enum stage {
1088 stage_macros,
1089 stage_opcodes,
1090 stage_registers,
1093 static void
1094 output_operand_type (FILE *table, enum operand_class class,
1095 enum operand_instance instance,
1096 const bitfield *types, unsigned int size,
1097 enum stage stage, const char *indent)
1099 unsigned int i;
1101 fprintf (table, "{ { %d, %d, ", class, instance);
1103 for (i = 0; i < size - 1; i++)
1105 if (((i + 3) % 20) != 0)
1106 fprintf (table, "%d, ", types[i].value);
1107 else
1108 fprintf (table, "%d,", types[i].value);
1109 if (((i + 3) % 20) == 0)
1111 /* We need \\ for macro. */
1112 if (stage == stage_macros)
1113 fprintf (table, " \\\n%s", indent);
1114 else
1115 fprintf (table, "\n%s", indent);
1119 fprintf (table, "%d } }", types[i].value);
1122 static void
1123 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1124 const char *indent, int lineno)
1126 char *str, *next, *last;
1127 enum operand_class class = ClassNone;
1128 enum operand_instance instance = InstanceNone;
1129 bitfield types [ARRAY_SIZE (operand_types)];
1131 /* Copy the default operand type. */
1132 memcpy (types, operand_types, sizeof (types));
1134 if (strcmp (op, "0"))
1136 int baseindex = 0;
1138 last = op + strlen (op);
1139 for (next = op; next && next < last; )
1141 str = next_field (next, '|', &next, last);
1142 if (str)
1144 unsigned int i;
1146 if (!strncmp(str, "Class=", 6))
1148 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1149 if (!strcmp(str + 6, operand_classes[i].name))
1151 class = operand_classes[i].value;
1152 str = NULL;
1153 break;
1157 if (str && !strncmp(str, "Instance=", 9))
1159 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1160 if (!strcmp(str + 9, operand_instances[i].name))
1162 instance = operand_instances[i].value;
1163 str = NULL;
1164 break;
1168 if (str)
1170 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1171 if (strcasecmp(str, "BaseIndex") == 0)
1172 baseindex = 1;
1176 if (stage == stage_opcodes && baseindex && !active_isstring)
1178 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1179 if (!active_cpu_flags.bitfield.cpu64
1180 && !active_cpu_flags.bitfield.cpumpx)
1181 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1182 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1185 output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1186 stage, indent);
1189 static char *mkident (const char *mnem)
1191 char *ident = xstrdup (mnem), *p = ident;
1195 if (!ISALNUM (*p))
1196 *p = '_';
1198 while (*++p);
1200 return ident;
1203 static void
1204 output_i386_opcode (FILE *table, const char *name, char *str,
1205 char *last, int lineno)
1207 unsigned int i, length, prefix = 0, space = 0;
1208 char *base_opcode, *extension_opcode, *end, *ident;
1209 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1210 unsigned long long opcode;
1212 /* Find base_opcode. */
1213 base_opcode = next_field (str, ',', &str, last);
1215 /* Find extension_opcode, if any. */
1216 extension_opcode = strchr (base_opcode, '/');
1217 if (extension_opcode)
1218 *extension_opcode++ = '\0';
1220 /* Find cpu_flags. */
1221 cpu_flags = next_field (str, ',', &str, last);
1223 /* Find opcode_modifier. */
1224 opcode_modifier = next_field (str, ',', &str, last);
1226 /* Remove the first {. */
1227 str = remove_leading_whitespaces (str);
1228 if (*str != '{')
1229 abort ();
1230 str = remove_leading_whitespaces (str + 1);
1231 remove_trailing_whitespaces (str);
1233 /* Remove } and trailing white space. */
1234 i = strlen (str);
1235 if (!i || str[i - 1] != '}')
1236 abort ();
1237 str[--i] = '\0';
1238 remove_trailing_whitespaces (str);
1240 if (!*str)
1241 operand_types [i = 0] = NULL;
1242 else
1244 last = str + strlen (str);
1246 /* Find operand_types. */
1247 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1249 if (str >= last)
1251 operand_types [i] = NULL;
1252 break;
1255 operand_types [i] = next_field (str, ',', &str, last);
1259 opcode = strtoull (base_opcode, &end, 0);
1261 /* Determine opcode length. */
1262 for (length = 1; length < 8; ++length)
1263 if (!(opcode >> (8 * length)))
1264 break;
1266 /* Transform prefixes encoded in the opcode into opcode modifier
1267 representation. */
1268 if (length > 1)
1270 switch (opcode >> (8 * length - 8))
1272 case 0x66: prefix = PREFIX_0X66; break;
1273 case 0xF3: prefix = PREFIX_0XF3; break;
1274 case 0xF2: prefix = PREFIX_0XF2; break;
1277 if (prefix)
1278 opcode &= (1ULL << (8 * --length)) - 1;
1281 /* Transform opcode space encoded in the opcode into opcode modifier
1282 representation. */
1283 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1285 switch ((opcode >> (8 * length - 16)) & 0xff)
1287 default: space = SPACE_0F; break;
1288 case 0x38: space = SPACE_0F38; break;
1289 case 0x3A: space = SPACE_0F3A; break;
1292 if (space != SPACE_0F && --length == 1)
1293 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1294 filename, lineno, name);
1295 opcode &= (1ULL << (8 * --length)) - 1;
1298 if (length > 2)
1299 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1300 filename, lineno, name, 2 * length, opcode);
1302 ident = mkident (name);
1303 fprintf (table, " { MN_%s, 0x%0*llx%s, %u,",
1304 ident, 2 * (int)length, opcode, end, i);
1305 free (ident);
1307 process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1308 extension_opcode, operand_types, lineno);
1310 process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax);
1312 fprintf (table, " { ");
1314 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1316 if (!operand_types[i])
1318 if (i == 0)
1319 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1320 lineno);
1321 break;
1324 if (i != 0)
1325 fprintf (table, ",\n ");
1327 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1328 "\t ", lineno);
1330 fprintf (table, " } },\n");
1333 struct opcode_hash_entry
1335 const char *name;
1336 struct opcode_entry
1338 struct opcode_entry *next;
1339 char *opcode;
1340 int lineno;
1341 } entry;
1344 /* Calculate the hash value of an opcode hash entry P. */
1346 static hashval_t
1347 opcode_hash_hash (const void *p)
1349 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1350 return htab_hash_string (entry->name);
1353 /* Compare a string Q against an opcode hash entry P. */
1355 static int
1356 opcode_hash_eq (const void *p, const void *q)
1358 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1359 const char *name = (const char *) q;
1360 return strcmp (name, entry->name) == 0;
1363 static void
1364 parse_template (char *buf, int lineno)
1366 char sep, *end, *name;
1367 struct template *tmpl;
1368 struct template_instance *last_inst = NULL;
1370 buf = remove_leading_whitespaces (buf + 1);
1371 end = strchr (buf, ':');
1372 if (end == NULL)
1374 struct template *prev = NULL;
1376 end = strchr (buf, '>');
1377 if (end == NULL)
1378 fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1379 if (*remove_leading_whitespaces (end + 1))
1380 fail ("%s: %d: malformed template purge\n", filename, lineno);
1381 *end = '\0';
1382 remove_trailing_whitespaces (buf);
1383 /* Don't bother freeing the various structures. */
1384 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1385 if (!strcmp (buf, tmpl->name))
1386 break;
1387 if (tmpl == NULL)
1388 fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1389 if (prev)
1390 prev->next = tmpl->next;
1391 else
1392 templates = tmpl->next;
1393 return;
1395 *end++ = '\0';
1396 remove_trailing_whitespaces (buf);
1398 if (*buf == '\0')
1399 fail ("%s: %d: missing template identifier\n", filename, lineno);
1400 tmpl = xmalloc (sizeof (*tmpl));
1401 tmpl->name = xstrdup (buf);
1403 tmpl->params = NULL;
1404 do {
1405 struct template_param *param;
1407 buf = remove_leading_whitespaces (end);
1408 end = strpbrk (buf, ":,");
1409 if (end == NULL)
1410 fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1412 sep = *end;
1413 *end++ = '\0';
1414 remove_trailing_whitespaces (buf);
1416 param = xmalloc (sizeof (*param));
1417 param->name = xstrdup (buf);
1418 param->next = tmpl->params;
1419 tmpl->params = param;
1420 } while (sep == ':');
1422 tmpl->instances = NULL;
1423 do {
1424 struct template_instance *inst;
1425 char *cur, *next;
1426 const struct template_param *param;
1428 buf = remove_leading_whitespaces (end);
1429 end = strpbrk (buf, ",>");
1430 if (end == NULL)
1431 fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1433 sep = *end;
1434 *end++ = '\0';
1436 inst = xmalloc (sizeof (*inst));
1437 inst->next = NULL;
1438 inst->args = NULL;
1440 cur = next_field (buf, ':', &next, end);
1441 inst->name = *cur != '$' ? xstrdup (cur) : "";
1443 for (param = tmpl->params; param; param = param->next)
1445 struct template_arg *arg = xmalloc (sizeof (*arg));
1447 cur = next_field (next, ':', &next, end);
1448 if (next > end)
1449 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1450 arg->val = xstrdup (cur);
1451 arg->next = inst->args;
1452 inst->args = arg;
1455 if (tmpl->instances)
1456 last_inst->next = inst;
1457 else
1458 tmpl->instances = inst;
1459 last_inst = inst;
1460 } while (sep == ',');
1462 buf = remove_leading_whitespaces (end);
1463 if (*buf)
1464 fprintf(stderr, "%s: %d: excess characters '%s'\n",
1465 filename, lineno, buf);
1467 tmpl->next = templates;
1468 templates = tmpl;
1471 static unsigned int
1472 expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1473 struct opcode_hash_entry ***opcode_array_p, int lineno)
1475 static unsigned int idx, opcode_array_size;
1476 struct opcode_hash_entry **opcode_array = *opcode_array_p;
1477 struct opcode_hash_entry **hash_slot;
1478 struct opcode_entry *entry;
1479 char *ptr1 = strchr(name, '<'), *ptr2;
1481 if (ptr1 == NULL)
1483 /* Get the slot in hash table. */
1484 hash_slot = (struct opcode_hash_entry **)
1485 htab_find_slot_with_hash (opcode_hash_table, name,
1486 htab_hash_string (name),
1487 INSERT);
1489 if (*hash_slot == NULL)
1491 /* It is the new one. Put it on opcode array. */
1492 if (idx >= opcode_array_size)
1494 /* Grow the opcode array when needed. */
1495 opcode_array_size += 1024;
1496 opcode_array = (struct opcode_hash_entry **)
1497 xrealloc (opcode_array,
1498 sizeof (*opcode_array) * opcode_array_size);
1499 *opcode_array_p = opcode_array;
1502 opcode_array[idx] = (struct opcode_hash_entry *)
1503 xmalloc (sizeof (struct opcode_hash_entry));
1504 opcode_array[idx]->name = xstrdup (name);
1505 *hash_slot = opcode_array[idx];
1506 entry = &opcode_array[idx]->entry;
1507 idx++;
1509 else
1511 /* Append it to the existing one. */
1512 struct opcode_entry **entryp = &(*hash_slot)->entry.next;
1514 while (*entryp != NULL)
1515 entryp = &(*entryp)->next;
1516 entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry));
1517 *entryp = entry;
1520 entry->next = NULL;
1521 entry->opcode = xstrdup (str);
1522 entry->lineno = lineno;
1524 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1525 fail ("%s: %d: missing '>'\n", filename, lineno);
1526 else
1528 const struct template *tmpl;
1529 const struct template_instance *inst;
1531 *ptr1 = '\0';
1532 ptr1 = remove_leading_whitespaces (ptr1 + 1);
1533 remove_trailing_whitespaces (ptr1);
1535 *ptr2++ = '\0';
1537 for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1538 if (!strcmp(ptr1, tmpl->name))
1539 break;
1540 if (!tmpl)
1541 fail ("reference to unknown template '%s'\n", ptr1);
1543 for (inst = tmpl->instances; inst; inst = inst->next)
1545 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1546 char *str2 = xmalloc(2 * strlen(str));
1547 const char *src;
1549 strcpy (name2, name);
1550 strcat (name2, inst->name);
1551 strcat (name2, ptr2);
1553 for (ptr1 = str2, src = str; *src; )
1555 const char *ident = tmpl->name, *end;
1556 const struct template_param *param;
1557 const struct template_arg *arg;
1559 if ((*ptr1 = *src++) != '<')
1561 ++ptr1;
1562 continue;
1564 while (ISSPACE(*src))
1565 ++src;
1566 while (*ident && *src == *ident)
1567 ++src, ++ident;
1568 while (ISSPACE(*src))
1569 ++src;
1570 if (*src != ':' || *ident != '\0')
1572 memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1573 ptr1 += ident - tmpl->name;
1574 continue;
1576 while (ISSPACE(*++src))
1579 end = src;
1580 while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1581 ++end;
1583 for (param = tmpl->params, arg = inst->args; param;
1584 param = param->next, arg = arg->next)
1586 if (end - src == strlen (param->name)
1587 && !memcmp (src, param->name, end - src))
1589 src = end;
1590 break;
1594 if (param == NULL)
1595 fail ("template '%s' has no parameter '%.*s'\n",
1596 tmpl->name, (int)(end - src), src);
1598 while (ISSPACE(*src))
1599 ++src;
1600 if (*src != '>')
1601 fail ("%s: %d: missing '>'\n", filename, lineno);
1603 memcpy(ptr1, arg->val, strlen(arg->val));
1604 ptr1 += strlen(arg->val);
1605 ++src;
1608 *ptr1 = '\0';
1610 expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1611 lineno);
1613 free (str2);
1614 free (name2);
1618 return idx;
1621 static int mnemonic_cmp(const void *p1, const void *p2)
1623 const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2;
1624 const char *s1 = (*e1)->name, *s2 = (*e2)->name;
1625 unsigned int i;
1626 size_t l1 = strlen (s1), l2 = strlen (s2);
1628 for (i = 1; i <= l1 && i <= l2; ++i)
1630 if (s1[l1 - i] != s2[l2 - i])
1631 return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i];
1634 return (int)(l1 - l2);
1637 static void
1638 process_i386_opcodes (FILE *table)
1640 FILE *fp;
1641 char buf[2048];
1642 unsigned int i, j, nr, offs;
1643 size_t l;
1644 char *str, *p, *last;
1645 htab_t opcode_hash_table;
1646 struct opcode_hash_entry **opcode_array = NULL;
1647 int lineno = 0, marker = 0;
1649 filename = "i386-opc.tbl";
1650 fp = stdin;
1652 i = 0;
1653 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1654 opcode_hash_eq, NULL,
1655 xcalloc, free);
1657 fprintf (table, "\n#include \"i386-mnem.h\"\n");
1658 fprintf (table, "\n/* i386 opcode table. */\n\n");
1659 fprintf (table, "static const insn_template i386_optab[] =\n{\n");
1661 /* Put everything on opcode array. */
1662 while (!feof (fp))
1664 char *name;
1666 if (fgets (buf, sizeof (buf), fp) == NULL)
1667 break;
1669 p = remove_leading_whitespaces (buf);
1671 for ( ; ; )
1673 lineno++;
1675 /* Skip comments. */
1676 str = strstr (p, "//");
1677 if (str != NULL)
1679 str[0] = '\0';
1680 remove_trailing_whitespaces (p);
1681 break;
1684 /* Look for line continuation character. */
1685 remove_trailing_whitespaces (p);
1686 j = strlen (buf);
1687 if (!j || buf[j - 1] != '+')
1688 break;
1689 if (j >= sizeof (buf) - 1)
1690 fail ("%s: %d: (continued) line too long\n", filename, lineno);
1692 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1694 fprintf (stderr, "%s: Line continuation on last line?\n",
1695 filename);
1696 break;
1700 switch (p[0])
1702 case '#':
1703 if (!strcmp("### MARKER ###", buf))
1704 marker = 1;
1705 else
1707 /* Since we ignore all included files (we only care about their
1708 #define-s here), we don't need to monitor filenames. The final
1709 line number directive is going to refer to the main source file
1710 again. */
1711 char *end;
1712 unsigned long ln;
1714 p = remove_leading_whitespaces (p + 1);
1715 if (!strncmp(p, "line", 4))
1716 p += 4;
1717 ln = strtoul (p, &end, 10);
1718 if (ln > 1 && ln < INT_MAX
1719 && *remove_leading_whitespaces (end) == '"')
1720 lineno = ln - 1;
1722 /* Ignore comments. */
1723 case '\0':
1724 continue;
1725 break;
1726 case '<':
1727 parse_template (p, lineno);
1728 continue;
1729 default:
1730 if (!marker)
1731 continue;
1732 break;
1735 last = p + strlen (p);
1737 /* Find name. */
1738 name = next_field (p, ',', &str, last);
1740 i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1741 lineno);
1744 /* Process opcode array. */
1745 for (j = 0; j < i; j++)
1747 const char *name = opcode_array[j]->name;
1748 struct opcode_entry *next;
1750 for (next = &opcode_array[j]->entry; next; next = next->next)
1752 str = next->opcode;
1753 lineno = next->lineno;
1754 last = str + strlen (str);
1755 output_i386_opcode (table, name, str, last, lineno);
1759 fclose (fp);
1761 fprintf (table, "};\n");
1763 /* Generate opcode sets array. */
1764 fprintf (table, "\n/* i386 opcode sets table. */\n\n");
1765 fprintf (table, "static const insn_template *const i386_op_sets[] =\n{\n");
1766 fprintf (table, " i386_optab,\n");
1768 for (nr = j = 0; j < i; j++)
1770 struct opcode_entry *next = &opcode_array[j]->entry;
1774 ++nr;
1775 next = next->next;
1777 while (next);
1778 fprintf (table, " i386_optab + %u,\n", nr);
1781 fprintf (table, "};\n");
1783 /* Emit mnemonics and associated #define-s. */
1784 qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
1786 fp = fopen ("i386-mnem.h", "w");
1787 if (fp == NULL)
1788 fail ("can't create i386-mnem.h, errno = %s\n",
1789 xstrerror (errno));
1791 process_copyright (fp);
1793 fprintf (table, "\n/* i386 mnemonics table. */\n\n");
1794 fprintf (table, "const char i386_mnemonics[] =\n");
1795 fprintf (fp, "\nextern const char i386_mnemonics[];\n\n");
1797 str = NULL;
1798 for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++)
1800 const char *name = opcode_array[j]->name;
1801 const char *next = NULL;
1802 size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0;
1804 if (str == NULL)
1805 str = mkident (name);
1806 if (l < l1 && !strcmp(name, next + l1 - l))
1808 fprintf (fp, "#define MN_%s ", str);
1809 free (str);
1810 str = mkident (next);
1811 fprintf (fp, "(MN_%s + %u)\n", str, l1 - l);
1813 else
1815 fprintf (table, " \"\\0\"\"%s\"\n", name);
1816 fprintf (fp, "#define MN_%s %#x\n", str, offs + 1);
1817 offs += strlen (name) + 1;
1818 free (str);
1819 str = NULL;
1821 l = l1;
1824 fprintf (table, " \"\\0\"\".insn\"\n");
1825 fprintf (fp, "#define MN__insn %#x\n", offs + 1);
1827 fprintf (table, ";\n");
1829 fclose (fp);
1832 static void
1833 process_i386_registers (FILE *table)
1835 FILE *fp;
1836 char buf[2048];
1837 char *str, *p, *last;
1838 char *reg_name, *reg_type, *reg_flags, *reg_num;
1839 char *dw2_32_num, *dw2_64_num;
1840 int lineno = 0;
1842 filename = "i386-reg.tbl";
1843 fp = fopen (filename, "r");
1844 if (fp == NULL)
1845 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1846 xstrerror (errno));
1848 fprintf (table, "\n/* i386 register table. */\n\n");
1849 fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
1851 while (!feof (fp))
1853 if (fgets (buf, sizeof (buf), fp) == NULL)
1854 break;
1856 lineno++;
1858 p = remove_leading_whitespaces (buf);
1860 /* Skip comments. */
1861 str = strstr (p, "//");
1862 if (str != NULL)
1863 str[0] = '\0';
1865 /* Remove trailing white spaces. */
1866 remove_trailing_whitespaces (p);
1868 switch (p[0])
1870 case '#':
1871 fprintf (table, "%s\n", p);
1872 case '\0':
1873 continue;
1874 break;
1875 default:
1876 break;
1879 last = p + strlen (p);
1881 /* Find reg_name. */
1882 reg_name = next_field (p, ',', &str, last);
1884 /* Find reg_type. */
1885 reg_type = next_field (str, ',', &str, last);
1887 /* Find reg_flags. */
1888 reg_flags = next_field (str, ',', &str, last);
1890 /* Find reg_num. */
1891 reg_num = next_field (str, ',', &str, last);
1893 fprintf (table, " { \"%s\",\n ", reg_name);
1895 process_i386_operand_type (table, reg_type, stage_registers, "\t",
1896 lineno);
1898 /* Find 32-bit Dwarf2 register number. */
1899 dw2_32_num = next_field (str, ',', &str, last);
1901 /* Find 64-bit Dwarf2 register number. */
1902 dw2_64_num = next_field (str, ',', &str, last);
1904 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1905 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1908 fclose (fp);
1910 fprintf (table, "};\n");
1912 fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1915 static void
1916 process_i386_initializers (void)
1918 unsigned int i;
1919 FILE *fp = fopen ("i386-init.h", "w");
1921 if (fp == NULL)
1922 fail ("can't create i386-init.h, errno = %s\n",
1923 xstrerror (errno));
1925 process_copyright (fp);
1927 for (i = 0; i < Cpu64; i++)
1928 process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i);
1930 for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++)
1932 char *deps = xstrdup (isa_dependencies[i].deps);
1934 process_i386_cpu_flag (fp, deps, isa_dependencies[i].name,
1935 "", " ", -1, CpuMax);
1936 free (deps);
1939 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1940 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1941 one to 387. We want the reverse to be true though: Disabling 8087 also
1942 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1943 memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387],
1944 sizeof (isa_reverse_deps[0]));
1945 isa_reverse_deps[Cpu287][Cpu387] = 1;
1946 memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287],
1947 sizeof (isa_reverse_deps[0]));
1948 isa_reverse_deps[Cpu8087][Cpu287] = 1;
1950 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1951 lead to disabling of anything else. */
1952 memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0]));
1954 for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++)
1956 size_t len;
1957 char *upper;
1959 if (memchr(isa_reverse_deps[i], 1,
1960 ARRAY_SIZE (isa_reverse_deps[0])) == NULL)
1961 continue;
1963 isa_reverse_deps[i][i] = 1;
1964 process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i);
1967 fprintf (fp, "\n");
1969 fclose (fp);
1972 /* Program options. */
1973 #define OPTION_SRCDIR 200
1975 struct option long_options[] =
1977 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
1978 {"debug", no_argument, NULL, 'd'},
1979 {"version", no_argument, NULL, 'V'},
1980 {"help", no_argument, NULL, 'h'},
1981 {0, no_argument, NULL, 0}
1984 static void
1985 print_version (void)
1987 printf ("%s: version 1.0\n", program_name);
1988 xexit (0);
1991 static void
1992 usage (FILE * stream, int status)
1994 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1995 program_name);
1996 xexit (status);
2000 main (int argc, char **argv)
2002 extern int chdir (char *);
2003 char *srcdir = NULL;
2004 int c;
2005 unsigned int i, cpumax;
2006 FILE *table;
2008 program_name = *argv;
2009 xmalloc_set_program_name (program_name);
2011 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2012 switch (c)
2014 case OPTION_SRCDIR:
2015 srcdir = optarg;
2016 break;
2017 case 'V':
2018 case 'v':
2019 print_version ();
2020 break;
2021 case 'd':
2022 debug = 1;
2023 break;
2024 case 'h':
2025 case '?':
2026 usage (stderr, 0);
2027 default:
2028 case 0:
2029 break;
2032 if (optind != argc)
2033 usage (stdout, 1);
2035 if (srcdir != NULL)
2036 if (chdir (srcdir) != 0)
2037 fail ("unable to change directory to \"%s\", errno = %s\n",
2038 srcdir, xstrerror (errno));
2040 /* cpu_flags isn't sorted by position. */
2041 cpumax = 0;
2042 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2043 if (cpu_flags[i].position > cpumax)
2044 cpumax = cpu_flags[i].position;
2046 /* Check the unused bitfield in i386_cpu_flags. */
2047 #ifdef CpuUnused
2048 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2050 if ((cpumax - 1) != CpuMax)
2051 fail ("CpuMax != %d!\n", cpumax);
2052 #else
2053 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2055 if (cpumax != CpuMax)
2056 fail ("CpuMax != %d!\n", cpumax);
2058 c = CpuNumOfBits - CpuMax - 1;
2059 if (c)
2060 fail ("%d unused bits in i386_cpu_flags.\n", c);
2061 #endif
2063 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2065 /* Check the unused bitfield in i386_operand_type. */
2066 #ifdef OTUnused
2067 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2068 == OTNum + 1);
2069 #else
2070 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2071 == OTNum);
2073 c = OTNumOfBits - OTNum;
2074 if (c)
2075 fail ("%d unused bits in i386_operand_type.\n", c);
2076 #endif
2078 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2079 compare);
2081 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2082 sizeof (opcode_modifiers [0]), compare);
2084 qsort (operand_types, ARRAY_SIZE (operand_types),
2085 sizeof (operand_types [0]), compare);
2087 table = fopen ("i386-tbl.h", "w");
2088 if (table == NULL)
2089 fail ("can't create i386-tbl.h, errno = %s\n",
2090 xstrerror (errno));
2092 process_copyright (table);
2094 process_i386_opcodes (table);
2095 process_i386_registers (table);
2096 process_i386_initializers ();
2098 fclose (table);
2100 exit (0);