1 /* Copyright (C) 2007-2024 Free Software Foundation, Inc.
2
3 This file is part of the GNU opcodes library.
4
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.
9
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.
14
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. */
19
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"
28
29 #include "i386-opc.h"
30
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); }))
34
35 static const char *program_name = NULL;
36 static int debug = 0;
37
38 typedef struct dependency
39 {
40 const char *name;
41 /* Note: Only direct dependencies should be enumerated. */
42 const char *deps;
43 } dependency;
44
45 static const dependency isa_dependencies[] =
46 {
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 { "ZNVER5",
98 "ZNVER4|AVX_VNNI|MOVDIRI|MOVDIR64B|AVX512_VP2INTERSECT|PREFETCHI" },
99 { "BTVER1",
100 "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" },
101 { "BTVER2",
102 "BTVER1|AVX|BMI|F16C|AES|PCLMULQDQ|Movbe|Xsaveopt|PRFCHW" },
103 { "286",
104 "186" },
105 { "386",
106 "286" },
107 { "486",
108 "386" },
109 { "586",
110 "486|387" },
111 { "586:nofpu",
112 "486" },
113 { "686",
114 "586|687|CMOV|FXSR" },
115 { "686:min",
116 "586|687" },
117 { "687",
118 "387" },
119 { "FISTTP",
120 "687" },
121 { "SSE",
122 "FXSR" },
123 { "SSE2",
124 "SSE" },
125 { "SSE3",
126 "SSE2" },
127 { "SSSE3",
128 "SSE3" },
129 { "SSE4_1",
130 "SSSE3" },
131 { "SSE4_2",
132 "SSE4_1|POPCNT" },
133 { "Xsaveopt",
134 "XSAVE" },
135 { "AES",
136 "SSE2" },
137 { "PCLMULQDQ",
138 "SSE2" },
139 { "FMA",
140 "AVX" },
141 { "FMA4",
142 "AVX" },
143 { "XOP",
144 "SSE4A|FMA4" },
145 { "LWP",
146 "XSAVE" },
147 { "F16C",
148 "AVX" },
149 { "3dnow",
150 "MMX" },
151 { "3dnowA",
152 "3dnow" },
153 { "SSE4a",
154 "SSE3" },
155 { "ABM",
156 "LZCNT|POPCNT" },
157 { "AVX",
158 "SSE4_2|XSAVE" },
159 { "AVX2",
160 "AVX" },
161 { "AVX_VNNI",
162 "AVX2" },
163 { "AVX_IFMA",
164 "AVX2" },
165 { "AVX_VNNI_INT8",
166 "AVX2" },
167 { "AVX_VNNI_INT16",
168 "AVX2" },
169 { "AVX_NE_CONVERT",
170 "AVX2" },
171 { "CX16",
172 "64" },
173 { "LKGS",
174 "64" },
175 { "FRED",
176 "LKGS" },
177 { "AVX512F",
178 "AVX2" },
179 { "AVX512CD",
180 "AVX512F" },
181 { "AVX512ER",
182 "AVX512F" },
183 { "AVX512PF",
184 "AVX512F" },
185 { "AVX512DQ",
186 "AVX512F" },
187 { "AVX512BW",
188 "AVX512F" },
189 { "AVX512VL",
190 "AVX512F" },
191 { "AVX512IFMA",
192 "AVX512F" },
193 { "AVX512VBMI",
194 "AVX512BW" },
195 { "AVX512_4FMAPS",
196 "AVX512F" },
197 { "AVX512_4VNNIW",
198 "AVX512F" },
199 { "AVX512_VPOPCNTDQ",
200 "AVX512F" },
201 { "AVX512_VBMI2",
202 "AVX512BW" },
203 { "AVX512_VNNI",
204 "AVX512F" },
205 { "AVX512_BITALG",
206 "AVX512BW" },
207 { "AVX512_VP2INTERSECT",
208 "AVX512F" },
209 { "AVX512_BF16",
210 "AVX512BW" },
211 { "AVX512_FP16",
212 "AVX512BW" },
213 { "IAMCU",
214 "586:nofpu" },
215 { "EPT",
216 "VMX" },
217 { "VMFUNC",
218 "VMX" },
219 { "MPX",
220 "XSAVE" },
221 { "SHA",
222 "SSE2" },
223 { "SHA512",
224 "AVX2" },
225 { "SM3",
226 "AVX" },
227 { "SM4",
228 "AVX2" },
229 { "XSAVES",
230 "XSAVEC" },
231 { "XSAVEC",
232 "XSAVE" },
233 { "OSPKE",
234 "XSAVE" },
235 { "GFNI",
236 "SSE2" },
237 { "VAES",
238 "AVX2|AES" },
239 { "VPCLMULQDQ",
240 "AVX2|PCLMULQDQ" },
241 { "AVX10_1",
242 "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA"
243 "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" },
244 { "SEV_ES",
245 "SVME" },
246 { "SNP",
247 "SEV_ES" },
248 { "RMPQUERY",
249 "SNP|64" },
250 { "TSX",
251 "RTM|HLE" },
252 { "TSXLDTRK",
253 "RTM" },
254 { "AMX_TILE",
255 "XSAVE|64" },
256 { "AMX_INT8",
257 "AMX_TILE" },
258 { "AMX_BF16",
259 "AMX_TILE" },
260 { "AMX_FP16",
261 "AMX_TILE" },
262 { "AMX_COMPLEX",
263 "AMX_TILE" },
264 { "KL",
265 "SSE2" },
266 { "WIDEKL",
267 "KL" },
268 { "PBNDKB",
269 "64" },
270 { "UINTR",
271 "64" },
272 { "PREFETCHI",
273 "64" },
274 { "CMPCCXADD",
275 "64" },
276 { "MSRLIST",
277 "64" },
278 { "USER_MSR",
279 "64" },
280 { "APX_F",
281 "XSAVE|64" },
282 };
283
284 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
285 static unsigned char isa_reverse_deps[CpuMax][CpuMax];
286
287 typedef struct bitfield
288 {
289 int position;
290 int value;
291 const char *name;
292 } bitfield;
293
294 #define BITFIELD(n) { Cpu##n, 0, #n }
295
296 static bitfield cpu_flags[] =
297 {
298 BITFIELD (186),
299 BITFIELD (286),
300 BITFIELD (386),
301 BITFIELD (486),
302 BITFIELD (586),
303 BITFIELD (686),
304 BITFIELD (CMOV),
305 BITFIELD (FXSR),
306 BITFIELD (Clflush),
307 BITFIELD (Nop),
308 BITFIELD (SYSCALL),
309 BITFIELD (8087),
310 BITFIELD (287),
311 BITFIELD (387),
312 BITFIELD (687),
313 BITFIELD (FISTTP),
314 BITFIELD (MMX),
315 BITFIELD (SSE),
316 BITFIELD (SSE2),
317 BITFIELD (SSE3),
318 BITFIELD (SSSE3),
319 BITFIELD (SSE4_1),
320 BITFIELD (SSE4_2),
321 BITFIELD (AVX),
322 BITFIELD (AVX2),
323 BITFIELD (AVX512F),
324 BITFIELD (AVX512CD),
325 BITFIELD (AVX512ER),
326 BITFIELD (AVX512PF),
327 BITFIELD (AVX512VL),
328 BITFIELD (AVX512DQ),
329 BITFIELD (AVX512BW),
330 BITFIELD (IAMCU),
331 BITFIELD (SSE4a),
332 BITFIELD (3dnow),
333 BITFIELD (3dnowA),
334 BITFIELD (PadLock),
335 BITFIELD (SVME),
336 BITFIELD (VMX),
337 BITFIELD (SMX),
338 BITFIELD (Xsave),
339 BITFIELD (Xsaveopt),
340 BITFIELD (AES),
341 BITFIELD (PCLMULQDQ),
342 BITFIELD (FMA),
343 BITFIELD (FMA4),
344 BITFIELD (XOP),
345 BITFIELD (LWP),
346 BITFIELD (BMI),
347 BITFIELD (TBM),
348 BITFIELD (Movbe),
349 BITFIELD (CX16),
350 BITFIELD (LAHF_SAHF),
351 BITFIELD (EPT),
352 BITFIELD (Rdtscp),
353 BITFIELD (FSGSBase),
354 BITFIELD (RdRnd),
355 BITFIELD (F16C),
356 BITFIELD (BMI2),
357 BITFIELD (LZCNT),
358 BITFIELD (POPCNT),
359 BITFIELD (MONITOR),
360 BITFIELD (HLE),
361 BITFIELD (RTM),
362 BITFIELD (INVPCID),
363 BITFIELD (VMFUNC),
364 BITFIELD (RDSEED),
365 BITFIELD (ADX),
366 BITFIELD (PRFCHW),
367 BITFIELD (SMAP),
368 BITFIELD (SHA),
369 BITFIELD (SHA512),
370 BITFIELD (SM3),
371 BITFIELD (SM4),
372 BITFIELD (ClflushOpt),
373 BITFIELD (XSAVES),
374 BITFIELD (XSAVEC),
375 BITFIELD (PREFETCHWT1),
376 BITFIELD (SE1),
377 BITFIELD (CLWB),
378 BITFIELD (MPX),
379 BITFIELD (AVX512IFMA),
380 BITFIELD (AVX512VBMI),
381 BITFIELD (AVX512_4FMAPS),
382 BITFIELD (AVX512_4VNNIW),
383 BITFIELD (AVX512_VPOPCNTDQ),
384 BITFIELD (AVX512_VBMI2),
385 BITFIELD (AVX512_VNNI),
386 BITFIELD (AVX512_BITALG),
387 BITFIELD (AVX512_BF16),
388 BITFIELD (AVX512_VP2INTERSECT),
389 BITFIELD (TDX),
390 BITFIELD (AVX_VNNI),
391 BITFIELD (AVX512_FP16),
392 BITFIELD (PREFETCHI),
393 BITFIELD (AVX_IFMA),
394 BITFIELD (AVX_VNNI_INT8),
395 BITFIELD (AVX_VNNI_INT16),
396 BITFIELD (CMPCCXADD),
397 BITFIELD (WRMSRNS),
398 BITFIELD (MSRLIST),
399 BITFIELD (AVX_NE_CONVERT),
400 BITFIELD (RAO_INT),
401 BITFIELD (FRED),
402 BITFIELD (LKGS),
403 BITFIELD (USER_MSR),
404 BITFIELD (APX_F),
405 BITFIELD (MWAITX),
406 BITFIELD (CLZERO),
407 BITFIELD (OSPKE),
408 BITFIELD (RDPID),
409 BITFIELD (PTWRITE),
410 BITFIELD (IBT),
411 BITFIELD (SHSTK),
412 BITFIELD (GFNI),
413 BITFIELD (VAES),
414 BITFIELD (VPCLMULQDQ),
415 BITFIELD (WBNOINVD),
416 BITFIELD (PCONFIG),
417 BITFIELD (PBNDKB),
418 BITFIELD (WAITPKG),
419 BITFIELD (UINTR),
420 BITFIELD (CLDEMOTE),
421 BITFIELD (AMX_INT8),
422 BITFIELD (AMX_BF16),
423 BITFIELD (AMX_FP16),
424 BITFIELD (AMX_COMPLEX),
425 BITFIELD (AMX_TILE),
426 BITFIELD (MOVDIRI),
427 BITFIELD (MOVDIR64B),
428 BITFIELD (ENQCMD),
429 BITFIELD (SERIALIZE),
430 BITFIELD (RDPRU),
431 BITFIELD (MCOMMIT),
432 BITFIELD (SEV_ES),
433 BITFIELD (TSXLDTRK),
434 BITFIELD (KL),
435 BITFIELD (WideKL),
436 BITFIELD (HRESET),
437 BITFIELD (INVLPGB),
438 BITFIELD (TLBSYNC),
439 BITFIELD (SNP),
440 BITFIELD (RMPQUERY),
441 BITFIELD (64),
442 BITFIELD (No64),
443 #ifdef CpuUnused
444 BITFIELD (Unused),
445 #endif
446 };
447
448 #undef BITFIELD
449 #define BITFIELD(n) { n, 0, #n }
450
451 static bitfield opcode_modifiers[] =
452 {
453 BITFIELD (D),
454 BITFIELD (W),
455 BITFIELD (Load),
456 BITFIELD (Modrm),
457 BITFIELD (Jump),
458 BITFIELD (FloatMF),
459 BITFIELD (Size),
460 BITFIELD (CheckOperandSize),
461 BITFIELD (OperandConstraint),
462 BITFIELD (MnemonicSize),
463 BITFIELD (No_bSuf),
464 BITFIELD (No_wSuf),
465 BITFIELD (No_lSuf),
466 BITFIELD (No_sSuf),
467 BITFIELD (No_qSuf),
468 BITFIELD (FWait),
469 BITFIELD (IsString),
470 BITFIELD (RegMem),
471 BITFIELD (BNDPrefixOk),
472 BITFIELD (PrefixOk),
473 BITFIELD (IsPrefix),
474 BITFIELD (ImmExt),
475 BITFIELD (NoRex64),
476 BITFIELD (Vex),
477 BITFIELD (VexVVVV),
478 BITFIELD (VexW),
479 BITFIELD (OpcodePrefix),
480 BITFIELD (SIB),
481 BITFIELD (SSE2AVX),
482 BITFIELD (EVex),
483 BITFIELD (Masking),
484 BITFIELD (Broadcast),
485 BITFIELD (StaticRounding),
486 BITFIELD (SAE),
487 BITFIELD (Disp8MemShift),
488 BITFIELD (Optimize),
489 BITFIELD (Dialect),
490 BITFIELD (ISA64),
491 BITFIELD (NoEgpr),
492 BITFIELD (NF),
493 BITFIELD (Rex2),
494 };
495
496 #define CLASS(n) #n, n
497
498 static const struct {
499 const char *name;
500 enum operand_class value;
501 } operand_classes[] = {
502 CLASS (Reg),
503 CLASS (SReg),
504 CLASS (RegCR),
505 CLASS (RegDR),
506 CLASS (RegTR),
507 CLASS (RegMMX),
508 CLASS (RegSIMD),
509 CLASS (RegMask),
510 CLASS (RegBND),
511 };
512
513 #undef CLASS
514
515 #define INSTANCE(n) #n, n
516
517 static const struct {
518 const char *name;
519 enum operand_instance value;
520 } operand_instances[] = {
521 INSTANCE (Accum),
522 INSTANCE (RegC),
523 INSTANCE (RegD),
524 INSTANCE (RegB),
525 };
526
527 #undef INSTANCE
528
529 static bitfield operand_types[] =
530 {
531 BITFIELD (Imm1),
532 BITFIELD (Imm8),
533 BITFIELD (Imm8S),
534 BITFIELD (Imm16),
535 BITFIELD (Imm32),
536 BITFIELD (Imm32S),
537 BITFIELD (Imm64),
538 BITFIELD (BaseIndex),
539 BITFIELD (Disp8),
540 BITFIELD (Disp16),
541 BITFIELD (Disp32),
542 BITFIELD (Disp64),
543 BITFIELD (Byte),
544 BITFIELD (Word),
545 BITFIELD (Dword),
546 BITFIELD (Fword),
547 BITFIELD (Qword),
548 BITFIELD (Tbyte),
549 BITFIELD (Xmmword),
550 BITFIELD (Ymmword),
551 BITFIELD (Zmmword),
552 BITFIELD (Tmmword),
553 BITFIELD (Unspecified),
554 #ifdef OTUnused
555 BITFIELD (OTUnused),
556 #endif
557 };
558
559 static const char *filename;
560 static i386_cpu_flags active_cpu_flags;
561 static int active_isstring;
562
563 struct template_arg {
564 const struct template_arg *next;
565 const char *val;
566 };
567
568 struct template_instance {
569 const struct template_instance *next;
570 const char *name;
571 const struct template_arg *args;
572 };
573
574 struct template_param {
575 const struct template_param *next;
576 const char *name;
577 };
578
579 struct template {
580 struct template *next;
581 const char *name;
582 const struct template_instance *instances;
583 const struct template_param *params;
584 };
585
586 static struct template *templates;
587
588 static int
compare(const void * x,const void * y)589 compare (const void *x, const void *y)
590 {
591 const bitfield *xp = (const bitfield *) x;
592 const bitfield *yp = (const bitfield *) y;
593 return xp->position - yp->position;
594 }
595
596 static void
fail(const char * message,...)597 fail (const char *message, ...)
598 {
599 va_list args;
600
601 va_start (args, message);
602 fprintf (stderr, "%s: error: ", program_name);
603 vfprintf (stderr, message, args);
604 va_end (args);
605 xexit (1);
606 }
607
608 static void
process_copyright(FILE * fp)609 process_copyright (FILE *fp)
610 {
611 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
612 /* Copyright (C) 2007-2024 Free Software Foundation, Inc.\n\
613 \n\
614 This file is part of the GNU opcodes library.\n\
615 \n\
616 This library is free software; you can redistribute it and/or modify\n\
617 it under the terms of the GNU General Public License as published by\n\
618 the Free Software Foundation; either version 3, or (at your option)\n\
619 any later version.\n\
620 \n\
621 It is distributed in the hope that it will be useful, but WITHOUT\n\
622 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
623 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
624 License for more details.\n\
625 \n\
626 You should have received a copy of the GNU General Public License\n\
627 along with this program; if not, write to the Free Software\n\
628 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
629 MA 02110-1301, USA. */\n");
630 }
631
632 /* Remove leading white spaces. */
633
634 static char *
remove_leading_whitespaces(char * str)635 remove_leading_whitespaces (char *str)
636 {
637 while (ISSPACE (*str))
638 str++;
639 return str;
640 }
641
642 /* Remove trailing white spaces. */
643
644 static void
remove_trailing_whitespaces(char * str)645 remove_trailing_whitespaces (char *str)
646 {
647 size_t last = strlen (str);
648
649 if (last == 0)
650 return;
651
652 do
653 {
654 last--;
655 if (ISSPACE (str [last]))
656 str[last] = '\0';
657 else
658 break;
659 }
660 while (last != 0);
661 }
662
663 /* Find next field separated by SEP and terminate it. Return a
664 pointer to the one after it. */
665
666 static char *
next_field(char * str,char sep,char ** next,char * last)667 next_field (char *str, char sep, char **next, char *last)
668 {
669 char *p;
670
671 p = remove_leading_whitespaces (str);
672 for (str = p; *str != sep && *str != '\0'; str++);
673
674 *str = '\0';
675 remove_trailing_whitespaces (p);
676
677 *next = str + 1;
678
679 if (p >= last)
680 abort ();
681
682 return p;
683 }
684
685 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
686
687 static void
set_bitfield(char * f,bitfield * array,int value,unsigned int size,int lineno)688 set_bitfield (char *f, bitfield *array, int value,
689 unsigned int size, int lineno)
690 {
691 unsigned int i;
692
693 /* Ignore empty fields; they may result from template expansions. */
694 if (*f == '\0')
695 return;
696
697 for (i = 0; i < size; i++)
698 if (strcasecmp (array[i].name, f) == 0)
699 {
700 array[i].value = value;
701 return;
702 }
703
704 if (value)
705 {
706 const char *v = strchr (f, '=');
707
708 if (v)
709 {
710 size_t n = v - f;
711 char *end;
712
713 for (i = 0; i < size; i++)
714 if (strncasecmp (array[i].name, f, n) == 0)
715 {
716 value = strtol (v + 1, &end, 0);
717 if (*end == '\0')
718 {
719 array[i].value = value;
720 return;
721 }
722 break;
723 }
724 }
725 }
726
727 if (lineno != -1)
728 fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f);
729 else
730 fail ("unknown bitfield: %s\n", f);
731 }
732
733 static void
add_isa_dependencies(bitfield * flags,const char * f,int value,unsigned int reverse)734 add_isa_dependencies (bitfield *flags, const char *f, int value,
735 unsigned int reverse)
736 {
737 unsigned int i;
738 char *str = NULL;
739 const char *isa = f;
740 static bool is_avx;
741 bool is_isa = false, orig_is_avx = is_avx;
742
743 /* Need to find base entry for references to auxiliary ones. */
744 if (strchr (f, ':'))
745 {
746 str = xstrdup (f);
747 *strchr (str, ':') = '\0';
748 isa = str;
749 }
750 /* isa_dependencies[] prefers "LM" over "64". */
751 else if (!strcmp (f, "LM"))
752 isa = "64";
753 for (i = 0; i < CpuMax; ++i)
754 if (strcasecmp (flags[i].name, isa) == 0)
755 {
756 flags[i].value = value;
757 if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
758 /* Don't record the feature itself here. */
759 && reverse != i
760 /* Don't record base architectures. */
761 && reverse > Cpu686)
762 isa_reverse_deps[i][reverse] = 1;
763 is_isa = true;
764 if (i == CpuAVX || i == CpuXOP || i == CpuVAES || i == CpuVPCLMULQDQ)
765 is_avx = true;
766 break;
767 }
768 free (str);
769
770 /* Do not turn off dependencies. */
771 if (is_isa && !value)
772 {
773 is_avx = orig_is_avx;
774 return;
775 }
776
777 for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i)
778 if (strcasecmp (isa_dependencies[i].name, f) == 0)
779 {
780 char *deps = xstrdup (isa_dependencies[i].deps);
781 char *next = deps;
782 char *last = deps + strlen (deps);
783
784 for (; next && next < last; )
785 {
786 char *str = next_field (next, '|', &next, last);
787
788 /* No AVX/XOP -> SSE reverse dependencies. */
789 if (is_avx && strncmp (str, "SSE", 3) == 0)
790 add_isa_dependencies (flags, str, value, CpuMax);
791 else
792 add_isa_dependencies (flags, str, value, reverse);
793 }
794 free (deps);
795
796 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted,
797 unless the sole dependency is the "64-bit mode only" one. */
798 if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
799 && strcmp (isa_dependencies[i].deps, "64"))
800 isa_reverse_deps[reverse][reverse] = 1;
801
802 is_avx = orig_is_avx;
803 return;
804 }
805
806 if (!is_isa)
807 fail ("unknown bitfield: %s\n", f);
808
809 is_avx = orig_is_avx;
810 }
811
812 static void
output_cpu_flags(FILE * table,bitfield * flags,unsigned int size,int mode,const char * comma,const char * indent,int lineno)813 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
814 int mode, const char *comma, const char *indent, int lineno)
815 {
816 unsigned int i = 0, j = 0;
817
818 if (mode < 0)
819 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
820
821 fprintf (table, "%s{ { ", indent);
822
823 if (mode <= 0)
824 {
825 for (j = ~0u; i < CpuAttrEnums; i++)
826 {
827 if (!flags[i].value)
828 continue;
829
830 if (j < ~0u)
831 fail ("%s: %d: invalid combination of CPU identifiers\n",
832 filename, lineno);
833 j = i;
834 if (mode)
835 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
836 }
837
838 /* Write 0 to indicate "no associated flag". */
839 fprintf (table, "%u, ", j + 1);
840
841 j = 1;
842 }
843
844 for (; i < size - 1; i++, j++)
845 {
846 if (((j + 1) % 20) != 0)
847 fprintf (table, "%d, ", flags[i].value);
848 else
849 fprintf (table, "%d,", flags[i].value);
850 if (((j + 1) % 20) == 0)
851 {
852 /* We need \\ for macro. */
853 if (mode > 0)
854 fprintf (table, " \\\n %s", indent);
855 else
856 fprintf (table, "\n %s", indent);
857 }
858 if (mode < 0 && flags[i].value)
859 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
860 }
861
862 #if defined(CpuAttrUnused) != defined(CpuUnused)
863 if (mode <= 0)
864 # ifdef CpuUnused
865 fprintf (table, " } }%s\n", comma);
866 # else
867 fprintf (table, "%d, 0 } }%s\n", flags[i].value, comma);
868 # endif
869 else
870 #endif
871 fprintf (table, "%d } }%s\n", flags[i].value, comma);
872 }
873
874 static void
process_i386_cpu_flag(FILE * table,char * flag,const char * name,const char * comma,const char * indent,int lineno,unsigned int reverse)875 process_i386_cpu_flag (FILE *table, char *flag,
876 const char *name,
877 const char *comma, const char *indent,
878 int lineno, unsigned int reverse)
879 {
880 char *str, *next = flag, *last;
881 unsigned int i;
882 int value = 1;
883 bool is_isa = false;
884 bitfield all [ARRAY_SIZE (cpu_flags)];
885 bitfield any [ARRAY_SIZE (cpu_flags)];
886
887 /* Copy the default cpu flags. */
888 memcpy (all, cpu_flags, sizeof (cpu_flags));
889 memcpy (any, cpu_flags, sizeof (cpu_flags));
890
891 if (flag == NULL)
892 {
893 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
894 any[i].value = isa_reverse_deps[reverse][i];
895 goto output;
896 }
897
898 if (flag[0] == '~')
899 {
900 last = flag + strlen (flag);
901
902 if (flag[1] == '(')
903 {
904 last -= 1;
905 next = flag + 2;
906 if (*last != ')')
907 fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
908 lineno, flag);
909 *last = '\0';
910 }
911 else
912 next = flag + 1;
913
914 /* First we turn on everything except for cpuno64 and - if
915 present - the padding field. */
916 for (i = 0; i < ARRAY_SIZE (any); i++)
917 if (any[i].position < CpuNo64)
918 any[i].value = 1;
919
920 /* Turn off selective bits. */
921 value = 0;
922 }
923
924 if (name != NULL && value != 0)
925 {
926 for (i = 0; i < ARRAY_SIZE (any); i++)
927 if (strcasecmp (any[i].name, name) == 0)
928 {
929 add_isa_dependencies (any, name, 1, reverse);
930 is_isa = true;
931 break;
932 }
933 }
934
935 if (strcmp (flag, "0"))
936 {
937 bool combined = false;
938
939 if (is_isa)
940 return;
941
942 /* Turn on/off selective bits. */
943 last = flag + strlen (flag);
944 if (name == NULL && strchr (flag, '&'))
945 {
946 for (; next < last && *next != '('; )
947 {
948 str = next_field (next, '&', &next, last);
949 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
950 }
951 if (*next == '(')
952 {
953 if (*--last != ')')
954 fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
955 lineno, flag);
956 ++next;
957 *last = '\0';
958 }
959 combined = true;
960 }
961 for (; next && next < last; )
962 {
963 str = next_field (next, '|', &next, last);
964 if (name)
965 add_isa_dependencies (any, str, value, reverse);
966 else if (combined || next < last)
967 set_bitfield (str, any, value, ARRAY_SIZE (any), lineno);
968 else /* Singular specifiers go into "all". */
969 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno);
970 combined = true;
971 }
972 }
973
974 output:
975 if (name != NULL)
976 {
977 size_t len = strlen (name);
978 char *upper = xmalloc (len + 1);
979
980 /* Cpu64 is special: It specifies a mode dependency, not an ISA one. Zap
981 the flag from ISA initializer macros (and from CPU_ANY_64_FLAGS
982 itself we only care about tracking its dependents. Also don't emit the
983 (otherwise all zero) CPU_64_FLAGS. */
984 if (flag != NULL && reverse == Cpu64)
985 return;
986 if (is_isa || flag == NULL)
987 any[Cpu64].value = 0;
988
989 for (i = 0; i < len; ++i)
990 {
991 /* Don't emit #define-s for auxiliary entries. */
992 if (name[i] == ':')
993 return;
994 upper[i] = TOUPPER (name[i]);
995 }
996 upper[i] = '\0';
997 fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n",
998 flag != NULL ? "": "ANY_", upper);
999 free (upper);
1000 }
1001 else
1002 {
1003 /* Synthesize "64-bit mode only" dependencies from the dependencies we
1004 have accumulated. */
1005 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
1006 if (all[i].value && isa_reverse_deps[Cpu64][i])
1007 all[Cpu64].value = 1;
1008
1009 output_cpu_flags(table, all, ARRAY_SIZE (all), -1, comma, indent, lineno);
1010 }
1011
1012 output_cpu_flags (table, any, ARRAY_SIZE (any), name != NULL,
1013 comma, indent, lineno);
1014 }
1015
1016 static void
output_opcode_modifier(FILE * table,bitfield * modifier,unsigned int size)1017 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1018 {
1019 unsigned int i;
1020
1021 fprintf (table, " { ");
1022
1023 for (i = 0; i < size - 1; i++)
1024 {
1025 if (((i + 1) % 20) != 0)
1026 fprintf (table, "%d, ", modifier[i].value);
1027 else
1028 fprintf (table, "%d,", modifier[i].value);
1029 if (((i + 1) % 20) == 0)
1030 fprintf (table, "\n ");
1031 }
1032
1033 fprintf (table, "%d },\n", modifier[i].value);
1034 }
1035
1036 /* Returns LOG2 of element size. */
1037 static int
get_element_size(char ** opnd,int lineno)1038 get_element_size (char **opnd, int lineno)
1039 {
1040 char *str, *next, *last, *op;
1041 const char *full = opnd[0];
1042 int elem_size = INT_MAX;
1043
1044 /* Find the memory operand. */
1045 while (full != NULL && strstr(full, "BaseIndex") == NULL)
1046 full = *++opnd;
1047 if (full == NULL)
1048 fail ("%s: %d: no memory operand\n", filename, lineno);
1049
1050 op = xstrdup (full);
1051 last = op + strlen (op);
1052 for (next = op; next && next < last; )
1053 {
1054 str = next_field (next, '|', &next, last);
1055 if (str)
1056 {
1057 if (strcasecmp(str, "Byte") == 0)
1058 {
1059 /* The smallest element size, no need to check
1060 further. */
1061 elem_size = 0;
1062 break;
1063 }
1064 else if (strcasecmp(str, "Word") == 0)
1065 {
1066 if (elem_size > 1)
1067 elem_size = 1;
1068 }
1069 else if (strcasecmp(str, "Dword") == 0)
1070 {
1071 if (elem_size > 2)
1072 elem_size = 2;
1073 }
1074 else if (strcasecmp(str, "Qword") == 0)
1075 {
1076 if (elem_size > 3)
1077 elem_size = 3;
1078 }
1079 }
1080 }
1081 free (op);
1082
1083 if (elem_size == INT_MAX)
1084 fail ("%s: %d: unknown element size: %s\n", filename, lineno, full);
1085
1086 return elem_size;
1087 }
1088
1089 static bool
rex2_disallowed(const unsigned long long opcode,unsigned int length,unsigned int space,const char * cpu_flags)1090 rex2_disallowed (const unsigned long long opcode, unsigned int length,
1091 unsigned int space, const char *cpu_flags)
1092 {
1093 /* Some opcodes encode a ModR/M-like byte directly in the opcode. */
1094 unsigned int base_opcode = opcode >> (8 * length - 8);
1095
1096 /* All opcodes listed map0 0x4*, 0x7*, 0xa*, 0xe* and map1 0x3*, 0x8*
1097 are reserved under REX2 and triggers #UD when prefixed with REX2 */
1098 if (space == 0)
1099 switch (base_opcode >> 4)
1100 {
1101 case 0x4:
1102 case 0x7:
1103 case 0xA:
1104 case 0xE:
1105 return true;
1106 default:
1107 return false;
1108 }
1109
1110 if (space == SPACE_0F)
1111 switch (base_opcode >> 4)
1112 {
1113 case 0x3:
1114 case 0x8:
1115 return true;
1116 default:
1117 return false;
1118 }
1119
1120 return false;
1121 }
1122
1123 static void
process_i386_opcode_modifier(FILE * table,char * mod,unsigned int space,unsigned int prefix,const char * extension_opcode,char ** opnd,int lineno,bool rex2_disallowed)1124 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1125 unsigned int prefix, const char *extension_opcode,
1126 char **opnd, int lineno, bool rex2_disallowed)
1127 {
1128 char *str, *next, *last;
1129 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1130 static const char *const spaces[] = {
1131 #define SPACE(n) [SPACE_##n] = #n
1132 SPACE(BASE),
1133 SPACE(0F),
1134 SPACE(0F38),
1135 SPACE(0F3A),
1136 SPACE(EVEXMAP4),
1137 SPACE(EVEXMAP5),
1138 SPACE(EVEXMAP6),
1139 SPACE(VEXMAP7),
1140 SPACE(XOP08),
1141 SPACE(XOP09),
1142 SPACE(XOP0A),
1143 #undef SPACE
1144 };
1145
1146 active_isstring = 0;
1147
1148 /* Copy the default opcode modifier. */
1149 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1150
1151 if (strcmp (mod, "0"))
1152 {
1153 unsigned int have_w = 0, bwlq_suf = 0xf;
1154
1155 last = mod + strlen (mod);
1156 for (next = mod; next && next < last; )
1157 {
1158 str = next_field (next, '|', &next, last);
1159 if (str)
1160 {
1161 int val = 1;
1162
1163 if (strncmp(str, "OpcodeSpace", 11) == 0)
1164 {
1165 char *end;
1166
1167 if (str[11] != '=')
1168 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1169 filename, lineno);
1170
1171 val = strtol (str + 12, &end, 0);
1172 if (*end)
1173 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1174 filename, lineno, end);
1175
1176 if (space)
1177 {
1178 if (val != space)
1179 fail ("%s:%d: Conflicting opcode space specifications\n",
1180 filename, lineno);
1181 fprintf (stderr,
1182 "%s:%d: Warning: redundant opcode space specification\n",
1183 filename, lineno);
1184 }
1185
1186 space = val;
1187 continue;
1188 }
1189
1190 if (strcasecmp(str, "Broadcast") == 0)
1191 val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1192 else if (strcasecmp(str, "Disp8MemShift") == 0)
1193 val = get_element_size (opnd, lineno);
1194
1195 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1196 lineno);
1197 if (strcasecmp(str, "IsString") == 0)
1198 active_isstring = 1;
1199
1200 if (strcasecmp(str, "W") == 0)
1201 have_w = 1;
1202
1203 if (strcasecmp(str, "No_bSuf") == 0)
1204 bwlq_suf &= ~1;
1205 if (strcasecmp(str, "No_wSuf") == 0)
1206 bwlq_suf &= ~2;
1207 if (strcasecmp(str, "No_lSuf") == 0)
1208 bwlq_suf &= ~4;
1209 if (strcasecmp(str, "No_qSuf") == 0)
1210 bwlq_suf &= ~8;
1211 }
1212 }
1213
1214 if (prefix)
1215 {
1216 if (!modifiers[OpcodePrefix].value)
1217 modifiers[OpcodePrefix].value = prefix;
1218 else if (modifiers[OpcodePrefix].value != prefix)
1219 fail ("%s:%d: Conflicting prefix specifications\n",
1220 filename, lineno);
1221 else
1222 fprintf (stderr,
1223 "%s:%d: Warning: redundant prefix specification\n",
1224 filename, lineno);
1225 }
1226
1227 if (have_w && !bwlq_suf)
1228 fail ("%s: %d: stray W modifier\n", filename, lineno);
1229 if (have_w && !(bwlq_suf & 1))
1230 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1231 filename, lineno);
1232 if (have_w && !(bwlq_suf & ~1))
1233 fprintf (stderr,
1234 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1235 filename, lineno);
1236 }
1237
1238 if (space >= ARRAY_SIZE (spaces) || !spaces[space])
1239 fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
1240
1241 fprintf (table, " SPACE_%s, %s,\n",
1242 spaces[space], extension_opcode ? extension_opcode : "None");
1243
1244 /* Rather than evaluating multiple conditions at runtime to determine
1245 whether an EVEX encoding is being dealt with, derive that information
1246 right here. A missing EVex attribute means "dynamic". */
1247 if (!modifiers[EVex].value
1248 && (modifiers[Disp8MemShift].value
1249 || modifiers[Broadcast].value
1250 || modifiers[Masking].value
1251 || modifiers[SAE].value))
1252 modifiers[EVex].value = EVEXDYN;
1253
1254 /* Vex, legacy map2 and map3 and rex2_disallowed do not support EGPR.
1255 For templates supporting both Vex and EVex allowing EGPR. */
1256 if ((modifiers[Vex].value || space > SPACE_0F || rex2_disallowed)
1257 && !modifiers[EVex].value)
1258 modifiers[NoEgpr].value = 1;
1259
1260 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1261 }
1262
1263 enum stage {
1264 stage_macros,
1265 stage_opcodes,
1266 stage_registers,
1267 };
1268
1269 static void
output_operand_type(FILE * table,enum operand_class class,enum operand_instance instance,const bitfield * types,unsigned int size,enum stage stage,const char * indent)1270 output_operand_type (FILE *table, enum operand_class class,
1271 enum operand_instance instance,
1272 const bitfield *types, unsigned int size,
1273 enum stage stage, const char *indent)
1274 {
1275 unsigned int i;
1276
1277 fprintf (table, "{ { %d, %d, ", class, instance);
1278
1279 for (i = 0; i < size - 1; i++)
1280 {
1281 if (((i + 3) % 20) != 0)
1282 fprintf (table, "%d, ", types[i].value);
1283 else
1284 fprintf (table, "%d,", types[i].value);
1285 if (((i + 3) % 20) == 0)
1286 {
1287 /* We need \\ for macro. */
1288 if (stage == stage_macros)
1289 fprintf (table, " \\\n%s", indent);
1290 else
1291 fprintf (table, "\n%s", indent);
1292 }
1293 }
1294
1295 fprintf (table, "%d } }", types[i].value);
1296 }
1297
1298 static void
process_i386_operand_type(FILE * table,char * op,enum stage stage,const char * indent,int lineno)1299 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1300 const char *indent, int lineno)
1301 {
1302 char *str, *next, *last;
1303 enum operand_class class = ClassNone;
1304 enum operand_instance instance = InstanceNone;
1305 bitfield types [ARRAY_SIZE (operand_types)];
1306
1307 /* Copy the default operand type. */
1308 memcpy (types, operand_types, sizeof (types));
1309
1310 if (strcmp (op, "0"))
1311 {
1312 int baseindex = 0;
1313
1314 last = op + strlen (op);
1315 for (next = op; next && next < last; )
1316 {
1317 str = next_field (next, '|', &next, last);
1318 if (str)
1319 {
1320 unsigned int i;
1321
1322 if (!strncmp(str, "Class=", 6))
1323 {
1324 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1325 if (!strcmp(str + 6, operand_classes[i].name))
1326 {
1327 class = operand_classes[i].value;
1328 str = NULL;
1329 break;
1330 }
1331 }
1332
1333 if (str && !strncmp(str, "Instance=", 9))
1334 {
1335 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1336 if (!strcmp(str + 9, operand_instances[i].name))
1337 {
1338 instance = operand_instances[i].value;
1339 str = NULL;
1340 break;
1341 }
1342 }
1343 }
1344 if (str)
1345 {
1346 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1347 if (strcasecmp(str, "BaseIndex") == 0)
1348 baseindex = 1;
1349 }
1350 }
1351
1352 if (stage == stage_opcodes && baseindex && !active_isstring)
1353 {
1354 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1355 if (!active_cpu_flags.bitfield.cpu64
1356 && !active_cpu_flags.bitfield.cpumpx)
1357 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1358 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1359 }
1360 }
1361 output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1362 stage, indent);
1363 }
1364
mkident(const char * mnem)1365 static char *mkident (const char *mnem)
1366 {
1367 char *ident = xstrdup (mnem), *p = ident;
1368
1369 do
1370 {
1371 if (!ISALNUM (*p))
1372 *p = '_';
1373 }
1374 while (*++p);
1375
1376 return ident;
1377 }
1378
1379 static void
output_i386_opcode(FILE * table,const char * name,char * str,char * last,int lineno)1380 output_i386_opcode (FILE *table, const char *name, char *str,
1381 char *last, int lineno)
1382 {
1383 unsigned int i, length, prefix = 0, space = 0;
1384 char *base_opcode, *extension_opcode, *end, *ident;
1385 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1386 unsigned long long opcode;
1387
1388 /* Find base_opcode. */
1389 base_opcode = next_field (str, ',', &str, last);
1390
1391 /* Find extension_opcode, if any. */
1392 extension_opcode = strchr (base_opcode, '/');
1393 if (extension_opcode)
1394 *extension_opcode++ = '\0';
1395
1396 /* Find cpu_flags. */
1397 cpu_flags = next_field (str, ',', &str, last);
1398
1399 /* Find opcode_modifier. */
1400 opcode_modifier = next_field (str, ',', &str, last);
1401
1402 /* Remove the first {. */
1403 str = remove_leading_whitespaces (str);
1404 if (*str != '{')
1405 abort ();
1406 str = remove_leading_whitespaces (str + 1);
1407 remove_trailing_whitespaces (str);
1408
1409 /* Remove } and trailing white space. */
1410 i = strlen (str);
1411 if (!i || str[i - 1] != '}')
1412 abort ();
1413 str[--i] = '\0';
1414 remove_trailing_whitespaces (str);
1415
1416 if (!*str)
1417 operand_types [i = 0] = NULL;
1418 else
1419 {
1420 last = str + strlen (str);
1421
1422 /* Find operand_types. */
1423 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1424 {
1425 if (str >= last)
1426 {
1427 operand_types [i] = NULL;
1428 break;
1429 }
1430
1431 operand_types [i] = next_field (str, ',', &str, last);
1432 }
1433 }
1434
1435 opcode = strtoull (base_opcode, &end, 0);
1436
1437 /* Determine opcode length. */
1438 for (length = 1; length < 8; ++length)
1439 if (!(opcode >> (8 * length)))
1440 break;
1441
1442 /* Transform prefixes encoded in the opcode into opcode modifier
1443 representation. */
1444 if (length > 1)
1445 {
1446 switch (opcode >> (8 * length - 8))
1447 {
1448 case 0x66: prefix = PREFIX_0X66; break;
1449 case 0xF3: prefix = PREFIX_0XF3; break;
1450 case 0xF2: prefix = PREFIX_0XF2; break;
1451 }
1452
1453 if (prefix)
1454 opcode &= (1ULL << (8 * --length)) - 1;
1455 }
1456
1457 /* Transform opcode space encoded in the opcode into opcode modifier
1458 representation. */
1459 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1460 {
1461 switch ((opcode >> (8 * length - 16)) & 0xff)
1462 {
1463 default: space = SPACE_0F; break;
1464 case 0x38: space = SPACE_0F38; break;
1465 case 0x3A: space = SPACE_0F3A; break;
1466 }
1467
1468 if (space != SPACE_0F && --length == 1)
1469 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1470 filename, lineno, name);
1471 opcode &= (1ULL << (8 * --length)) - 1;
1472 }
1473
1474 if (length > 2)
1475 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1476 filename, lineno, name, 2 * length, opcode);
1477
1478 ident = mkident (name);
1479 fprintf (table, " { MN_%s, 0x%0*llx%s, %u,",
1480 ident, 2 * (int)length, opcode, end, i);
1481 free (ident);
1482
1483 process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1484 extension_opcode, operand_types, lineno,
1485 rex2_disallowed (opcode, length, space,
1486 cpu_flags));
1487
1488 process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax);
1489
1490 fprintf (table, " { ");
1491
1492 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1493 {
1494 if (!operand_types[i])
1495 {
1496 if (i == 0)
1497 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1498 lineno);
1499 break;
1500 }
1501
1502 if (i != 0)
1503 fprintf (table, ",\n ");
1504
1505 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1506 "\t ", lineno);
1507 }
1508 fprintf (table, " } },\n");
1509 }
1510
1511 struct opcode_hash_entry
1512 {
1513 const char *name;
1514 struct opcode_entry
1515 {
1516 struct opcode_entry *next;
1517 char *opcode;
1518 int lineno;
1519 } entry;
1520 };
1521
1522 /* Calculate the hash value of an opcode hash entry P. */
1523
1524 static hashval_t
opcode_hash_hash(const void * p)1525 opcode_hash_hash (const void *p)
1526 {
1527 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1528 return htab_hash_string (entry->name);
1529 }
1530
1531 /* Compare a string Q against an opcode hash entry P. */
1532
1533 static int
opcode_hash_eq(const void * p,const void * q)1534 opcode_hash_eq (const void *p, const void *q)
1535 {
1536 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1537 const char *name = (const char *) q;
1538 return strcmp (name, entry->name) == 0;
1539 }
1540
1541 static void
parse_template(char * buf,int lineno)1542 parse_template (char *buf, int lineno)
1543 {
1544 char sep, *end, *name;
1545 struct template *tmpl;
1546 struct template_instance *last_inst = NULL;
1547
1548 buf = remove_leading_whitespaces (buf + 1);
1549 end = strchr (buf, ':');
1550 if (end == NULL)
1551 {
1552 struct template *prev = NULL;
1553
1554 end = strchr (buf, '>');
1555 if (end == NULL)
1556 fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1557 if (*remove_leading_whitespaces (end + 1))
1558 fail ("%s: %d: malformed template purge\n", filename, lineno);
1559 *end = '\0';
1560 remove_trailing_whitespaces (buf);
1561 /* Don't bother freeing the various structures. */
1562 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1563 if (!strcmp (buf, tmpl->name))
1564 break;
1565 if (tmpl == NULL)
1566 fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1567 if (prev)
1568 prev->next = tmpl->next;
1569 else
1570 templates = tmpl->next;
1571 return;
1572 }
1573 *end++ = '\0';
1574 remove_trailing_whitespaces (buf);
1575
1576 if (*buf == '\0')
1577 fail ("%s: %d: missing template identifier\n", filename, lineno);
1578 tmpl = xmalloc (sizeof (*tmpl));
1579 tmpl->name = xstrdup (buf);
1580
1581 tmpl->params = NULL;
1582 do {
1583 struct template_param *param;
1584
1585 buf = remove_leading_whitespaces (end);
1586 end = strpbrk (buf, ":,");
1587 if (end == NULL)
1588 fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1589
1590 sep = *end;
1591 *end++ = '\0';
1592 remove_trailing_whitespaces (buf);
1593
1594 param = xmalloc (sizeof (*param));
1595 param->name = xstrdup (buf);
1596 param->next = tmpl->params;
1597 tmpl->params = param;
1598 } while (sep == ':');
1599
1600 tmpl->instances = NULL;
1601 do {
1602 struct template_instance *inst;
1603 char *cur, *next;
1604 const struct template_param *param;
1605
1606 buf = remove_leading_whitespaces (end);
1607 end = strpbrk (buf, ",>");
1608 if (end == NULL)
1609 fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1610
1611 sep = *end;
1612 *end++ = '\0';
1613
1614 inst = xmalloc (sizeof (*inst));
1615 inst->next = NULL;
1616 inst->args = NULL;
1617
1618 cur = next_field (buf, ':', &next, end);
1619 inst->name = *cur != '$' ? xstrdup (cur) : "";
1620
1621 for (param = tmpl->params; param; param = param->next)
1622 {
1623 struct template_arg *arg = xmalloc (sizeof (*arg));
1624
1625 cur = next_field (next, ':', &next, end);
1626 if (next > end)
1627 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1628 arg->val = xstrdup (cur);
1629 arg->next = inst->args;
1630 inst->args = arg;
1631 }
1632
1633 if (tmpl->instances)
1634 last_inst->next = inst;
1635 else
1636 tmpl->instances = inst;
1637 last_inst = inst;
1638 } while (sep == ',');
1639
1640 buf = remove_leading_whitespaces (end);
1641 if (*buf)
1642 fprintf(stderr, "%s: %d: excess characters '%s'\n",
1643 filename, lineno, buf);
1644
1645 tmpl->next = templates;
1646 templates = tmpl;
1647 }
1648
1649 static unsigned int
expand_templates(char * name,const char * str,htab_t opcode_hash_table,struct opcode_hash_entry *** opcode_array_p,int lineno)1650 expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1651 struct opcode_hash_entry ***opcode_array_p, int lineno)
1652 {
1653 static unsigned int idx, opcode_array_size;
1654 struct opcode_hash_entry **opcode_array = *opcode_array_p;
1655 struct opcode_hash_entry **hash_slot;
1656 struct opcode_entry *entry;
1657 char *ptr1 = strchr(name, '<'), *ptr2;
1658
1659 if (ptr1 == NULL)
1660 {
1661 /* Get the slot in hash table. */
1662 hash_slot = (struct opcode_hash_entry **)
1663 htab_find_slot_with_hash (opcode_hash_table, name,
1664 htab_hash_string (name),
1665 INSERT);
1666
1667 if (*hash_slot == NULL)
1668 {
1669 /* It is the new one. Put it on opcode array. */
1670 if (idx >= opcode_array_size)
1671 {
1672 /* Grow the opcode array when needed. */
1673 opcode_array_size += 1024;
1674 opcode_array = (struct opcode_hash_entry **)
1675 xrealloc (opcode_array,
1676 sizeof (*opcode_array) * opcode_array_size);
1677 *opcode_array_p = opcode_array;
1678 }
1679
1680 opcode_array[idx] = (struct opcode_hash_entry *)
1681 xmalloc (sizeof (struct opcode_hash_entry));
1682 opcode_array[idx]->name = xstrdup (name);
1683 *hash_slot = opcode_array[idx];
1684 entry = &opcode_array[idx]->entry;
1685 idx++;
1686 }
1687 else
1688 {
1689 /* Append it to the existing one. */
1690 struct opcode_entry **entryp = &(*hash_slot)->entry.next;
1691
1692 while (*entryp != NULL)
1693 entryp = &(*entryp)->next;
1694 entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry));
1695 *entryp = entry;
1696 }
1697
1698 entry->next = NULL;
1699 entry->opcode = xstrdup (str);
1700 entry->lineno = lineno;
1701 }
1702 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1703 fail ("%s: %d: missing '>'\n", filename, lineno);
1704 else
1705 {
1706 const struct template *tmpl;
1707 const struct template_instance *inst;
1708
1709 *ptr1 = '\0';
1710 ptr1 = remove_leading_whitespaces (ptr1 + 1);
1711 remove_trailing_whitespaces (ptr1);
1712
1713 *ptr2++ = '\0';
1714
1715 for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1716 if (!strcmp(ptr1, tmpl->name))
1717 break;
1718 if (!tmpl)
1719 fail ("reference to unknown template '%s'\n", ptr1);
1720
1721 for (inst = tmpl->instances; inst; inst = inst->next)
1722 {
1723 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1724 char *str2 = xmalloc(2 * strlen(str));
1725 const char *src;
1726
1727 strcpy (name2, name);
1728 strcat (name2, inst->name);
1729 strcat (name2, ptr2);
1730
1731 for (ptr1 = str2, src = str; *src; )
1732 {
1733 const char *ident = tmpl->name, *end;
1734 const struct template_param *param;
1735 const struct template_arg *arg;
1736
1737 if ((*ptr1 = *src++) != '<')
1738 {
1739 ++ptr1;
1740 continue;
1741 }
1742 while (ISSPACE(*src))
1743 ++src;
1744 while (*ident && *src == *ident)
1745 ++src, ++ident;
1746 while (ISSPACE(*src))
1747 ++src;
1748 if (*src != ':' || *ident != '\0')
1749 {
1750 memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1751 ptr1 += ident - tmpl->name;
1752 continue;
1753 }
1754 while (ISSPACE(*++src))
1755 ;
1756
1757 end = src;
1758 while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1759 ++end;
1760
1761 for (param = tmpl->params, arg = inst->args; param;
1762 param = param->next, arg = arg->next)
1763 {
1764 if (end - src == strlen (param->name)
1765 && !memcmp (src, param->name, end - src))
1766 {
1767 src = end;
1768 break;
1769 }
1770 }
1771
1772 if (param == NULL)
1773 fail ("template '%s' has no parameter '%.*s'\n",
1774 tmpl->name, (int)(end - src), src);
1775
1776 while (ISSPACE(*src))
1777 ++src;
1778 if (*src != '>')
1779 fail ("%s: %d: missing '>'\n", filename, lineno);
1780
1781 memcpy(ptr1, arg->val, strlen(arg->val));
1782 ptr1 += strlen(arg->val);
1783 ++src;
1784 }
1785
1786 *ptr1 = '\0';
1787
1788 expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1789 lineno);
1790
1791 free (str2);
1792 free (name2);
1793 }
1794 }
1795
1796 return idx;
1797 }
1798
mnemonic_cmp(const void * p1,const void * p2)1799 static int mnemonic_cmp(const void *p1, const void *p2)
1800 {
1801 const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2;
1802 const char *s1 = (*e1)->name, *s2 = (*e2)->name;
1803 unsigned int i;
1804 size_t l1 = strlen (s1), l2 = strlen (s2);
1805
1806 for (i = 1; i <= l1 && i <= l2; ++i)
1807 {
1808 if (s1[l1 - i] != s2[l2 - i])
1809 return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i];
1810 }
1811
1812 return (int)(l1 - l2);
1813 }
1814
1815 static void
process_i386_opcodes(FILE * table)1816 process_i386_opcodes (FILE *table)
1817 {
1818 FILE *fp;
1819 char buf[2048];
1820 unsigned int i, j, nr, offs;
1821 size_t l;
1822 char *str, *p, *last;
1823 htab_t opcode_hash_table;
1824 struct opcode_hash_entry **opcode_array = NULL;
1825 int lineno = 0, marker = 0;
1826
1827 filename = "i386-opc.tbl";
1828 fp = stdin;
1829
1830 i = 0;
1831 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1832 opcode_hash_eq, NULL,
1833 xcalloc, free);
1834
1835 fprintf (table, "\n#include \"i386-mnem.h\"\n");
1836 fprintf (table, "\n/* i386 opcode table. */\n\n");
1837 fprintf (table, "static const insn_template i386_optab[] =\n{\n");
1838
1839 /* Put everything on opcode array. */
1840 while (!feof (fp))
1841 {
1842 char *name;
1843
1844 if (fgets (buf, sizeof (buf), fp) == NULL)
1845 break;
1846
1847 p = remove_leading_whitespaces (buf);
1848
1849 for ( ; ; )
1850 {
1851 lineno++;
1852
1853 /* Skip comments. */
1854 str = strstr (p, "//");
1855 if (str != NULL)
1856 {
1857 str[0] = '\0';
1858 remove_trailing_whitespaces (p);
1859 break;
1860 }
1861
1862 /* Look for line continuation character. */
1863 remove_trailing_whitespaces (p);
1864 j = strlen (buf);
1865 if (!j || buf[j - 1] != '+')
1866 break;
1867 if (j >= sizeof (buf) - 1)
1868 fail ("%s: %d: (continued) line too long\n", filename, lineno);
1869
1870 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1871 {
1872 fprintf (stderr, "%s: Line continuation on last line?\n",
1873 filename);
1874 break;
1875 }
1876 }
1877
1878 switch (p[0])
1879 {
1880 case '#':
1881 if (!strcmp("### MARKER ###", buf))
1882 marker = 1;
1883 else
1884 {
1885 /* Since we ignore all included files (we only care about their
1886 #define-s here), we don't need to monitor filenames. The final
1887 line number directive is going to refer to the main source file
1888 again. */
1889 char *end;
1890 unsigned long ln;
1891
1892 p = remove_leading_whitespaces (p + 1);
1893 if (!strncmp(p, "line", 4))
1894 p += 4;
1895 ln = strtoul (p, &end, 10);
1896 if (ln > 1 && ln < INT_MAX
1897 && *remove_leading_whitespaces (end) == '"')
1898 lineno = ln - 1;
1899 }
1900 /* Ignore comments. */
1901 case '\0':
1902 continue;
1903 break;
1904 case '<':
1905 parse_template (p, lineno);
1906 continue;
1907 default:
1908 if (!marker)
1909 continue;
1910 break;
1911 }
1912
1913 last = p + strlen (p);
1914
1915 /* Find name. */
1916 name = next_field (p, ',', &str, last);
1917
1918 i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1919 lineno);
1920 }
1921
1922 /* Process opcode array. */
1923 for (j = 0; j < i; j++)
1924 {
1925 const char *name = opcode_array[j]->name;
1926 struct opcode_entry *next;
1927
1928 for (next = &opcode_array[j]->entry; next; next = next->next)
1929 {
1930 str = next->opcode;
1931 lineno = next->lineno;
1932 last = str + strlen (str);
1933 output_i386_opcode (table, name, str, last, lineno);
1934 }
1935 }
1936
1937 fclose (fp);
1938
1939 fprintf (table, "};\n");
1940
1941 /* Generate opcode sets array. */
1942 fprintf (table, "\n/* i386 opcode sets table. */\n\n");
1943 fprintf (table, "typedef unsigned short i386_op_off_t;\n");
1944 fprintf (table, "static const i386_op_off_t i386_op_sets[] =\n{\n ");
1945
1946 for (nr = j = 0; j < i; j++)
1947 {
1948 struct opcode_entry *next = &opcode_array[j]->entry;
1949
1950 if ((j + 1) % 8 != 0)
1951 fprintf (table, "%5u,", nr);
1952 else
1953 fprintf (table, "%5u,\n ", nr);
1954 do
1955 {
1956 ++nr;
1957 next = next->next;
1958 }
1959 while (next);
1960 }
1961
1962 fprintf (table, "%5u\n};\n", nr);
1963
1964 /* Emit mnemonics and associated #define-s. */
1965 qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
1966
1967 fp = fopen ("i386-mnem.h", "w");
1968 if (fp == NULL)
1969 fail ("can't create i386-mnem.h, errno = %s\n",
1970 xstrerror (errno));
1971
1972 process_copyright (fp);
1973
1974 fprintf (table, "\n/* i386 mnemonics table. */\n\n");
1975 fprintf (table, "const char i386_mnemonics[] =\n");
1976 fprintf (fp, "\nextern const char i386_mnemonics[];\n\n");
1977
1978 str = NULL;
1979 for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++)
1980 {
1981 const char *name = opcode_array[j]->name;
1982 const char *next = NULL;
1983 size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0;
1984
1985 if (str == NULL)
1986 str = mkident (name);
1987 if (l < l1 && !strcmp(name, next + l1 - l))
1988 {
1989 fprintf (fp, "#define MN_%s ", str);
1990 free (str);
1991 str = mkident (next);
1992 fprintf (fp, "(MN_%s + %zu)\n", str, l1 - l);
1993 }
1994 else
1995 {
1996 fprintf (table, " \"\\0\"\"%s\"\n", name);
1997 fprintf (fp, "#define MN_%s %#x\n", str, offs + 1);
1998 offs += strlen (name) + 1;
1999 free (str);
2000 str = NULL;
2001 }
2002 l = l1;
2003 }
2004
2005 fprintf (table, " \"\\0\"\".insn\"\n");
2006 fprintf (fp, "#define MN__insn %#x\n", offs + 1);
2007
2008 fprintf (table, ";\n");
2009
2010 fclose (fp);
2011 }
2012
2013 static void
process_i386_registers(FILE * table)2014 process_i386_registers (FILE *table)
2015 {
2016 FILE *fp;
2017 char buf[2048];
2018 char *str, *p, *last;
2019 char *reg_name, *reg_type, *reg_flags, *reg_num;
2020 char *dw2_32_num, *dw2_64_num;
2021 int lineno = 0;
2022
2023 filename = "i386-reg.tbl";
2024 fp = fopen (filename, "r");
2025 if (fp == NULL)
2026 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
2027 xstrerror (errno));
2028
2029 fprintf (table, "\n/* i386 register table. */\n\n");
2030 fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
2031
2032 while (!feof (fp))
2033 {
2034 if (fgets (buf, sizeof (buf), fp) == NULL)
2035 break;
2036
2037 lineno++;
2038
2039 p = remove_leading_whitespaces (buf);
2040
2041 /* Skip comments. */
2042 str = strstr (p, "//");
2043 if (str != NULL)
2044 str[0] = '\0';
2045
2046 /* Remove trailing white spaces. */
2047 remove_trailing_whitespaces (p);
2048
2049 switch (p[0])
2050 {
2051 case '#':
2052 fprintf (table, "%s\n", p);
2053 case '\0':
2054 continue;
2055 break;
2056 default:
2057 break;
2058 }
2059
2060 last = p + strlen (p);
2061
2062 /* Find reg_name. */
2063 reg_name = next_field (p, ',', &str, last);
2064
2065 /* Find reg_type. */
2066 reg_type = next_field (str, ',', &str, last);
2067
2068 /* Find reg_flags. */
2069 reg_flags = next_field (str, ',', &str, last);
2070
2071 /* Find reg_num. */
2072 reg_num = next_field (str, ',', &str, last);
2073
2074 fprintf (table, " { \"%s\",\n ", reg_name);
2075
2076 process_i386_operand_type (table, reg_type, stage_registers, "\t",
2077 lineno);
2078
2079 /* Find 32-bit Dwarf2 register number. */
2080 dw2_32_num = next_field (str, ',', &str, last);
2081
2082 /* Find 64-bit Dwarf2 register number. */
2083 dw2_64_num = next_field (str, ',', &str, last);
2084
2085 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
2086 reg_flags, reg_num, dw2_32_num, dw2_64_num);
2087 }
2088
2089 fclose (fp);
2090
2091 fprintf (table, "};\n");
2092
2093 fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2094 }
2095
2096 static void
process_i386_initializers(void)2097 process_i386_initializers (void)
2098 {
2099 unsigned int i;
2100 FILE *fp = fopen ("i386-init.h", "w");
2101
2102 if (fp == NULL)
2103 fail ("can't create i386-init.h, errno = %s\n",
2104 xstrerror (errno));
2105
2106 process_copyright (fp);
2107
2108 for (i = 0; i < CpuMax; i++)
2109 process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i);
2110
2111 for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++)
2112 {
2113 char *deps = xstrdup (isa_dependencies[i].deps);
2114
2115 process_i386_cpu_flag (fp, deps, isa_dependencies[i].name,
2116 "", " ", -1, CpuMax);
2117 free (deps);
2118 }
2119
2120 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
2121 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
2122 one to 387. We want the reverse to be true though: Disabling 8087 also
2123 is to disable 287+ and later; disabling 287 also means disabling 387+. */
2124 memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387],
2125 sizeof (isa_reverse_deps[0]));
2126 isa_reverse_deps[Cpu287][Cpu387] = 1;
2127 memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287],
2128 sizeof (isa_reverse_deps[0]));
2129 isa_reverse_deps[Cpu8087][Cpu287] = 1;
2130
2131 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
2132 lead to disabling of anything else. */
2133 memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0]));
2134
2135 for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++)
2136 {
2137 size_t len;
2138 char *upper;
2139
2140 if (memchr(isa_reverse_deps[i], 1,
2141 ARRAY_SIZE (isa_reverse_deps[0])) == NULL)
2142 continue;
2143
2144 isa_reverse_deps[i][i] = 1;
2145 process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i);
2146 }
2147
2148 fprintf (fp, "\n");
2149
2150 fclose (fp);
2151 }
2152
2153 /* Program options. */
2154 #define OPTION_SRCDIR 200
2155
2156 struct option long_options[] =
2157 {
2158 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2159 {"debug", no_argument, NULL, 'd'},
2160 {"version", no_argument, NULL, 'V'},
2161 {"help", no_argument, NULL, 'h'},
2162 {0, no_argument, NULL, 0}
2163 };
2164
2165 static void
print_version(void)2166 print_version (void)
2167 {
2168 printf ("%s: version 1.0\n", program_name);
2169 xexit (0);
2170 }
2171
2172 static void
usage(FILE * stream,int status)2173 usage (FILE * stream, int status)
2174 {
2175 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2176 program_name);
2177 xexit (status);
2178 }
2179
2180 int
main(int argc,char ** argv)2181 main (int argc, char **argv)
2182 {
2183 extern int chdir (char *);
2184 char *srcdir = NULL;
2185 int c;
2186 unsigned int i, cpumax;
2187 FILE *table;
2188
2189 program_name = *argv;
2190 xmalloc_set_program_name (program_name);
2191
2192 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2193 switch (c)
2194 {
2195 case OPTION_SRCDIR:
2196 srcdir = optarg;
2197 break;
2198 case 'V':
2199 case 'v':
2200 print_version ();
2201 break;
2202 case 'd':
2203 debug = 1;
2204 break;
2205 case 'h':
2206 case '?':
2207 usage (stderr, 0);
2208 default:
2209 case 0:
2210 break;
2211 }
2212
2213 if (optind != argc)
2214 usage (stdout, 1);
2215
2216 if (srcdir != NULL)
2217 if (chdir (srcdir) != 0)
2218 fail ("unable to change directory to \"%s\", errno = %s\n",
2219 srcdir, xstrerror (errno));
2220
2221 /* cpu_flags isn't sorted by position. */
2222 cpumax = 0;
2223 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2224 if (cpu_flags[i].position > cpumax)
2225 cpumax = cpu_flags[i].position;
2226
2227 /* Check the unused bitfield in i386_cpu_flags. */
2228 #ifdef CpuUnused
2229 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2230
2231 if ((cpumax - 1) != CpuMax)
2232 fail ("CpuMax != %d!\n", cpumax);
2233 #else
2234 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2235
2236 if (cpumax != CpuMax)
2237 fail ("CpuMax != %d!\n", cpumax);
2238
2239 c = CpuNumOfBits - CpuMax - 1;
2240 if (c)
2241 fail ("%d unused bits in i386_cpu_flags.\n", c);
2242 #endif
2243
2244 /* If this triggers, CpuIsaBits needs to be increased. */
2245 static_assert (CpuAttrEnums <= (1u << CpuIsaBits));
2246
2247 /* Check the unused bitfield in i386_cpu_attr. */
2248 #ifndef CpuAttrUnused
2249 c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums);
2250 if (c)
2251 fail ("%d unused bits in i386_cpu_attr.\n", c);
2252 #endif
2253
2254 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2255
2256 /* Check the unused bitfield in i386_operand_type. */
2257 #ifdef OTUnused
2258 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2259 == OTNum + 1);
2260 #else
2261 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2262 == OTNum);
2263
2264 c = OTNumOfBits - OTNum;
2265 if (c)
2266 fail ("%d unused bits in i386_operand_type.\n", c);
2267 #endif
2268
2269 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2270 compare);
2271
2272 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2273 sizeof (opcode_modifiers [0]), compare);
2274
2275 qsort (operand_types, ARRAY_SIZE (operand_types),
2276 sizeof (operand_types [0]), compare);
2277
2278 process_i386_initializers ();
2279
2280 table = fopen ("i386-tbl.h", "w");
2281 if (table == NULL)
2282 fail ("can't create i386-tbl.h, errno = %s\n",
2283 xstrerror (errno));
2284
2285 process_copyright (table);
2286
2287 process_i386_opcodes (table);
2288 process_i386_registers (table);
2289
2290 fclose (table);
2291
2292 exit (0);
2293 }
2294