1 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
25 #include "libiberty.h"
27 #include "safe-ctype.h"
31 /* Build-time checks are preferrable over runtime ones. Use this construct
32 in preference where possible. */
33 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
35 static const char *program_name
= NULL
;
38 typedef struct dependency
41 /* Note: Only direct dependencies should be enumerated. */
45 static const dependency isa_dependencies
[] =
52 "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" },
64 "GENERIC64|FISTTP|SSE3|MONITOR|CX16" },
66 "P4|FISTTP|SSE3|MONITOR" },
70 "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" },
72 "186|286|386|486|586|SYSCALL|387|MMX" },
76 "K6_2|686:min|687|Nop|3dnowA" },
78 "ATHLON|Rdtscp|SSE2|LM" },
80 "K8|FISTTP|SSE4A|ABM|MONITOR" },
82 "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMULQDQ|PRFCHW" },
84 "BDVER1|FMA|BMI|TBM|F16C" },
86 "BDVER2|Xsaveopt|FSGSBase" },
88 "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" },
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" },
92 "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" },
94 "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" },
96 "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" },
98 "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" },
100 "BTVER1|AVX|BMI|F16C|AES|PCLMULQDQ|Movbe|Xsaveopt|PRFCHW" },
112 "586|687|CMOV|FXSR" },
193 { "AVX512_VPOPCNTDQ",
201 { "AVX512_VP2INTERSECT",
236 "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA"
237 "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" },
264 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
265 static unsigned char isa_reverse_deps
[CpuMax
][CpuMax
];
267 typedef struct bitfield
274 #define BITFIELD(n) { Cpu##n, 0, #n }
276 static bitfield cpu_flags
[] =
321 BITFIELD (PCLMULQDQ
),
330 BITFIELD (LAHF_SAHF
),
352 BITFIELD (ClflushOpt
),
355 BITFIELD (PREFETCHWT1
),
359 BITFIELD (AVX512IFMA
),
360 BITFIELD (AVX512VBMI
),
361 BITFIELD (AVX512_4FMAPS
),
362 BITFIELD (AVX512_4VNNIW
),
363 BITFIELD (AVX512_VPOPCNTDQ
),
364 BITFIELD (AVX512_VBMI2
),
365 BITFIELD (AVX512_VNNI
),
366 BITFIELD (AVX512_BITALG
),
367 BITFIELD (AVX512_BF16
),
368 BITFIELD (AVX512_VP2INTERSECT
),
371 BITFIELD (AVX512_FP16
),
372 BITFIELD (PREFETCHI
),
374 BITFIELD (AVX_VNNI_INT8
),
375 BITFIELD (AVX_VNNI_INT16
),
376 BITFIELD (CMPCCXADD
),
379 BITFIELD (AVX_NE_CONVERT
),
393 BITFIELD (VPCLMULQDQ
),
403 BITFIELD (AMX_COMPLEX
),
406 BITFIELD (MOVDIR64B
),
408 BITFIELD (SERIALIZE
),
428 #define BITFIELD(n) { n, 0, #n }
430 static bitfield opcode_modifiers
[] =
439 BITFIELD (CheckOperandSize
),
440 BITFIELD (OperandConstraint
),
441 BITFIELD (MnemonicSize
),
450 BITFIELD (BNDPrefixOk
),
458 BITFIELD (OpcodePrefix
),
463 BITFIELD (Broadcast
),
464 BITFIELD (StaticRounding
),
466 BITFIELD (Disp8MemShift
),
469 BITFIELD (ATTMnemonic
),
470 BITFIELD (ATTSyntax
),
471 BITFIELD (IntelSyntax
),
475 #define CLASS(n) #n, n
477 static const struct {
479 enum operand_class value
;
480 } operand_classes
[] = {
494 #define INSTANCE(n) #n, n
496 static const struct {
498 enum operand_instance value
;
499 } operand_instances
[] = {
508 static bitfield operand_types
[] =
517 BITFIELD (BaseIndex
),
532 BITFIELD (Unspecified
),
538 static const char *filename
;
539 static i386_cpu_flags active_cpu_flags
;
540 static int active_isstring
;
542 struct template_arg
{
543 const struct template_arg
*next
;
547 struct template_instance
{
548 const struct template_instance
*next
;
550 const struct template_arg
*args
;
553 struct template_param
{
554 const struct template_param
*next
;
559 struct template *next
;
561 const struct template_instance
*instances
;
562 const struct template_param
*params
;
565 static struct template *templates
;
568 compare (const void *x
, const void *y
)
570 const bitfield
*xp
= (const bitfield
*) x
;
571 const bitfield
*yp
= (const bitfield
*) y
;
572 return xp
->position
- yp
->position
;
576 fail (const char *message
, ...)
580 va_start (args
, message
);
581 fprintf (stderr
, "%s: error: ", program_name
);
582 vfprintf (stderr
, message
, args
);
588 process_copyright (FILE *fp
)
590 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
591 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
593 This file is part of the GNU opcodes library.\n\
595 This library is free software; you can redistribute it and/or modify\n\
596 it under the terms of the GNU General Public License as published by\n\
597 the Free Software Foundation; either version 3, or (at your option)\n\
598 any later version.\n\
600 It is distributed in the hope that it will be useful, but WITHOUT\n\
601 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
602 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
603 License for more details.\n\
605 You should have received a copy of the GNU General Public License\n\
606 along with this program; if not, write to the Free Software\n\
607 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
608 MA 02110-1301, USA. */\n");
611 /* Remove leading white spaces. */
614 remove_leading_whitespaces (char *str
)
616 while (ISSPACE (*str
))
621 /* Remove trailing white spaces. */
624 remove_trailing_whitespaces (char *str
)
626 size_t last
= strlen (str
);
634 if (ISSPACE (str
[last
]))
642 /* Find next field separated by SEP and terminate it. Return a
643 pointer to the one after it. */
646 next_field (char *str
, char sep
, char **next
, char *last
)
650 p
= remove_leading_whitespaces (str
);
651 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
654 remove_trailing_whitespaces (p
);
664 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
667 set_bitfield (char *f
, bitfield
*array
, int value
,
668 unsigned int size
, int lineno
)
672 /* Ignore empty fields; they may result from template expansions. */
676 for (i
= 0; i
< size
; i
++)
677 if (strcasecmp (array
[i
].name
, f
) == 0)
679 array
[i
].value
= value
;
685 const char *v
= strchr (f
, '=');
692 for (i
= 0; i
< size
; i
++)
693 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
695 value
= strtol (v
+ 1, &end
, 0);
698 array
[i
].value
= value
;
707 fail ("%s: %d: unknown bitfield: %s\n", filename
, lineno
, f
);
709 fail ("unknown bitfield: %s\n", f
);
713 add_isa_dependencies (bitfield
*flags
, const char *f
, int value
,
714 unsigned int reverse
)
720 bool is_isa
= false, orig_is_avx
= is_avx
;
722 /* Need to find base entry for references to auxiliary ones. */
726 *strchr (str
, ':') = '\0';
729 /* isa_dependencies[] prefers "LM" over "64". */
730 else if (!strcmp (f
, "LM"))
732 for (i
= 0; i
< CpuMax
; ++i
)
733 if (strcasecmp (flags
[i
].name
, isa
) == 0)
735 flags
[i
].value
= value
;
736 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0])
737 /* Don't record the feature itself here. */
739 /* Don't record base architectures. */
741 isa_reverse_deps
[i
][reverse
] = 1;
743 if (i
== CpuAVX
|| i
== CpuXOP
|| i
== CpuVAES
|| i
== CpuVPCLMULQDQ
)
749 /* Do not turn off dependencies. */
750 if (is_isa
&& !value
)
752 is_avx
= orig_is_avx
;
756 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); ++i
)
757 if (strcasecmp (isa_dependencies
[i
].name
, f
) == 0)
759 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
761 char *last
= deps
+ strlen (deps
);
763 for (; next
&& next
< last
; )
765 char *str
= next_field (next
, '|', &next
, last
);
767 /* No AVX/XOP -> SSE reverse dependencies. */
768 if (is_avx
&& strncmp (str
, "SSE", 3) == 0)
769 add_isa_dependencies (flags
, str
, value
, CpuMax
);
771 add_isa_dependencies (flags
, str
, value
, reverse
);
775 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
776 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0]))
777 isa_reverse_deps
[reverse
][reverse
] = 1;
779 is_avx
= orig_is_avx
;
784 fail ("unknown bitfield: %s\n", f
);
786 is_avx
= orig_is_avx
;
790 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
791 int macro
, const char *comma
, const char *indent
, int lineno
)
793 unsigned int i
= 0, j
= 0;
795 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
797 fprintf (table
, "%s{ { ", indent
);
801 for (j
= ~0u; i
< CpuAttrEnums
; i
++)
807 fail ("%s: %d: invalid combination of CPU identifiers\n",
810 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
813 /* Write 0 to indicate "no associated flag". */
814 fprintf (table
, "%u, ", j
+ 1);
819 for (; i
< size
- 1; i
++, j
++)
821 if (((j
+ 1) % 20) != 0)
822 fprintf (table
, "%d, ", flags
[i
].value
);
824 fprintf (table
, "%d,", flags
[i
].value
);
825 if (((j
+ 1) % 20) == 0)
827 /* We need \\ for macro. */
829 fprintf (table
, " \\\n %s", indent
);
831 fprintf (table
, "\n %s", indent
);
834 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
837 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
841 process_i386_cpu_flag (FILE *table
, char *flag
,
843 const char *comma
, const char *indent
,
844 int lineno
, unsigned int reverse
)
846 char *str
, *next
= flag
, *last
;
850 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
852 /* Copy the default cpu flags. */
853 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
857 for (i
= 0; i
< ARRAY_SIZE (isa_reverse_deps
[0]); ++i
)
858 flags
[i
].value
= isa_reverse_deps
[reverse
][i
];
864 last
= flag
+ strlen (flag
);
871 fail ("%s: %d: missing `)' in bitfield: %s\n", filename
,
878 /* First we turn on everything except for cpuno64 and - if
879 present - the padding field. */
880 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
881 if (flags
[i
].position
< CpuNo64
)
884 /* Turn off selective bits. */
888 if (name
!= NULL
&& value
!= 0)
890 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
891 if (strcasecmp (flags
[i
].name
, name
) == 0)
893 add_isa_dependencies (flags
, name
, 1, reverse
);
899 if (strcmp (flag
, "0"))
904 /* Turn on/off selective bits. */
905 last
= flag
+ strlen (flag
);
906 for (; next
&& next
< last
; )
908 str
= next_field (next
, '|', &next
, last
);
910 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
912 add_isa_dependencies (flags
, str
, value
, reverse
);
919 size_t len
= strlen (name
);
920 char *upper
= xmalloc (len
+ 1);
922 for (i
= 0; i
< len
; ++i
)
924 /* Don't emit #define-s for auxiliary entries. */
927 upper
[i
] = TOUPPER (name
[i
]);
930 fprintf (table
, "\n#define CPU_%s%s_FLAGS \\\n",
931 flag
!= NULL
? "": "ANY_", upper
);
935 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), name
!= NULL
,
936 comma
, indent
, lineno
);
940 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
944 fprintf (table
, " { ");
946 for (i
= 0; i
< size
- 1; i
++)
948 if (((i
+ 1) % 20) != 0)
949 fprintf (table
, "%d, ", modifier
[i
].value
);
951 fprintf (table
, "%d,", modifier
[i
].value
);
952 if (((i
+ 1) % 20) == 0)
953 fprintf (table
, "\n ");
956 fprintf (table
, "%d },\n", modifier
[i
].value
);
959 /* Returns LOG2 of element size. */
961 get_element_size (char **opnd
, int lineno
)
963 char *str
, *next
, *last
, *op
;
964 const char *full
= opnd
[0];
965 int elem_size
= INT_MAX
;
967 /* Find the memory operand. */
968 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
971 fail ("%s: %d: no memory operand\n", filename
, lineno
);
974 last
= op
+ strlen (op
);
975 for (next
= op
; next
&& next
< last
; )
977 str
= next_field (next
, '|', &next
, last
);
980 if (strcasecmp(str
, "Byte") == 0)
982 /* The smallest element size, no need to check
987 else if (strcasecmp(str
, "Word") == 0)
992 else if (strcasecmp(str
, "Dword") == 0)
997 else if (strcasecmp(str
, "Qword") == 0)
1006 if (elem_size
== INT_MAX
)
1007 fail ("%s: %d: unknown element size: %s\n", filename
, lineno
, full
);
1013 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1014 unsigned int prefix
, const char *extension_opcode
,
1015 char **opnd
, int lineno
)
1017 char *str
, *next
, *last
;
1018 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1019 static const char *const spaces
[] = {
1020 #define SPACE(n) [SPACE_##n] = #n
1034 active_isstring
= 0;
1036 /* Copy the default opcode modifier. */
1037 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1039 if (strcmp (mod
, "0"))
1041 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1043 last
= mod
+ strlen (mod
);
1044 for (next
= mod
; next
&& next
< last
; )
1046 str
= next_field (next
, '|', &next
, last
);
1051 if (strncmp(str
, "OpcodeSpace", 11) == 0)
1056 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1059 val
= strtol (str
+ 12, &end
, 0);
1061 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1062 filename
, lineno
, end
);
1067 fail ("%s:%d: Conflicting opcode space specifications\n",
1070 "%s:%d: Warning: redundant opcode space specification\n",
1078 if (strcasecmp(str
, "Broadcast") == 0)
1079 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1080 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1081 val
= get_element_size (opnd
, lineno
);
1083 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1085 if (strcasecmp(str
, "IsString") == 0)
1086 active_isstring
= 1;
1088 if (strcasecmp(str
, "W") == 0)
1091 if (strcasecmp(str
, "No_bSuf") == 0)
1093 if (strcasecmp(str
, "No_wSuf") == 0)
1095 if (strcasecmp(str
, "No_lSuf") == 0)
1097 if (strcasecmp(str
, "No_qSuf") == 0)
1104 if (!modifiers
[OpcodePrefix
].value
)
1105 modifiers
[OpcodePrefix
].value
= prefix
;
1106 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1107 fail ("%s:%d: Conflicting prefix specifications\n",
1111 "%s:%d: Warning: redundant prefix specification\n",
1115 if (have_w
&& !bwlq_suf
)
1116 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1117 if (have_w
&& !(bwlq_suf
& 1))
1118 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1120 if (have_w
&& !(bwlq_suf
& ~1))
1122 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1126 if (space
>= ARRAY_SIZE (spaces
) || !spaces
[space
])
1127 fail ("%s:%d: Unknown opcode space %u\n", filename
, lineno
, space
);
1129 fprintf (table
, " SPACE_%s, %s,\n",
1130 spaces
[space
], extension_opcode
? extension_opcode
: "None");
1132 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1142 output_operand_type (FILE *table
, enum operand_class
class,
1143 enum operand_instance instance
,
1144 const bitfield
*types
, unsigned int size
,
1145 enum stage stage
, const char *indent
)
1149 fprintf (table
, "{ { %d, %d, ", class, instance
);
1151 for (i
= 0; i
< size
- 1; i
++)
1153 if (((i
+ 3) % 20) != 0)
1154 fprintf (table
, "%d, ", types
[i
].value
);
1156 fprintf (table
, "%d,", types
[i
].value
);
1157 if (((i
+ 3) % 20) == 0)
1159 /* We need \\ for macro. */
1160 if (stage
== stage_macros
)
1161 fprintf (table
, " \\\n%s", indent
);
1163 fprintf (table
, "\n%s", indent
);
1167 fprintf (table
, "%d } }", types
[i
].value
);
1171 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1172 const char *indent
, int lineno
)
1174 char *str
, *next
, *last
;
1175 enum operand_class
class = ClassNone
;
1176 enum operand_instance instance
= InstanceNone
;
1177 bitfield types
[ARRAY_SIZE (operand_types
)];
1179 /* Copy the default operand type. */
1180 memcpy (types
, operand_types
, sizeof (types
));
1182 if (strcmp (op
, "0"))
1186 last
= op
+ strlen (op
);
1187 for (next
= op
; next
&& next
< last
; )
1189 str
= next_field (next
, '|', &next
, last
);
1194 if (!strncmp(str
, "Class=", 6))
1196 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1197 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1199 class = operand_classes
[i
].value
;
1205 if (str
&& !strncmp(str
, "Instance=", 9))
1207 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1208 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1210 instance
= operand_instances
[i
].value
;
1218 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1219 if (strcasecmp(str
, "BaseIndex") == 0)
1224 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1226 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1227 if (!active_cpu_flags
.bitfield
.cpu64
1228 && !active_cpu_flags
.bitfield
.cpumpx
)
1229 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1230 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1233 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1237 static char *mkident (const char *mnem
)
1239 char *ident
= xstrdup (mnem
), *p
= ident
;
1252 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1253 char *last
, int lineno
)
1255 unsigned int i
, length
, prefix
= 0, space
= 0;
1256 char *base_opcode
, *extension_opcode
, *end
, *ident
;
1257 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1258 unsigned long long opcode
;
1260 /* Find base_opcode. */
1261 base_opcode
= next_field (str
, ',', &str
, last
);
1263 /* Find extension_opcode, if any. */
1264 extension_opcode
= strchr (base_opcode
, '/');
1265 if (extension_opcode
)
1266 *extension_opcode
++ = '\0';
1268 /* Find cpu_flags. */
1269 cpu_flags
= next_field (str
, ',', &str
, last
);
1271 /* Find opcode_modifier. */
1272 opcode_modifier
= next_field (str
, ',', &str
, last
);
1274 /* Remove the first {. */
1275 str
= remove_leading_whitespaces (str
);
1278 str
= remove_leading_whitespaces (str
+ 1);
1279 remove_trailing_whitespaces (str
);
1281 /* Remove } and trailing white space. */
1283 if (!i
|| str
[i
- 1] != '}')
1286 remove_trailing_whitespaces (str
);
1289 operand_types
[i
= 0] = NULL
;
1292 last
= str
+ strlen (str
);
1294 /* Find operand_types. */
1295 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1299 operand_types
[i
] = NULL
;
1303 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1307 opcode
= strtoull (base_opcode
, &end
, 0);
1309 /* Determine opcode length. */
1310 for (length
= 1; length
< 8; ++length
)
1311 if (!(opcode
>> (8 * length
)))
1314 /* Transform prefixes encoded in the opcode into opcode modifier
1318 switch (opcode
>> (8 * length
- 8))
1320 case 0x66: prefix
= PREFIX_0X66
; break;
1321 case 0xF3: prefix
= PREFIX_0XF3
; break;
1322 case 0xF2: prefix
= PREFIX_0XF2
; break;
1326 opcode
&= (1ULL << (8 * --length
)) - 1;
1329 /* Transform opcode space encoded in the opcode into opcode modifier
1331 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1333 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1335 default: space
= SPACE_0F
; break;
1336 case 0x38: space
= SPACE_0F38
; break;
1337 case 0x3A: space
= SPACE_0F3A
; break;
1340 if (space
!= SPACE_0F
&& --length
== 1)
1341 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1342 filename
, lineno
, name
);
1343 opcode
&= (1ULL << (8 * --length
)) - 1;
1347 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1348 filename
, lineno
, name
, 2 * length
, opcode
);
1350 ident
= mkident (name
);
1351 fprintf (table
, " { MN_%s, 0x%0*llx%s, %u,",
1352 ident
, 2 * (int)length
, opcode
, end
, i
);
1355 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1356 extension_opcode
, operand_types
, lineno
);
1358 process_i386_cpu_flag (table
, cpu_flags
, NULL
, ",", " ", lineno
, CpuMax
);
1360 fprintf (table
, " { ");
1362 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1364 if (!operand_types
[i
])
1367 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1373 fprintf (table
, ",\n ");
1375 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1378 fprintf (table
, " } },\n");
1381 struct opcode_hash_entry
1386 struct opcode_entry
*next
;
1392 /* Calculate the hash value of an opcode hash entry P. */
1395 opcode_hash_hash (const void *p
)
1397 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1398 return htab_hash_string (entry
->name
);
1401 /* Compare a string Q against an opcode hash entry P. */
1404 opcode_hash_eq (const void *p
, const void *q
)
1406 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1407 const char *name
= (const char *) q
;
1408 return strcmp (name
, entry
->name
) == 0;
1412 parse_template (char *buf
, int lineno
)
1414 char sep
, *end
, *name
;
1415 struct template *tmpl
;
1416 struct template_instance
*last_inst
= NULL
;
1418 buf
= remove_leading_whitespaces (buf
+ 1);
1419 end
= strchr (buf
, ':');
1422 struct template *prev
= NULL
;
1424 end
= strchr (buf
, '>');
1426 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1427 if (*remove_leading_whitespaces (end
+ 1))
1428 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1430 remove_trailing_whitespaces (buf
);
1431 /* Don't bother freeing the various structures. */
1432 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1433 if (!strcmp (buf
, tmpl
->name
))
1436 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1438 prev
->next
= tmpl
->next
;
1440 templates
= tmpl
->next
;
1444 remove_trailing_whitespaces (buf
);
1447 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1448 tmpl
= xmalloc (sizeof (*tmpl
));
1449 tmpl
->name
= xstrdup (buf
);
1451 tmpl
->params
= NULL
;
1453 struct template_param
*param
;
1455 buf
= remove_leading_whitespaces (end
);
1456 end
= strpbrk (buf
, ":,");
1458 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1462 remove_trailing_whitespaces (buf
);
1464 param
= xmalloc (sizeof (*param
));
1465 param
->name
= xstrdup (buf
);
1466 param
->next
= tmpl
->params
;
1467 tmpl
->params
= param
;
1468 } while (sep
== ':');
1470 tmpl
->instances
= NULL
;
1472 struct template_instance
*inst
;
1474 const struct template_param
*param
;
1476 buf
= remove_leading_whitespaces (end
);
1477 end
= strpbrk (buf
, ",>");
1479 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1484 inst
= xmalloc (sizeof (*inst
));
1488 cur
= next_field (buf
, ':', &next
, end
);
1489 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1491 for (param
= tmpl
->params
; param
; param
= param
->next
)
1493 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1495 cur
= next_field (next
, ':', &next
, end
);
1497 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1498 arg
->val
= xstrdup (cur
);
1499 arg
->next
= inst
->args
;
1503 if (tmpl
->instances
)
1504 last_inst
->next
= inst
;
1506 tmpl
->instances
= inst
;
1508 } while (sep
== ',');
1510 buf
= remove_leading_whitespaces (end
);
1512 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1513 filename
, lineno
, buf
);
1515 tmpl
->next
= templates
;
1520 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1521 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1523 static unsigned int idx
, opcode_array_size
;
1524 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1525 struct opcode_hash_entry
**hash_slot
;
1526 struct opcode_entry
*entry
;
1527 char *ptr1
= strchr(name
, '<'), *ptr2
;
1531 /* Get the slot in hash table. */
1532 hash_slot
= (struct opcode_hash_entry
**)
1533 htab_find_slot_with_hash (opcode_hash_table
, name
,
1534 htab_hash_string (name
),
1537 if (*hash_slot
== NULL
)
1539 /* It is the new one. Put it on opcode array. */
1540 if (idx
>= opcode_array_size
)
1542 /* Grow the opcode array when needed. */
1543 opcode_array_size
+= 1024;
1544 opcode_array
= (struct opcode_hash_entry
**)
1545 xrealloc (opcode_array
,
1546 sizeof (*opcode_array
) * opcode_array_size
);
1547 *opcode_array_p
= opcode_array
;
1550 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1551 xmalloc (sizeof (struct opcode_hash_entry
));
1552 opcode_array
[idx
]->name
= xstrdup (name
);
1553 *hash_slot
= opcode_array
[idx
];
1554 entry
= &opcode_array
[idx
]->entry
;
1559 /* Append it to the existing one. */
1560 struct opcode_entry
**entryp
= &(*hash_slot
)->entry
.next
;
1562 while (*entryp
!= NULL
)
1563 entryp
= &(*entryp
)->next
;
1564 entry
= (struct opcode_entry
*)xmalloc (sizeof (struct opcode_entry
));
1569 entry
->opcode
= xstrdup (str
);
1570 entry
->lineno
= lineno
;
1572 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1573 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1576 const struct template *tmpl
;
1577 const struct template_instance
*inst
;
1580 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1581 remove_trailing_whitespaces (ptr1
);
1585 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1586 if (!strcmp(ptr1
, tmpl
->name
))
1589 fail ("reference to unknown template '%s'\n", ptr1
);
1591 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1593 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1594 char *str2
= xmalloc(2 * strlen(str
));
1597 strcpy (name2
, name
);
1598 strcat (name2
, inst
->name
);
1599 strcat (name2
, ptr2
);
1601 for (ptr1
= str2
, src
= str
; *src
; )
1603 const char *ident
= tmpl
->name
, *end
;
1604 const struct template_param
*param
;
1605 const struct template_arg
*arg
;
1607 if ((*ptr1
= *src
++) != '<')
1612 while (ISSPACE(*src
))
1614 while (*ident
&& *src
== *ident
)
1616 while (ISSPACE(*src
))
1618 if (*src
!= ':' || *ident
!= '\0')
1620 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1621 ptr1
+= ident
- tmpl
->name
;
1624 while (ISSPACE(*++src
))
1628 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1631 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1632 param
= param
->next
, arg
= arg
->next
)
1634 if (end
- src
== strlen (param
->name
)
1635 && !memcmp (src
, param
->name
, end
- src
))
1643 fail ("template '%s' has no parameter '%.*s'\n",
1644 tmpl
->name
, (int)(end
- src
), src
);
1646 while (ISSPACE(*src
))
1649 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1651 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1652 ptr1
+= strlen(arg
->val
);
1658 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1669 static int mnemonic_cmp(const void *p1
, const void *p2
)
1671 const struct opcode_hash_entry
*const *e1
= p1
, *const *e2
= p2
;
1672 const char *s1
= (*e1
)->name
, *s2
= (*e2
)->name
;
1674 size_t l1
= strlen (s1
), l2
= strlen (s2
);
1676 for (i
= 1; i
<= l1
&& i
<= l2
; ++i
)
1678 if (s1
[l1
- i
] != s2
[l2
- i
])
1679 return (unsigned char)s1
[l1
- i
] - (unsigned char)s2
[l2
- i
];
1682 return (int)(l1
- l2
);
1686 process_i386_opcodes (FILE *table
)
1690 unsigned int i
, j
, nr
, offs
;
1692 char *str
, *p
, *last
;
1693 htab_t opcode_hash_table
;
1694 struct opcode_hash_entry
**opcode_array
= NULL
;
1695 int lineno
= 0, marker
= 0;
1697 filename
= "i386-opc.tbl";
1701 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1702 opcode_hash_eq
, NULL
,
1705 fprintf (table
, "\n#include \"i386-mnem.h\"\n");
1706 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1707 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1709 /* Put everything on opcode array. */
1714 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1717 p
= remove_leading_whitespaces (buf
);
1723 /* Skip comments. */
1724 str
= strstr (p
, "//");
1728 remove_trailing_whitespaces (p
);
1732 /* Look for line continuation character. */
1733 remove_trailing_whitespaces (p
);
1735 if (!j
|| buf
[j
- 1] != '+')
1737 if (j
>= sizeof (buf
) - 1)
1738 fail ("%s: %d: (continued) line too long\n", filename
, lineno
);
1740 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1742 fprintf (stderr
, "%s: Line continuation on last line?\n",
1751 if (!strcmp("### MARKER ###", buf
))
1755 /* Since we ignore all included files (we only care about their
1756 #define-s here), we don't need to monitor filenames. The final
1757 line number directive is going to refer to the main source file
1762 p
= remove_leading_whitespaces (p
+ 1);
1763 if (!strncmp(p
, "line", 4))
1765 ln
= strtoul (p
, &end
, 10);
1766 if (ln
> 1 && ln
< INT_MAX
1767 && *remove_leading_whitespaces (end
) == '"')
1770 /* Ignore comments. */
1775 parse_template (p
, lineno
);
1783 last
= p
+ strlen (p
);
1786 name
= next_field (p
, ',', &str
, last
);
1788 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1792 /* Process opcode array. */
1793 for (j
= 0; j
< i
; j
++)
1795 const char *name
= opcode_array
[j
]->name
;
1796 struct opcode_entry
*next
;
1798 for (next
= &opcode_array
[j
]->entry
; next
; next
= next
->next
)
1801 lineno
= next
->lineno
;
1802 last
= str
+ strlen (str
);
1803 output_i386_opcode (table
, name
, str
, last
, lineno
);
1809 fprintf (table
, "};\n");
1811 /* Generate opcode sets array. */
1812 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1813 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1814 fprintf (table
, " i386_optab,\n");
1816 for (nr
= j
= 0; j
< i
; j
++)
1818 struct opcode_entry
*next
= &opcode_array
[j
]->entry
;
1826 fprintf (table
, " i386_optab + %u,\n", nr
);
1829 fprintf (table
, "};\n");
1831 /* Emit mnemonics and associated #define-s. */
1832 qsort (opcode_array
, i
, sizeof (*opcode_array
), mnemonic_cmp
);
1834 fp
= fopen ("i386-mnem.h", "w");
1836 fail ("can't create i386-mnem.h, errno = %s\n",
1839 process_copyright (fp
);
1841 fprintf (table
, "\n/* i386 mnemonics table. */\n\n");
1842 fprintf (table
, "const char i386_mnemonics[] =\n");
1843 fprintf (fp
, "\nextern const char i386_mnemonics[];\n\n");
1846 for (l
= strlen (opcode_array
[offs
= j
= 0]->name
); j
< i
; j
++)
1848 const char *name
= opcode_array
[j
]->name
;
1849 const char *next
= NULL
;
1850 size_t l1
= j
+ 1 < i
? strlen(next
= opcode_array
[j
+ 1]->name
) : 0;
1853 str
= mkident (name
);
1854 if (l
< l1
&& !strcmp(name
, next
+ l1
- l
))
1856 fprintf (fp
, "#define MN_%s ", str
);
1858 str
= mkident (next
);
1859 fprintf (fp
, "(MN_%s + %zu)\n", str
, l1
- l
);
1863 fprintf (table
, " \"\\0\"\"%s\"\n", name
);
1864 fprintf (fp
, "#define MN_%s %#x\n", str
, offs
+ 1);
1865 offs
+= strlen (name
) + 1;
1872 fprintf (table
, " \"\\0\"\".insn\"\n");
1873 fprintf (fp
, "#define MN__insn %#x\n", offs
+ 1);
1875 fprintf (table
, ";\n");
1881 process_i386_registers (FILE *table
)
1885 char *str
, *p
, *last
;
1886 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1887 char *dw2_32_num
, *dw2_64_num
;
1890 filename
= "i386-reg.tbl";
1891 fp
= fopen (filename
, "r");
1893 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1896 fprintf (table
, "\n/* i386 register table. */\n\n");
1897 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1901 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1906 p
= remove_leading_whitespaces (buf
);
1908 /* Skip comments. */
1909 str
= strstr (p
, "//");
1913 /* Remove trailing white spaces. */
1914 remove_trailing_whitespaces (p
);
1919 fprintf (table
, "%s\n", p
);
1927 last
= p
+ strlen (p
);
1929 /* Find reg_name. */
1930 reg_name
= next_field (p
, ',', &str
, last
);
1932 /* Find reg_type. */
1933 reg_type
= next_field (str
, ',', &str
, last
);
1935 /* Find reg_flags. */
1936 reg_flags
= next_field (str
, ',', &str
, last
);
1939 reg_num
= next_field (str
, ',', &str
, last
);
1941 fprintf (table
, " { \"%s\",\n ", reg_name
);
1943 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1946 /* Find 32-bit Dwarf2 register number. */
1947 dw2_32_num
= next_field (str
, ',', &str
, last
);
1949 /* Find 64-bit Dwarf2 register number. */
1950 dw2_64_num
= next_field (str
, ',', &str
, last
);
1952 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1953 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1958 fprintf (table
, "};\n");
1960 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1964 process_i386_initializers (void)
1967 FILE *fp
= fopen ("i386-init.h", "w");
1970 fail ("can't create i386-init.h, errno = %s\n",
1973 process_copyright (fp
);
1975 for (i
= 0; i
< CpuMax
; i
++)
1976 process_i386_cpu_flag (fp
, "0", cpu_flags
[i
].name
, "", " ", -1, i
);
1978 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); i
++)
1980 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
1982 process_i386_cpu_flag (fp
, deps
, isa_dependencies
[i
].name
,
1983 "", " ", -1, CpuMax
);
1987 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1988 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1989 one to 387. We want the reverse to be true though: Disabling 8087 also
1990 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1991 memcpy (isa_reverse_deps
[Cpu287
], isa_reverse_deps
[Cpu387
],
1992 sizeof (isa_reverse_deps
[0]));
1993 isa_reverse_deps
[Cpu287
][Cpu387
] = 1;
1994 memcpy (isa_reverse_deps
[Cpu8087
], isa_reverse_deps
[Cpu287
],
1995 sizeof (isa_reverse_deps
[0]));
1996 isa_reverse_deps
[Cpu8087
][Cpu287
] = 1;
1998 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1999 lead to disabling of anything else. */
2000 memset (isa_reverse_deps
[CpuPOPCNT
], 0, sizeof (isa_reverse_deps
[0]));
2002 for (i
= Cpu686
+ 1; i
< ARRAY_SIZE (isa_reverse_deps
); i
++)
2007 if (memchr(isa_reverse_deps
[i
], 1,
2008 ARRAY_SIZE (isa_reverse_deps
[0])) == NULL
)
2011 isa_reverse_deps
[i
][i
] = 1;
2012 process_i386_cpu_flag (fp
, NULL
, cpu_flags
[i
].name
, "", " ", -1, i
);
2020 /* Program options. */
2021 #define OPTION_SRCDIR 200
2023 struct option long_options
[] =
2025 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
2026 {"debug", no_argument
, NULL
, 'd'},
2027 {"version", no_argument
, NULL
, 'V'},
2028 {"help", no_argument
, NULL
, 'h'},
2029 {0, no_argument
, NULL
, 0}
2033 print_version (void)
2035 printf ("%s: version 1.0\n", program_name
);
2040 usage (FILE * stream
, int status
)
2042 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2048 main (int argc
, char **argv
)
2050 extern int chdir (char *);
2051 char *srcdir
= NULL
;
2053 unsigned int i
, cpumax
;
2056 program_name
= *argv
;
2057 xmalloc_set_program_name (program_name
);
2059 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2084 if (chdir (srcdir
) != 0)
2085 fail ("unable to change directory to \"%s\", errno = %s\n",
2086 srcdir
, xstrerror (errno
));
2088 /* cpu_flags isn't sorted by position. */
2090 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2091 if (cpu_flags
[i
].position
> cpumax
)
2092 cpumax
= cpu_flags
[i
].position
;
2094 /* Check the unused bitfield in i386_cpu_flags. */
2096 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2098 if ((cpumax
- 1) != CpuMax
)
2099 fail ("CpuMax != %d!\n", cpumax
);
2101 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2103 if (cpumax
!= CpuMax
)
2104 fail ("CpuMax != %d!\n", cpumax
);
2106 c
= CpuNumOfBits
- CpuMax
- 1;
2108 fail ("%d unused bits in i386_cpu_flags.\n", c
);
2111 /* If this triggers, CpuIsaBits needs to be increased. */
2112 static_assert (CpuAttrEnums
<= (1u << CpuIsaBits
));
2114 /* Check the unused bitfield in i386_cpu_attr. */
2115 #ifndef CpuAttrUnused
2116 c
= CpuAttrNumOfBits
- (CpuIsaBits
+ CpuMax
+ 1 - CpuAttrEnums
);
2118 fail ("%d unused bits in i386_cpu_attr.\n", c
);
2121 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2123 /* Check the unused bitfield in i386_operand_type. */
2125 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2128 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2131 c
= OTNumOfBits
- OTNum
;
2133 fail ("%d unused bits in i386_operand_type.\n", c
);
2136 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2139 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2140 sizeof (opcode_modifiers
[0]), compare
);
2142 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2143 sizeof (operand_types
[0]), compare
);
2145 table
= fopen ("i386-tbl.h", "w");
2147 fail ("can't create i386-tbl.h, errno = %s\n",
2150 process_copyright (table
);
2152 process_i386_opcodes (table
);
2153 process_i386_registers (table
);
2154 process_i386_initializers ();