xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/i386-gen.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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