Improve objdump's handling of compressed sections.
[binutils-gdb.git] / opcodes / i386-gen.c
blob53cb700d0aa1b270d0f81c6d7b264c5741b976d1
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" },
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|PCLMULQDQ|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|PCLMULQDQ|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|PCLMULQDQ|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 { "PCLMULQDQ",
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_VNNI_INT16",
166 "AVX2" },
167 { "AVX_NE_CONVERT",
168 "AVX2" },
169 { "CX16",
170 "64" },
171 { "LKGS",
172 "64" },
173 { "FRED",
174 "LKGS" },
175 { "AVX512F",
176 "AVX2" },
177 { "AVX512CD",
178 "AVX512F" },
179 { "AVX512ER",
180 "AVX512F" },
181 { "AVX512PF",
182 "AVX512F" },
183 { "AVX512DQ",
184 "AVX512F" },
185 { "AVX512BW",
186 "AVX512F" },
187 { "AVX512VL",
188 "AVX512F" },
189 { "AVX512IFMA",
190 "AVX512F" },
191 { "AVX512VBMI",
192 "AVX512BW" },
193 { "AVX512_4FMAPS",
194 "AVX512F" },
195 { "AVX512_4VNNIW",
196 "AVX512F" },
197 { "AVX512_VPOPCNTDQ",
198 "AVX512F" },
199 { "AVX512_VBMI2",
200 "AVX512BW" },
201 { "AVX512_VNNI",
202 "AVX512F" },
203 { "AVX512_BITALG",
204 "AVX512BW" },
205 { "AVX512_VP2INTERSECT",
206 "AVX512F" },
207 { "AVX512_BF16",
208 "AVX512BW" },
209 { "AVX512_FP16",
210 "AVX512BW" },
211 { "IAMCU",
212 "586:nofpu" },
213 { "EPT",
214 "VMX" },
215 { "VMFUNC",
216 "VMX" },
217 { "MPX",
218 "XSAVE" },
219 { "SHA",
220 "SSE2" },
221 { "SHA512",
222 "AVX2" },
223 { "SM3",
224 "AVX" },
225 { "SM4",
226 "AVX2" },
227 { "XSAVES",
228 "XSAVEC" },
229 { "XSAVEC",
230 "XSAVE" },
231 { "OSPKE",
232 "XSAVE" },
233 { "GFNI",
234 "SSE2" },
235 { "VAES",
236 "AVX2|AES" },
237 { "VPCLMULQDQ",
238 "AVX2|PCLMULQDQ" },
239 { "AVX10_1",
240 "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA"
241 "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" },
242 { "SEV_ES",
243 "SVME" },
244 { "SNP",
245 "SEV_ES" },
246 { "RMPQUERY",
247 "SNP|64" },
248 { "TSX",
249 "RTM|HLE" },
250 { "TSXLDTRK",
251 "RTM" },
252 { "AMX_TILE",
253 "XSAVE|64" },
254 { "AMX_INT8",
255 "AMX_TILE" },
256 { "AMX_BF16",
257 "AMX_TILE" },
258 { "AMX_FP16",
259 "AMX_TILE" },
260 { "AMX_COMPLEX",
261 "AMX_TILE" },
262 { "KL",
263 "SSE2" },
264 { "WIDEKL",
265 "KL" },
266 { "PBNDKB",
267 "64" },
268 { "UINTR",
269 "64" },
270 { "PREFETCHI",
271 "64" },
272 { "CMPCCXADD",
273 "64" },
274 { "MSRLIST",
275 "64" },
276 { "USER_MSR",
277 "64" },
280 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
281 static unsigned char isa_reverse_deps[CpuMax][CpuMax];
283 typedef struct bitfield
285 int position;
286 int value;
287 const char *name;
288 } bitfield;
290 #define BITFIELD(n) { Cpu##n, 0, #n }
292 static bitfield cpu_flags[] =
294 BITFIELD (186),
295 BITFIELD (286),
296 BITFIELD (386),
297 BITFIELD (486),
298 BITFIELD (586),
299 BITFIELD (686),
300 BITFIELD (CMOV),
301 BITFIELD (FXSR),
302 BITFIELD (Clflush),
303 BITFIELD (Nop),
304 BITFIELD (SYSCALL),
305 BITFIELD (8087),
306 BITFIELD (287),
307 BITFIELD (387),
308 BITFIELD (687),
309 BITFIELD (FISTTP),
310 BITFIELD (MMX),
311 BITFIELD (SSE),
312 BITFIELD (SSE2),
313 BITFIELD (SSE3),
314 BITFIELD (SSSE3),
315 BITFIELD (SSE4_1),
316 BITFIELD (SSE4_2),
317 BITFIELD (AVX),
318 BITFIELD (AVX2),
319 BITFIELD (AVX512F),
320 BITFIELD (AVX512CD),
321 BITFIELD (AVX512ER),
322 BITFIELD (AVX512PF),
323 BITFIELD (AVX512VL),
324 BITFIELD (AVX512DQ),
325 BITFIELD (AVX512BW),
326 BITFIELD (IAMCU),
327 BITFIELD (SSE4a),
328 BITFIELD (3dnow),
329 BITFIELD (3dnowA),
330 BITFIELD (PadLock),
331 BITFIELD (SVME),
332 BITFIELD (VMX),
333 BITFIELD (SMX),
334 BITFIELD (Xsave),
335 BITFIELD (Xsaveopt),
336 BITFIELD (AES),
337 BITFIELD (PCLMULQDQ),
338 BITFIELD (FMA),
339 BITFIELD (FMA4),
340 BITFIELD (XOP),
341 BITFIELD (LWP),
342 BITFIELD (BMI),
343 BITFIELD (TBM),
344 BITFIELD (Movbe),
345 BITFIELD (CX16),
346 BITFIELD (LAHF_SAHF),
347 BITFIELD (EPT),
348 BITFIELD (Rdtscp),
349 BITFIELD (FSGSBase),
350 BITFIELD (RdRnd),
351 BITFIELD (F16C),
352 BITFIELD (BMI2),
353 BITFIELD (LZCNT),
354 BITFIELD (POPCNT),
355 BITFIELD (MONITOR),
356 BITFIELD (HLE),
357 BITFIELD (RTM),
358 BITFIELD (INVPCID),
359 BITFIELD (VMFUNC),
360 BITFIELD (RDSEED),
361 BITFIELD (ADX),
362 BITFIELD (PRFCHW),
363 BITFIELD (SMAP),
364 BITFIELD (SHA),
365 BITFIELD (SHA512),
366 BITFIELD (SM3),
367 BITFIELD (SM4),
368 BITFIELD (ClflushOpt),
369 BITFIELD (XSAVES),
370 BITFIELD (XSAVEC),
371 BITFIELD (PREFETCHWT1),
372 BITFIELD (SE1),
373 BITFIELD (CLWB),
374 BITFIELD (MPX),
375 BITFIELD (AVX512IFMA),
376 BITFIELD (AVX512VBMI),
377 BITFIELD (AVX512_4FMAPS),
378 BITFIELD (AVX512_4VNNIW),
379 BITFIELD (AVX512_VPOPCNTDQ),
380 BITFIELD (AVX512_VBMI2),
381 BITFIELD (AVX512_VNNI),
382 BITFIELD (AVX512_BITALG),
383 BITFIELD (AVX512_BF16),
384 BITFIELD (AVX512_VP2INTERSECT),
385 BITFIELD (TDX),
386 BITFIELD (AVX_VNNI),
387 BITFIELD (AVX512_FP16),
388 BITFIELD (PREFETCHI),
389 BITFIELD (AVX_IFMA),
390 BITFIELD (AVX_VNNI_INT8),
391 BITFIELD (AVX_VNNI_INT16),
392 BITFIELD (CMPCCXADD),
393 BITFIELD (WRMSRNS),
394 BITFIELD (MSRLIST),
395 BITFIELD (AVX_NE_CONVERT),
396 BITFIELD (RAO_INT),
397 BITFIELD (FRED),
398 BITFIELD (LKGS),
399 BITFIELD (USER_MSR),
400 BITFIELD (MWAITX),
401 BITFIELD (CLZERO),
402 BITFIELD (OSPKE),
403 BITFIELD (RDPID),
404 BITFIELD (PTWRITE),
405 BITFIELD (IBT),
406 BITFIELD (SHSTK),
407 BITFIELD (GFNI),
408 BITFIELD (VAES),
409 BITFIELD (VPCLMULQDQ),
410 BITFIELD (WBNOINVD),
411 BITFIELD (PCONFIG),
412 BITFIELD (PBNDKB),
413 BITFIELD (WAITPKG),
414 BITFIELD (UINTR),
415 BITFIELD (CLDEMOTE),
416 BITFIELD (AMX_INT8),
417 BITFIELD (AMX_BF16),
418 BITFIELD (AMX_FP16),
419 BITFIELD (AMX_COMPLEX),
420 BITFIELD (AMX_TILE),
421 BITFIELD (MOVDIRI),
422 BITFIELD (MOVDIR64B),
423 BITFIELD (ENQCMD),
424 BITFIELD (SERIALIZE),
425 BITFIELD (RDPRU),
426 BITFIELD (MCOMMIT),
427 BITFIELD (SEV_ES),
428 BITFIELD (TSXLDTRK),
429 BITFIELD (KL),
430 BITFIELD (WideKL),
431 BITFIELD (HRESET),
432 BITFIELD (INVLPGB),
433 BITFIELD (TLBSYNC),
434 BITFIELD (SNP),
435 BITFIELD (RMPQUERY),
436 BITFIELD (64),
437 BITFIELD (No64),
438 #ifdef CpuUnused
439 BITFIELD (Unused),
440 #endif
443 #undef BITFIELD
444 #define BITFIELD(n) { n, 0, #n }
446 static bitfield opcode_modifiers[] =
448 BITFIELD (D),
449 BITFIELD (W),
450 BITFIELD (Load),
451 BITFIELD (Modrm),
452 BITFIELD (Jump),
453 BITFIELD (FloatMF),
454 BITFIELD (Size),
455 BITFIELD (CheckOperandSize),
456 BITFIELD (OperandConstraint),
457 BITFIELD (MnemonicSize),
458 BITFIELD (No_bSuf),
459 BITFIELD (No_wSuf),
460 BITFIELD (No_lSuf),
461 BITFIELD (No_sSuf),
462 BITFIELD (No_qSuf),
463 BITFIELD (FWait),
464 BITFIELD (IsString),
465 BITFIELD (RegMem),
466 BITFIELD (BNDPrefixOk),
467 BITFIELD (PrefixOk),
468 BITFIELD (IsPrefix),
469 BITFIELD (ImmExt),
470 BITFIELD (NoRex64),
471 BITFIELD (Vex),
472 BITFIELD (VexVVVV),
473 BITFIELD (VexW),
474 BITFIELD (OpcodePrefix),
475 BITFIELD (SIB),
476 BITFIELD (SSE2AVX),
477 BITFIELD (EVex),
478 BITFIELD (Masking),
479 BITFIELD (Broadcast),
480 BITFIELD (StaticRounding),
481 BITFIELD (SAE),
482 BITFIELD (Disp8MemShift),
483 BITFIELD (Vsz),
484 BITFIELD (Optimize),
485 BITFIELD (ATTMnemonic),
486 BITFIELD (ATTSyntax),
487 BITFIELD (IntelSyntax),
488 BITFIELD (ISA64),
491 #define CLASS(n) #n, n
493 static const struct {
494 const char *name;
495 enum operand_class value;
496 } operand_classes[] = {
497 CLASS (Reg),
498 CLASS (SReg),
499 CLASS (RegCR),
500 CLASS (RegDR),
501 CLASS (RegTR),
502 CLASS (RegMMX),
503 CLASS (RegSIMD),
504 CLASS (RegMask),
505 CLASS (RegBND),
508 #undef CLASS
510 #define INSTANCE(n) #n, n
512 static const struct {
513 const char *name;
514 enum operand_instance value;
515 } operand_instances[] = {
516 INSTANCE (Accum),
517 INSTANCE (RegC),
518 INSTANCE (RegD),
519 INSTANCE (RegB),
522 #undef INSTANCE
524 static bitfield operand_types[] =
526 BITFIELD (Imm1),
527 BITFIELD (Imm8),
528 BITFIELD (Imm8S),
529 BITFIELD (Imm16),
530 BITFIELD (Imm32),
531 BITFIELD (Imm32S),
532 BITFIELD (Imm64),
533 BITFIELD (BaseIndex),
534 BITFIELD (Disp8),
535 BITFIELD (Disp16),
536 BITFIELD (Disp32),
537 BITFIELD (Disp64),
538 BITFIELD (Byte),
539 BITFIELD (Word),
540 BITFIELD (Dword),
541 BITFIELD (Fword),
542 BITFIELD (Qword),
543 BITFIELD (Tbyte),
544 BITFIELD (Xmmword),
545 BITFIELD (Ymmword),
546 BITFIELD (Zmmword),
547 BITFIELD (Tmmword),
548 BITFIELD (Unspecified),
549 #ifdef OTUnused
550 BITFIELD (OTUnused),
551 #endif
554 static const char *filename;
555 static i386_cpu_flags active_cpu_flags;
556 static int active_isstring;
558 struct template_arg {
559 const struct template_arg *next;
560 const char *val;
563 struct template_instance {
564 const struct template_instance *next;
565 const char *name;
566 const struct template_arg *args;
569 struct template_param {
570 const struct template_param *next;
571 const char *name;
574 struct template {
575 struct template *next;
576 const char *name;
577 const struct template_instance *instances;
578 const struct template_param *params;
581 static struct template *templates;
583 static int
584 compare (const void *x, const void *y)
586 const bitfield *xp = (const bitfield *) x;
587 const bitfield *yp = (const bitfield *) y;
588 return xp->position - yp->position;
591 static void
592 fail (const char *message, ...)
594 va_list args;
596 va_start (args, message);
597 fprintf (stderr, "%s: error: ", program_name);
598 vfprintf (stderr, message, args);
599 va_end (args);
600 xexit (1);
603 static void
604 process_copyright (FILE *fp)
606 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
607 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
609 This file is part of the GNU opcodes library.\n\
611 This library is free software; you can redistribute it and/or modify\n\
612 it under the terms of the GNU General Public License as published by\n\
613 the Free Software Foundation; either version 3, or (at your option)\n\
614 any later version.\n\
616 It is distributed in the hope that it will be useful, but WITHOUT\n\
617 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
618 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
619 License for more details.\n\
621 You should have received a copy of the GNU General Public License\n\
622 along with this program; if not, write to the Free Software\n\
623 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
624 MA 02110-1301, USA. */\n");
627 /* Remove leading white spaces. */
629 static char *
630 remove_leading_whitespaces (char *str)
632 while (ISSPACE (*str))
633 str++;
634 return str;
637 /* Remove trailing white spaces. */
639 static void
640 remove_trailing_whitespaces (char *str)
642 size_t last = strlen (str);
644 if (last == 0)
645 return;
649 last--;
650 if (ISSPACE (str [last]))
651 str[last] = '\0';
652 else
653 break;
655 while (last != 0);
658 /* Find next field separated by SEP and terminate it. Return a
659 pointer to the one after it. */
661 static char *
662 next_field (char *str, char sep, char **next, char *last)
664 char *p;
666 p = remove_leading_whitespaces (str);
667 for (str = p; *str != sep && *str != '\0'; str++);
669 *str = '\0';
670 remove_trailing_whitespaces (p);
672 *next = str + 1;
674 if (p >= last)
675 abort ();
677 return p;
680 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
682 static void
683 set_bitfield (char *f, bitfield *array, int value,
684 unsigned int size, int lineno)
686 unsigned int i;
688 /* Ignore empty fields; they may result from template expansions. */
689 if (*f == '\0')
690 return;
692 for (i = 0; i < size; i++)
693 if (strcasecmp (array[i].name, f) == 0)
695 array[i].value = value;
696 return;
699 if (value)
701 const char *v = strchr (f, '=');
703 if (v)
705 size_t n = v - f;
706 char *end;
708 for (i = 0; i < size; i++)
709 if (strncasecmp (array[i].name, f, n) == 0)
711 value = strtol (v + 1, &end, 0);
712 if (*end == '\0')
714 array[i].value = value;
715 return;
717 break;
722 if (lineno != -1)
723 fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f);
724 else
725 fail ("unknown bitfield: %s\n", f);
728 static void
729 add_isa_dependencies (bitfield *flags, const char *f, int value,
730 unsigned int reverse)
732 unsigned int i;
733 char *str = NULL;
734 const char *isa = f;
735 static bool is_avx;
736 bool is_isa = false, orig_is_avx = is_avx;
738 /* Need to find base entry for references to auxiliary ones. */
739 if (strchr (f, ':'))
741 str = xstrdup (f);
742 *strchr (str, ':') = '\0';
743 isa = str;
745 /* isa_dependencies[] prefers "LM" over "64". */
746 else if (!strcmp (f, "LM"))
747 isa = "64";
748 for (i = 0; i < CpuMax; ++i)
749 if (strcasecmp (flags[i].name, isa) == 0)
751 flags[i].value = value;
752 if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
753 /* Don't record the feature itself here. */
754 && reverse != i
755 /* Don't record base architectures. */
756 && reverse > Cpu686)
757 isa_reverse_deps[i][reverse] = 1;
758 is_isa = true;
759 if (i == CpuAVX || i == CpuXOP || i == CpuVAES || i == CpuVPCLMULQDQ)
760 is_avx = true;
761 break;
763 free (str);
765 /* Do not turn off dependencies. */
766 if (is_isa && !value)
768 is_avx = orig_is_avx;
769 return;
772 for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i)
773 if (strcasecmp (isa_dependencies[i].name, f) == 0)
775 char *deps = xstrdup (isa_dependencies[i].deps);
776 char *next = deps;
777 char *last = deps + strlen (deps);
779 for (; next && next < last; )
781 char *str = next_field (next, '|', &next, last);
783 /* No AVX/XOP -> SSE reverse dependencies. */
784 if (is_avx && strncmp (str, "SSE", 3) == 0)
785 add_isa_dependencies (flags, str, value, CpuMax);
786 else
787 add_isa_dependencies (flags, str, value, reverse);
789 free (deps);
791 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted,
792 unless the sole dependency is the "64-bit mode only" one. */
793 if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
794 && strcmp (isa_dependencies[i].deps, "64"))
795 isa_reverse_deps[reverse][reverse] = 1;
797 is_avx = orig_is_avx;
798 return;
801 if (!is_isa)
802 fail ("unknown bitfield: %s\n", f);
804 is_avx = orig_is_avx;
807 static void
808 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
809 int mode, const char *comma, const char *indent, int lineno)
811 unsigned int i = 0, j = 0;
813 if (mode < 0)
814 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
816 fprintf (table, "%s{ { ", indent);
818 if (mode <= 0)
820 for (j = ~0u; i < CpuAttrEnums; i++)
822 if (!flags[i].value)
823 continue;
825 if (j < ~0u)
826 fail ("%s: %d: invalid combination of CPU identifiers\n",
827 filename, lineno);
828 j = i;
829 if (mode)
830 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
833 /* Write 0 to indicate "no associated flag". */
834 fprintf (table, "%u, ", j + 1);
836 j = 1;
839 for (; i < size - 1; i++, j++)
841 if (((j + 1) % 20) != 0)
842 fprintf (table, "%d, ", flags[i].value);
843 else
844 fprintf (table, "%d,", flags[i].value);
845 if (((j + 1) % 20) == 0)
847 /* We need \\ for macro. */
848 if (mode > 0)
849 fprintf (table, " \\\n %s", indent);
850 else
851 fprintf (table, "\n %s", indent);
853 if (mode < 0 && flags[i].value)
854 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
857 fprintf (table, "%d } }%s\n", flags[i].value, comma);
860 static void
861 process_i386_cpu_flag (FILE *table, char *flag,
862 const char *name,
863 const char *comma, const char *indent,
864 int lineno, unsigned int reverse)
866 char *str, *next = flag, *last;
867 unsigned int i;
868 int value = 1;
869 bool is_isa = false;
870 bitfield all [ARRAY_SIZE (cpu_flags)];
871 bitfield any [ARRAY_SIZE (cpu_flags)];
873 /* Copy the default cpu flags. */
874 memcpy (all, cpu_flags, sizeof (cpu_flags));
875 memcpy (any, cpu_flags, sizeof (cpu_flags));
877 if (flag == NULL)
879 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
880 any[i].value = isa_reverse_deps[reverse][i];
881 goto output;
884 if (flag[0] == '~')
886 last = flag + strlen (flag);
888 if (flag[1] == '(')
890 last -= 1;
891 next = flag + 2;
892 if (*last != ')')
893 fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
894 lineno, flag);
895 *last = '\0';
897 else
898 next = flag + 1;
900 /* First we turn on everything except for cpuno64 and - if
901 present - the padding field. */
902 for (i = 0; i < ARRAY_SIZE (any); i++)
903 if (any[i].position < CpuNo64)
904 any[i].value = 1;
906 /* Turn off selective bits. */
907 value = 0;
910 if (name != NULL && value != 0)
912 for (i = 0; i < ARRAY_SIZE (any); i++)
913 if (strcasecmp (any[i].name, name) == 0)
915 add_isa_dependencies (any, name, 1, reverse);
916 is_isa = true;
917 break;
921 if (strcmp (flag, "0"))
923 bool combined = false;
925 if (is_isa)
926 return;
928 /* Turn on/off selective bits. */
929 last = flag + strlen (flag);
930 if (name == NULL && strchr (flag, '&'))
932 for (; next < last && *next != '('; )
934 str = next_field (next, '&', &next, last);
935 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
937 if (*next == '(')
939 if (*--last != ')')
940 fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
941 lineno, flag);
942 ++next;
943 *last = '\0';
945 combined = true;
947 for (; next && next < last; )
949 str = next_field (next, '|', &next, last);
950 if (name)
951 add_isa_dependencies (any, str, value, reverse);
952 else if (combined || next < last)
953 set_bitfield (str, any, value, ARRAY_SIZE (any), lineno);
954 else /* Singular specifiers go into "all". */
955 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
956 combined = true;
960 output:
961 if (name != NULL)
963 size_t len = strlen (name);
964 char *upper = xmalloc (len + 1);
966 /* Cpu64 is special: It specifies a mode dependency, not an ISA one. Zap
967 the flag from ISA initializer macros (and from CPU_ANY_64_FLAGS
968 itself we only care about tracking its dependents. Also don't emit the
969 (otherwise all zero) CPU_64_FLAGS. */
970 if (flag != NULL && reverse == Cpu64)
971 return;
972 if (is_isa || flag == NULL)
973 any[Cpu64].value = 0;
975 for (i = 0; i < len; ++i)
977 /* Don't emit #define-s for auxiliary entries. */
978 if (name[i] == ':')
979 return;
980 upper[i] = TOUPPER (name[i]);
982 upper[i] = '\0';
983 fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n",
984 flag != NULL ? "": "ANY_", upper);
985 free (upper);
987 else
989 /* Synthesize "64-bit mode only" dependencies from the dependencies we
990 have accumulated. */
991 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
992 if (all[i].value && isa_reverse_deps[Cpu64][i])
993 all[Cpu64].value = 1;
995 output_cpu_flags(table, all, ARRAY_SIZE (all), -1, comma, indent, lineno);
998 output_cpu_flags (table, any, ARRAY_SIZE (any), name != NULL,
999 comma, indent, lineno);
1002 static void
1003 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1005 unsigned int i;
1007 fprintf (table, " { ");
1009 for (i = 0; i < size - 1; i++)
1011 if (((i + 1) % 20) != 0)
1012 fprintf (table, "%d, ", modifier[i].value);
1013 else
1014 fprintf (table, "%d,", modifier[i].value);
1015 if (((i + 1) % 20) == 0)
1016 fprintf (table, "\n ");
1019 fprintf (table, "%d },\n", modifier[i].value);
1022 /* Returns LOG2 of element size. */
1023 static int
1024 get_element_size (char **opnd, int lineno)
1026 char *str, *next, *last, *op;
1027 const char *full = opnd[0];
1028 int elem_size = INT_MAX;
1030 /* Find the memory operand. */
1031 while (full != NULL && strstr(full, "BaseIndex") == NULL)
1032 full = *++opnd;
1033 if (full == NULL)
1034 fail ("%s: %d: no memory operand\n", filename, lineno);
1036 op = xstrdup (full);
1037 last = op + strlen (op);
1038 for (next = op; next && next < last; )
1040 str = next_field (next, '|', &next, last);
1041 if (str)
1043 if (strcasecmp(str, "Byte") == 0)
1045 /* The smallest element size, no need to check
1046 further. */
1047 elem_size = 0;
1048 break;
1050 else if (strcasecmp(str, "Word") == 0)
1052 if (elem_size > 1)
1053 elem_size = 1;
1055 else if (strcasecmp(str, "Dword") == 0)
1057 if (elem_size > 2)
1058 elem_size = 2;
1060 else if (strcasecmp(str, "Qword") == 0)
1062 if (elem_size > 3)
1063 elem_size = 3;
1067 free (op);
1069 if (elem_size == INT_MAX)
1070 fail ("%s: %d: unknown element size: %s\n", filename, lineno, full);
1072 return elem_size;
1075 static void
1076 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1077 unsigned int prefix, const char *extension_opcode,
1078 char **opnd, int lineno)
1080 char *str, *next, *last;
1081 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1082 static const char *const spaces[] = {
1083 #define SPACE(n) [SPACE_##n] = #n
1084 SPACE(BASE),
1085 SPACE(0F),
1086 SPACE(0F38),
1087 SPACE(0F3A),
1088 SPACE(EVEXMAP5),
1089 SPACE(EVEXMAP6),
1090 SPACE(VEXMAP7),
1091 SPACE(XOP08),
1092 SPACE(XOP09),
1093 SPACE(XOP0A),
1094 #undef SPACE
1097 active_isstring = 0;
1099 /* Copy the default opcode modifier. */
1100 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1102 if (strcmp (mod, "0"))
1104 unsigned int have_w = 0, bwlq_suf = 0xf;
1106 last = mod + strlen (mod);
1107 for (next = mod; next && next < last; )
1109 str = next_field (next, '|', &next, last);
1110 if (str)
1112 int val = 1;
1114 if (strncmp(str, "OpcodeSpace", 11) == 0)
1116 char *end;
1118 if (str[11] != '=')
1119 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1120 filename, lineno);
1122 val = strtol (str + 12, &end, 0);
1123 if (*end)
1124 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1125 filename, lineno, end);
1127 if (space)
1129 if (val != space)
1130 fail ("%s:%d: Conflicting opcode space specifications\n",
1131 filename, lineno);
1132 fprintf (stderr,
1133 "%s:%d: Warning: redundant opcode space specification\n",
1134 filename, lineno);
1137 space = val;
1138 continue;
1141 if (strcasecmp(str, "Broadcast") == 0)
1142 val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1143 else if (strcasecmp(str, "Disp8MemShift") == 0)
1144 val = get_element_size (opnd, lineno);
1146 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1147 lineno);
1148 if (strcasecmp(str, "IsString") == 0)
1149 active_isstring = 1;
1151 if (strcasecmp(str, "W") == 0)
1152 have_w = 1;
1154 if (strcasecmp(str, "No_bSuf") == 0)
1155 bwlq_suf &= ~1;
1156 if (strcasecmp(str, "No_wSuf") == 0)
1157 bwlq_suf &= ~2;
1158 if (strcasecmp(str, "No_lSuf") == 0)
1159 bwlq_suf &= ~4;
1160 if (strcasecmp(str, "No_qSuf") == 0)
1161 bwlq_suf &= ~8;
1165 if (prefix)
1167 if (!modifiers[OpcodePrefix].value)
1168 modifiers[OpcodePrefix].value = prefix;
1169 else if (modifiers[OpcodePrefix].value != prefix)
1170 fail ("%s:%d: Conflicting prefix specifications\n",
1171 filename, lineno);
1172 else
1173 fprintf (stderr,
1174 "%s:%d: Warning: redundant prefix specification\n",
1175 filename, lineno);
1178 if (have_w && !bwlq_suf)
1179 fail ("%s: %d: stray W modifier\n", filename, lineno);
1180 if (have_w && !(bwlq_suf & 1))
1181 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1182 filename, lineno);
1183 if (have_w && !(bwlq_suf & ~1))
1184 fprintf (stderr,
1185 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1186 filename, lineno);
1189 if (space >= ARRAY_SIZE (spaces) || !spaces[space])
1190 fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
1192 fprintf (table, " SPACE_%s, %s,\n",
1193 spaces[space], extension_opcode ? extension_opcode : "None");
1195 /* Rather than evaluating multiple conditions at runtime to determine
1196 whether an EVEX encoding is being dealt with, derive that information
1197 right here. A missing EVex attribute means "dynamic". */
1198 if (!modifiers[EVex].value
1199 && (modifiers[Disp8MemShift].value
1200 || modifiers[Broadcast].value
1201 || modifiers[Masking].value
1202 || modifiers[SAE].value))
1203 modifiers[EVex].value = EVEXDYN;
1205 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1208 enum stage {
1209 stage_macros,
1210 stage_opcodes,
1211 stage_registers,
1214 static void
1215 output_operand_type (FILE *table, enum operand_class class,
1216 enum operand_instance instance,
1217 const bitfield *types, unsigned int size,
1218 enum stage stage, const char *indent)
1220 unsigned int i;
1222 fprintf (table, "{ { %d, %d, ", class, instance);
1224 for (i = 0; i < size - 1; i++)
1226 if (((i + 3) % 20) != 0)
1227 fprintf (table, "%d, ", types[i].value);
1228 else
1229 fprintf (table, "%d,", types[i].value);
1230 if (((i + 3) % 20) == 0)
1232 /* We need \\ for macro. */
1233 if (stage == stage_macros)
1234 fprintf (table, " \\\n%s", indent);
1235 else
1236 fprintf (table, "\n%s", indent);
1240 fprintf (table, "%d } }", types[i].value);
1243 static void
1244 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1245 const char *indent, int lineno)
1247 char *str, *next, *last;
1248 enum operand_class class = ClassNone;
1249 enum operand_instance instance = InstanceNone;
1250 bitfield types [ARRAY_SIZE (operand_types)];
1252 /* Copy the default operand type. */
1253 memcpy (types, operand_types, sizeof (types));
1255 if (strcmp (op, "0"))
1257 int baseindex = 0;
1259 last = op + strlen (op);
1260 for (next = op; next && next < last; )
1262 str = next_field (next, '|', &next, last);
1263 if (str)
1265 unsigned int i;
1267 if (!strncmp(str, "Class=", 6))
1269 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1270 if (!strcmp(str + 6, operand_classes[i].name))
1272 class = operand_classes[i].value;
1273 str = NULL;
1274 break;
1278 if (str && !strncmp(str, "Instance=", 9))
1280 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1281 if (!strcmp(str + 9, operand_instances[i].name))
1283 instance = operand_instances[i].value;
1284 str = NULL;
1285 break;
1289 if (str)
1291 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1292 if (strcasecmp(str, "BaseIndex") == 0)
1293 baseindex = 1;
1297 if (stage == stage_opcodes && baseindex && !active_isstring)
1299 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1300 if (!active_cpu_flags.bitfield.cpu64
1301 && !active_cpu_flags.bitfield.cpumpx)
1302 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1303 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1306 output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1307 stage, indent);
1310 static char *mkident (const char *mnem)
1312 char *ident = xstrdup (mnem), *p = ident;
1316 if (!ISALNUM (*p))
1317 *p = '_';
1319 while (*++p);
1321 return ident;
1324 static void
1325 output_i386_opcode (FILE *table, const char *name, char *str,
1326 char *last, int lineno)
1328 unsigned int i, length, prefix = 0, space = 0;
1329 char *base_opcode, *extension_opcode, *end, *ident;
1330 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1331 unsigned long long opcode;
1333 /* Find base_opcode. */
1334 base_opcode = next_field (str, ',', &str, last);
1336 /* Find extension_opcode, if any. */
1337 extension_opcode = strchr (base_opcode, '/');
1338 if (extension_opcode)
1339 *extension_opcode++ = '\0';
1341 /* Find cpu_flags. */
1342 cpu_flags = next_field (str, ',', &str, last);
1344 /* Find opcode_modifier. */
1345 opcode_modifier = next_field (str, ',', &str, last);
1347 /* Remove the first {. */
1348 str = remove_leading_whitespaces (str);
1349 if (*str != '{')
1350 abort ();
1351 str = remove_leading_whitespaces (str + 1);
1352 remove_trailing_whitespaces (str);
1354 /* Remove } and trailing white space. */
1355 i = strlen (str);
1356 if (!i || str[i - 1] != '}')
1357 abort ();
1358 str[--i] = '\0';
1359 remove_trailing_whitespaces (str);
1361 if (!*str)
1362 operand_types [i = 0] = NULL;
1363 else
1365 last = str + strlen (str);
1367 /* Find operand_types. */
1368 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1370 if (str >= last)
1372 operand_types [i] = NULL;
1373 break;
1376 operand_types [i] = next_field (str, ',', &str, last);
1380 opcode = strtoull (base_opcode, &end, 0);
1382 /* Determine opcode length. */
1383 for (length = 1; length < 8; ++length)
1384 if (!(opcode >> (8 * length)))
1385 break;
1387 /* Transform prefixes encoded in the opcode into opcode modifier
1388 representation. */
1389 if (length > 1)
1391 switch (opcode >> (8 * length - 8))
1393 case 0x66: prefix = PREFIX_0X66; break;
1394 case 0xF3: prefix = PREFIX_0XF3; break;
1395 case 0xF2: prefix = PREFIX_0XF2; break;
1398 if (prefix)
1399 opcode &= (1ULL << (8 * --length)) - 1;
1402 /* Transform opcode space encoded in the opcode into opcode modifier
1403 representation. */
1404 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1406 switch ((opcode >> (8 * length - 16)) & 0xff)
1408 default: space = SPACE_0F; break;
1409 case 0x38: space = SPACE_0F38; break;
1410 case 0x3A: space = SPACE_0F3A; break;
1413 if (space != SPACE_0F && --length == 1)
1414 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1415 filename, lineno, name);
1416 opcode &= (1ULL << (8 * --length)) - 1;
1419 if (length > 2)
1420 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1421 filename, lineno, name, 2 * length, opcode);
1423 ident = mkident (name);
1424 fprintf (table, " { MN_%s, 0x%0*llx%s, %u,",
1425 ident, 2 * (int)length, opcode, end, i);
1426 free (ident);
1428 process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1429 extension_opcode, operand_types, lineno);
1431 process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax);
1433 fprintf (table, " { ");
1435 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1437 if (!operand_types[i])
1439 if (i == 0)
1440 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1441 lineno);
1442 break;
1445 if (i != 0)
1446 fprintf (table, ",\n ");
1448 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1449 "\t ", lineno);
1451 fprintf (table, " } },\n");
1454 struct opcode_hash_entry
1456 const char *name;
1457 struct opcode_entry
1459 struct opcode_entry *next;
1460 char *opcode;
1461 int lineno;
1462 } entry;
1465 /* Calculate the hash value of an opcode hash entry P. */
1467 static hashval_t
1468 opcode_hash_hash (const void *p)
1470 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1471 return htab_hash_string (entry->name);
1474 /* Compare a string Q against an opcode hash entry P. */
1476 static int
1477 opcode_hash_eq (const void *p, const void *q)
1479 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1480 const char *name = (const char *) q;
1481 return strcmp (name, entry->name) == 0;
1484 static void
1485 parse_template (char *buf, int lineno)
1487 char sep, *end, *name;
1488 struct template *tmpl;
1489 struct template_instance *last_inst = NULL;
1491 buf = remove_leading_whitespaces (buf + 1);
1492 end = strchr (buf, ':');
1493 if (end == NULL)
1495 struct template *prev = NULL;
1497 end = strchr (buf, '>');
1498 if (end == NULL)
1499 fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1500 if (*remove_leading_whitespaces (end + 1))
1501 fail ("%s: %d: malformed template purge\n", filename, lineno);
1502 *end = '\0';
1503 remove_trailing_whitespaces (buf);
1504 /* Don't bother freeing the various structures. */
1505 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1506 if (!strcmp (buf, tmpl->name))
1507 break;
1508 if (tmpl == NULL)
1509 fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1510 if (prev)
1511 prev->next = tmpl->next;
1512 else
1513 templates = tmpl->next;
1514 return;
1516 *end++ = '\0';
1517 remove_trailing_whitespaces (buf);
1519 if (*buf == '\0')
1520 fail ("%s: %d: missing template identifier\n", filename, lineno);
1521 tmpl = xmalloc (sizeof (*tmpl));
1522 tmpl->name = xstrdup (buf);
1524 tmpl->params = NULL;
1525 do {
1526 struct template_param *param;
1528 buf = remove_leading_whitespaces (end);
1529 end = strpbrk (buf, ":,");
1530 if (end == NULL)
1531 fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1533 sep = *end;
1534 *end++ = '\0';
1535 remove_trailing_whitespaces (buf);
1537 param = xmalloc (sizeof (*param));
1538 param->name = xstrdup (buf);
1539 param->next = tmpl->params;
1540 tmpl->params = param;
1541 } while (sep == ':');
1543 tmpl->instances = NULL;
1544 do {
1545 struct template_instance *inst;
1546 char *cur, *next;
1547 const struct template_param *param;
1549 buf = remove_leading_whitespaces (end);
1550 end = strpbrk (buf, ",>");
1551 if (end == NULL)
1552 fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1554 sep = *end;
1555 *end++ = '\0';
1557 inst = xmalloc (sizeof (*inst));
1558 inst->next = NULL;
1559 inst->args = NULL;
1561 cur = next_field (buf, ':', &next, end);
1562 inst->name = *cur != '$' ? xstrdup (cur) : "";
1564 for (param = tmpl->params; param; param = param->next)
1566 struct template_arg *arg = xmalloc (sizeof (*arg));
1568 cur = next_field (next, ':', &next, end);
1569 if (next > end)
1570 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1571 arg->val = xstrdup (cur);
1572 arg->next = inst->args;
1573 inst->args = arg;
1576 if (tmpl->instances)
1577 last_inst->next = inst;
1578 else
1579 tmpl->instances = inst;
1580 last_inst = inst;
1581 } while (sep == ',');
1583 buf = remove_leading_whitespaces (end);
1584 if (*buf)
1585 fprintf(stderr, "%s: %d: excess characters '%s'\n",
1586 filename, lineno, buf);
1588 tmpl->next = templates;
1589 templates = tmpl;
1592 static unsigned int
1593 expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1594 struct opcode_hash_entry ***opcode_array_p, int lineno)
1596 static unsigned int idx, opcode_array_size;
1597 struct opcode_hash_entry **opcode_array = *opcode_array_p;
1598 struct opcode_hash_entry **hash_slot;
1599 struct opcode_entry *entry;
1600 char *ptr1 = strchr(name, '<'), *ptr2;
1602 if (ptr1 == NULL)
1604 /* Get the slot in hash table. */
1605 hash_slot = (struct opcode_hash_entry **)
1606 htab_find_slot_with_hash (opcode_hash_table, name,
1607 htab_hash_string (name),
1608 INSERT);
1610 if (*hash_slot == NULL)
1612 /* It is the new one. Put it on opcode array. */
1613 if (idx >= opcode_array_size)
1615 /* Grow the opcode array when needed. */
1616 opcode_array_size += 1024;
1617 opcode_array = (struct opcode_hash_entry **)
1618 xrealloc (opcode_array,
1619 sizeof (*opcode_array) * opcode_array_size);
1620 *opcode_array_p = opcode_array;
1623 opcode_array[idx] = (struct opcode_hash_entry *)
1624 xmalloc (sizeof (struct opcode_hash_entry));
1625 opcode_array[idx]->name = xstrdup (name);
1626 *hash_slot = opcode_array[idx];
1627 entry = &opcode_array[idx]->entry;
1628 idx++;
1630 else
1632 /* Append it to the existing one. */
1633 struct opcode_entry **entryp = &(*hash_slot)->entry.next;
1635 while (*entryp != NULL)
1636 entryp = &(*entryp)->next;
1637 entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry));
1638 *entryp = entry;
1641 entry->next = NULL;
1642 entry->opcode = xstrdup (str);
1643 entry->lineno = lineno;
1645 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1646 fail ("%s: %d: missing '>'\n", filename, lineno);
1647 else
1649 const struct template *tmpl;
1650 const struct template_instance *inst;
1652 *ptr1 = '\0';
1653 ptr1 = remove_leading_whitespaces (ptr1 + 1);
1654 remove_trailing_whitespaces (ptr1);
1656 *ptr2++ = '\0';
1658 for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1659 if (!strcmp(ptr1, tmpl->name))
1660 break;
1661 if (!tmpl)
1662 fail ("reference to unknown template '%s'\n", ptr1);
1664 for (inst = tmpl->instances; inst; inst = inst->next)
1666 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1667 char *str2 = xmalloc(2 * strlen(str));
1668 const char *src;
1670 strcpy (name2, name);
1671 strcat (name2, inst->name);
1672 strcat (name2, ptr2);
1674 for (ptr1 = str2, src = str; *src; )
1676 const char *ident = tmpl->name, *end;
1677 const struct template_param *param;
1678 const struct template_arg *arg;
1680 if ((*ptr1 = *src++) != '<')
1682 ++ptr1;
1683 continue;
1685 while (ISSPACE(*src))
1686 ++src;
1687 while (*ident && *src == *ident)
1688 ++src, ++ident;
1689 while (ISSPACE(*src))
1690 ++src;
1691 if (*src != ':' || *ident != '\0')
1693 memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1694 ptr1 += ident - tmpl->name;
1695 continue;
1697 while (ISSPACE(*++src))
1700 end = src;
1701 while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1702 ++end;
1704 for (param = tmpl->params, arg = inst->args; param;
1705 param = param->next, arg = arg->next)
1707 if (end - src == strlen (param->name)
1708 && !memcmp (src, param->name, end - src))
1710 src = end;
1711 break;
1715 if (param == NULL)
1716 fail ("template '%s' has no parameter '%.*s'\n",
1717 tmpl->name, (int)(end - src), src);
1719 while (ISSPACE(*src))
1720 ++src;
1721 if (*src != '>')
1722 fail ("%s: %d: missing '>'\n", filename, lineno);
1724 memcpy(ptr1, arg->val, strlen(arg->val));
1725 ptr1 += strlen(arg->val);
1726 ++src;
1729 *ptr1 = '\0';
1731 expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1732 lineno);
1734 free (str2);
1735 free (name2);
1739 return idx;
1742 static int mnemonic_cmp(const void *p1, const void *p2)
1744 const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2;
1745 const char *s1 = (*e1)->name, *s2 = (*e2)->name;
1746 unsigned int i;
1747 size_t l1 = strlen (s1), l2 = strlen (s2);
1749 for (i = 1; i <= l1 && i <= l2; ++i)
1751 if (s1[l1 - i] != s2[l2 - i])
1752 return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i];
1755 return (int)(l1 - l2);
1758 static void
1759 process_i386_opcodes (FILE *table)
1761 FILE *fp;
1762 char buf[2048];
1763 unsigned int i, j, nr, offs;
1764 size_t l;
1765 char *str, *p, *last;
1766 htab_t opcode_hash_table;
1767 struct opcode_hash_entry **opcode_array = NULL;
1768 int lineno = 0, marker = 0;
1770 filename = "i386-opc.tbl";
1771 fp = stdin;
1773 i = 0;
1774 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1775 opcode_hash_eq, NULL,
1776 xcalloc, free);
1778 fprintf (table, "\n#include \"i386-mnem.h\"\n");
1779 fprintf (table, "\n/* i386 opcode table. */\n\n");
1780 fprintf (table, "static const insn_template i386_optab[] =\n{\n");
1782 /* Put everything on opcode array. */
1783 while (!feof (fp))
1785 char *name;
1787 if (fgets (buf, sizeof (buf), fp) == NULL)
1788 break;
1790 p = remove_leading_whitespaces (buf);
1792 for ( ; ; )
1794 lineno++;
1796 /* Skip comments. */
1797 str = strstr (p, "//");
1798 if (str != NULL)
1800 str[0] = '\0';
1801 remove_trailing_whitespaces (p);
1802 break;
1805 /* Look for line continuation character. */
1806 remove_trailing_whitespaces (p);
1807 j = strlen (buf);
1808 if (!j || buf[j - 1] != '+')
1809 break;
1810 if (j >= sizeof (buf) - 1)
1811 fail ("%s: %d: (continued) line too long\n", filename, lineno);
1813 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1815 fprintf (stderr, "%s: Line continuation on last line?\n",
1816 filename);
1817 break;
1821 switch (p[0])
1823 case '#':
1824 if (!strcmp("### MARKER ###", buf))
1825 marker = 1;
1826 else
1828 /* Since we ignore all included files (we only care about their
1829 #define-s here), we don't need to monitor filenames. The final
1830 line number directive is going to refer to the main source file
1831 again. */
1832 char *end;
1833 unsigned long ln;
1835 p = remove_leading_whitespaces (p + 1);
1836 if (!strncmp(p, "line", 4))
1837 p += 4;
1838 ln = strtoul (p, &end, 10);
1839 if (ln > 1 && ln < INT_MAX
1840 && *remove_leading_whitespaces (end) == '"')
1841 lineno = ln - 1;
1843 /* Ignore comments. */
1844 case '\0':
1845 continue;
1846 break;
1847 case '<':
1848 parse_template (p, lineno);
1849 continue;
1850 default:
1851 if (!marker)
1852 continue;
1853 break;
1856 last = p + strlen (p);
1858 /* Find name. */
1859 name = next_field (p, ',', &str, last);
1861 i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1862 lineno);
1865 /* Process opcode array. */
1866 for (j = 0; j < i; j++)
1868 const char *name = opcode_array[j]->name;
1869 struct opcode_entry *next;
1871 for (next = &opcode_array[j]->entry; next; next = next->next)
1873 str = next->opcode;
1874 lineno = next->lineno;
1875 last = str + strlen (str);
1876 output_i386_opcode (table, name, str, last, lineno);
1880 fclose (fp);
1882 fprintf (table, "};\n");
1884 /* Generate opcode sets array. */
1885 fprintf (table, "\n/* i386 opcode sets table. */\n\n");
1886 fprintf (table, "static const insn_template *const i386_op_sets[] =\n{\n");
1887 fprintf (table, " i386_optab,\n");
1889 for (nr = j = 0; j < i; j++)
1891 struct opcode_entry *next = &opcode_array[j]->entry;
1895 ++nr;
1896 next = next->next;
1898 while (next);
1899 fprintf (table, " i386_optab + %u,\n", nr);
1902 fprintf (table, "};\n");
1904 /* Emit mnemonics and associated #define-s. */
1905 qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
1907 fp = fopen ("i386-mnem.h", "w");
1908 if (fp == NULL)
1909 fail ("can't create i386-mnem.h, errno = %s\n",
1910 xstrerror (errno));
1912 process_copyright (fp);
1914 fprintf (table, "\n/* i386 mnemonics table. */\n\n");
1915 fprintf (table, "const char i386_mnemonics[] =\n");
1916 fprintf (fp, "\nextern const char i386_mnemonics[];\n\n");
1918 str = NULL;
1919 for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++)
1921 const char *name = opcode_array[j]->name;
1922 const char *next = NULL;
1923 size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0;
1925 if (str == NULL)
1926 str = mkident (name);
1927 if (l < l1 && !strcmp(name, next + l1 - l))
1929 fprintf (fp, "#define MN_%s ", str);
1930 free (str);
1931 str = mkident (next);
1932 fprintf (fp, "(MN_%s + %zu)\n", str, l1 - l);
1934 else
1936 fprintf (table, " \"\\0\"\"%s\"\n", name);
1937 fprintf (fp, "#define MN_%s %#x\n", str, offs + 1);
1938 offs += strlen (name) + 1;
1939 free (str);
1940 str = NULL;
1942 l = l1;
1945 fprintf (table, " \"\\0\"\".insn\"\n");
1946 fprintf (fp, "#define MN__insn %#x\n", offs + 1);
1948 fprintf (table, ";\n");
1950 fclose (fp);
1953 static void
1954 process_i386_registers (FILE *table)
1956 FILE *fp;
1957 char buf[2048];
1958 char *str, *p, *last;
1959 char *reg_name, *reg_type, *reg_flags, *reg_num;
1960 char *dw2_32_num, *dw2_64_num;
1961 int lineno = 0;
1963 filename = "i386-reg.tbl";
1964 fp = fopen (filename, "r");
1965 if (fp == NULL)
1966 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1967 xstrerror (errno));
1969 fprintf (table, "\n/* i386 register table. */\n\n");
1970 fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
1972 while (!feof (fp))
1974 if (fgets (buf, sizeof (buf), fp) == NULL)
1975 break;
1977 lineno++;
1979 p = remove_leading_whitespaces (buf);
1981 /* Skip comments. */
1982 str = strstr (p, "//");
1983 if (str != NULL)
1984 str[0] = '\0';
1986 /* Remove trailing white spaces. */
1987 remove_trailing_whitespaces (p);
1989 switch (p[0])
1991 case '#':
1992 fprintf (table, "%s\n", p);
1993 case '\0':
1994 continue;
1995 break;
1996 default:
1997 break;
2000 last = p + strlen (p);
2002 /* Find reg_name. */
2003 reg_name = next_field (p, ',', &str, last);
2005 /* Find reg_type. */
2006 reg_type = next_field (str, ',', &str, last);
2008 /* Find reg_flags. */
2009 reg_flags = next_field (str, ',', &str, last);
2011 /* Find reg_num. */
2012 reg_num = next_field (str, ',', &str, last);
2014 fprintf (table, " { \"%s\",\n ", reg_name);
2016 process_i386_operand_type (table, reg_type, stage_registers, "\t",
2017 lineno);
2019 /* Find 32-bit Dwarf2 register number. */
2020 dw2_32_num = next_field (str, ',', &str, last);
2022 /* Find 64-bit Dwarf2 register number. */
2023 dw2_64_num = next_field (str, ',', &str, last);
2025 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
2026 reg_flags, reg_num, dw2_32_num, dw2_64_num);
2029 fclose (fp);
2031 fprintf (table, "};\n");
2033 fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2036 static void
2037 process_i386_initializers (void)
2039 unsigned int i;
2040 FILE *fp = fopen ("i386-init.h", "w");
2042 if (fp == NULL)
2043 fail ("can't create i386-init.h, errno = %s\n",
2044 xstrerror (errno));
2046 process_copyright (fp);
2048 for (i = 0; i < CpuMax; i++)
2049 process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i);
2051 for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++)
2053 char *deps = xstrdup (isa_dependencies[i].deps);
2055 process_i386_cpu_flag (fp, deps, isa_dependencies[i].name,
2056 "", " ", -1, CpuMax);
2057 free (deps);
2060 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
2061 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
2062 one to 387. We want the reverse to be true though: Disabling 8087 also
2063 is to disable 287+ and later; disabling 287 also means disabling 387+. */
2064 memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387],
2065 sizeof (isa_reverse_deps[0]));
2066 isa_reverse_deps[Cpu287][Cpu387] = 1;
2067 memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287],
2068 sizeof (isa_reverse_deps[0]));
2069 isa_reverse_deps[Cpu8087][Cpu287] = 1;
2071 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
2072 lead to disabling of anything else. */
2073 memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0]));
2075 for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++)
2077 size_t len;
2078 char *upper;
2080 if (memchr(isa_reverse_deps[i], 1,
2081 ARRAY_SIZE (isa_reverse_deps[0])) == NULL)
2082 continue;
2084 isa_reverse_deps[i][i] = 1;
2085 process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i);
2088 fprintf (fp, "\n");
2090 fclose (fp);
2093 /* Program options. */
2094 #define OPTION_SRCDIR 200
2096 struct option long_options[] =
2098 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2099 {"debug", no_argument, NULL, 'd'},
2100 {"version", no_argument, NULL, 'V'},
2101 {"help", no_argument, NULL, 'h'},
2102 {0, no_argument, NULL, 0}
2105 static void
2106 print_version (void)
2108 printf ("%s: version 1.0\n", program_name);
2109 xexit (0);
2112 static void
2113 usage (FILE * stream, int status)
2115 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2116 program_name);
2117 xexit (status);
2121 main (int argc, char **argv)
2123 extern int chdir (char *);
2124 char *srcdir = NULL;
2125 int c;
2126 unsigned int i, cpumax;
2127 FILE *table;
2129 program_name = *argv;
2130 xmalloc_set_program_name (program_name);
2132 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2133 switch (c)
2135 case OPTION_SRCDIR:
2136 srcdir = optarg;
2137 break;
2138 case 'V':
2139 case 'v':
2140 print_version ();
2141 break;
2142 case 'd':
2143 debug = 1;
2144 break;
2145 case 'h':
2146 case '?':
2147 usage (stderr, 0);
2148 default:
2149 case 0:
2150 break;
2153 if (optind != argc)
2154 usage (stdout, 1);
2156 if (srcdir != NULL)
2157 if (chdir (srcdir) != 0)
2158 fail ("unable to change directory to \"%s\", errno = %s\n",
2159 srcdir, xstrerror (errno));
2161 /* cpu_flags isn't sorted by position. */
2162 cpumax = 0;
2163 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2164 if (cpu_flags[i].position > cpumax)
2165 cpumax = cpu_flags[i].position;
2167 /* Check the unused bitfield in i386_cpu_flags. */
2168 #ifdef CpuUnused
2169 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2171 if ((cpumax - 1) != CpuMax)
2172 fail ("CpuMax != %d!\n", cpumax);
2173 #else
2174 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2176 if (cpumax != CpuMax)
2177 fail ("CpuMax != %d!\n", cpumax);
2179 c = CpuNumOfBits - CpuMax - 1;
2180 if (c)
2181 fail ("%d unused bits in i386_cpu_flags.\n", c);
2182 #endif
2184 /* If this triggers, CpuIsaBits needs to be increased. */
2185 static_assert (CpuAttrEnums <= (1u << CpuIsaBits));
2187 /* Check the unused bitfield in i386_cpu_attr. */
2188 #ifndef CpuAttrUnused
2189 c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums);
2190 if (c)
2191 fail ("%d unused bits in i386_cpu_attr.\n", c);
2192 #endif
2194 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2196 /* Check the unused bitfield in i386_operand_type. */
2197 #ifdef OTUnused
2198 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2199 == OTNum + 1);
2200 #else
2201 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2202 == OTNum);
2204 c = OTNumOfBits - OTNum;
2205 if (c)
2206 fail ("%d unused bits in i386_operand_type.\n", c);
2207 #endif
2209 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2210 compare);
2212 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2213 sizeof (opcode_modifiers [0]), compare);
2215 qsort (operand_types, ARRAY_SIZE (operand_types),
2216 sizeof (operand_types [0]), compare);
2218 process_i386_initializers ();
2220 table = fopen ("i386-tbl.h", "w");
2221 if (table == NULL)
2222 fail ("can't create i386-tbl.h, errno = %s\n",
2223 xstrerror (errno));
2225 process_copyright (table);
2227 process_i386_opcodes (table);
2228 process_i386_registers (table);
2230 fclose (table);
2232 exit (0);