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|CX16" },
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|PCLMUL|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|PCLMUL|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|PCLMUL|Movbe|Xsaveopt|PRFCHW" },
112 "586|687|CMOV|FXSR" },
189 { "AVX512_VPOPCNTDQ",
197 { "AVX512_VP2INTERSECT",
251 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
252 static unsigned char isa_reverse_deps
[Cpu64
][Cpu64
];
254 typedef struct bitfield
261 #define BITFIELD(n) { Cpu##n, 0, #n }
263 static bitfield cpu_flags
[] =
318 BITFIELD (LAHF_SAHF
),
337 BITFIELD (ClflushOpt
),
340 BITFIELD (PREFETCHWT1
),
344 BITFIELD (AVX512IFMA
),
345 BITFIELD (AVX512VBMI
),
346 BITFIELD (AVX512_4FMAPS
),
347 BITFIELD (AVX512_4VNNIW
),
348 BITFIELD (AVX512_VPOPCNTDQ
),
349 BITFIELD (AVX512_VBMI2
),
350 BITFIELD (AVX512_VNNI
),
351 BITFIELD (AVX512_BITALG
),
352 BITFIELD (AVX512_BF16
),
353 BITFIELD (AVX512_VP2INTERSECT
),
356 BITFIELD (AVX512_FP16
),
357 BITFIELD (PREFETCHI
),
359 BITFIELD (AVX_VNNI_INT8
),
360 BITFIELD (CMPCCXADD
),
363 BITFIELD (AVX_NE_CONVERT
),
374 BITFIELD (VPCLMULQDQ
),
383 BITFIELD (AMX_COMPLEX
),
386 BITFIELD (MOVDIR64B
),
388 BITFIELD (SERIALIZE
),
408 #define BITFIELD(n) { n, 0, #n }
410 static bitfield opcode_modifiers
[] =
419 BITFIELD (CheckOperandSize
),
420 BITFIELD (OperandConstraint
),
421 BITFIELD (MnemonicSize
),
430 BITFIELD (BNDPrefixOk
),
438 BITFIELD (OpcodePrefix
),
443 BITFIELD (Broadcast
),
444 BITFIELD (StaticRounding
),
446 BITFIELD (Disp8MemShift
),
448 BITFIELD (ATTMnemonic
),
449 BITFIELD (ATTSyntax
),
450 BITFIELD (IntelSyntax
),
454 #define CLASS(n) #n, n
456 static const struct {
458 enum operand_class value
;
459 } operand_classes
[] = {
473 #define INSTANCE(n) #n, n
475 static const struct {
477 enum operand_instance value
;
478 } operand_instances
[] = {
487 static bitfield operand_types
[] =
496 BITFIELD (BaseIndex
),
511 BITFIELD (Unspecified
),
517 static const char *filename
;
518 static i386_cpu_flags active_cpu_flags
;
519 static int active_isstring
;
521 struct template_arg
{
522 const struct template_arg
*next
;
526 struct template_instance
{
527 const struct template_instance
*next
;
529 const struct template_arg
*args
;
532 struct template_param
{
533 const struct template_param
*next
;
538 struct template *next
;
540 const struct template_instance
*instances
;
541 const struct template_param
*params
;
544 static struct template *templates
;
547 compare (const void *x
, const void *y
)
549 const bitfield
*xp
= (const bitfield
*) x
;
550 const bitfield
*yp
= (const bitfield
*) y
;
551 return xp
->position
- yp
->position
;
555 fail (const char *message
, ...)
559 va_start (args
, message
);
560 fprintf (stderr
, "%s: error: ", program_name
);
561 vfprintf (stderr
, message
, args
);
567 process_copyright (FILE *fp
)
569 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
570 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
572 This file is part of the GNU opcodes library.\n\
574 This library is free software; you can redistribute it and/or modify\n\
575 it under the terms of the GNU General Public License as published by\n\
576 the Free Software Foundation; either version 3, or (at your option)\n\
577 any later version.\n\
579 It is distributed in the hope that it will be useful, but WITHOUT\n\
580 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
581 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
582 License for more details.\n\
584 You should have received a copy of the GNU General Public License\n\
585 along with this program; if not, write to the Free Software\n\
586 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
587 MA 02110-1301, USA. */\n");
590 /* Remove leading white spaces. */
593 remove_leading_whitespaces (char *str
)
595 while (ISSPACE (*str
))
600 /* Remove trailing white spaces. */
603 remove_trailing_whitespaces (char *str
)
605 size_t last
= strlen (str
);
613 if (ISSPACE (str
[last
]))
621 /* Find next field separated by SEP and terminate it. Return a
622 pointer to the one after it. */
625 next_field (char *str
, char sep
, char **next
, char *last
)
629 p
= remove_leading_whitespaces (str
);
630 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
633 remove_trailing_whitespaces (p
);
643 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
646 set_bitfield (char *f
, bitfield
*array
, int value
,
647 unsigned int size
, int lineno
)
651 /* Ignore empty fields; they may result from template expansions. */
655 for (i
= 0; i
< size
; i
++)
656 if (strcasecmp (array
[i
].name
, f
) == 0)
658 array
[i
].value
= value
;
664 const char *v
= strchr (f
, '=');
671 for (i
= 0; i
< size
; i
++)
672 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
674 value
= strtol (v
+ 1, &end
, 0);
677 array
[i
].value
= value
;
686 fail ("%s: %d: unknown bitfield: %s\n", filename
, lineno
, f
);
688 fail ("unknown bitfield: %s\n", f
);
692 add_isa_dependencies (bitfield
*flags
, const char *f
, int value
,
693 unsigned int reverse
)
698 bool is_isa
= false, is_avx
= false;
700 /* Need to find base entry for references to auxiliary ones. */
704 *strchr (str
, ':') = '\0';
707 for (i
= 0; i
< Cpu64
; ++i
)
708 if (strcasecmp (flags
[i
].name
, isa
) == 0)
710 flags
[i
].value
= value
;
711 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0])
712 /* Don't record the feature itself here. */
714 /* Don't record base architectures. */
716 isa_reverse_deps
[i
][reverse
] = 1;
718 if (i
== CpuAVX
|| i
== CpuXOP
)
724 /* Do not turn off dependencies. */
725 if (is_isa
&& !value
)
728 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); ++i
)
729 if (strcasecmp (isa_dependencies
[i
].name
, f
) == 0)
731 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
733 char *last
= deps
+ strlen (deps
);
735 for (; next
&& next
< last
; )
737 char *str
= next_field (next
, '|', &next
, last
);
739 /* No AVX/XOP -> SSE reverse dependencies. */
740 if (is_avx
&& strncmp (str
, "SSE", 3) == 0)
741 add_isa_dependencies (flags
, str
, value
, CpuMax
);
743 add_isa_dependencies (flags
, str
, value
, reverse
);
747 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
748 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0]))
749 isa_reverse_deps
[reverse
][reverse
] = 1;
755 fail ("unknown bitfield: %s\n", f
);
759 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
760 int macro
, const char *comma
, const char *indent
)
764 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
766 fprintf (table
, "%s{ { ", indent
);
768 for (i
= 0; i
< size
- 1; i
++)
770 if (((i
+ 1) % 20) != 0)
771 fprintf (table
, "%d, ", flags
[i
].value
);
773 fprintf (table
, "%d,", flags
[i
].value
);
774 if (((i
+ 1) % 20) == 0)
776 /* We need \\ for macro. */
778 fprintf (table
, " \\\n %s", indent
);
780 fprintf (table
, "\n %s", indent
);
783 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
786 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
790 process_i386_cpu_flag (FILE *table
, char *flag
,
792 const char *comma
, const char *indent
,
793 int lineno
, unsigned int reverse
)
795 char *str
, *next
= flag
, *last
;
799 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
801 /* Copy the default cpu flags. */
802 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
806 for (i
= 0; i
< ARRAY_SIZE (isa_reverse_deps
[0]); ++i
)
807 flags
[i
].value
= isa_reverse_deps
[reverse
][i
];
813 last
= flag
+ strlen (flag
);
820 fail ("%s: %d: missing `)' in bitfield: %s\n", filename
,
827 /* First we turn on everything except for cpu64, cpuno64, and - if
828 present - the padding field. */
829 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
830 if (flags
[i
].position
< Cpu64
)
833 /* Turn off selective bits. */
837 if (name
!= NULL
&& value
!= 0)
839 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
840 if (strcasecmp (flags
[i
].name
, name
) == 0)
842 add_isa_dependencies (flags
, name
, 1, reverse
);
848 if (strcmp (flag
, "0"))
853 /* Turn on/off selective bits. */
854 last
= flag
+ strlen (flag
);
855 for (; next
&& next
< last
; )
857 str
= next_field (next
, '|', &next
, last
);
859 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
861 add_isa_dependencies (flags
, str
, value
, reverse
);
868 size_t len
= strlen (name
);
869 char *upper
= xmalloc (len
+ 1);
871 for (i
= 0; i
< len
; ++i
)
873 /* Don't emit #define-s for auxiliary entries. */
876 upper
[i
] = TOUPPER (name
[i
]);
879 fprintf (table
, "\n#define CPU_%s%s_FLAGS \\\n",
880 flag
!= NULL
? "": "ANY_", upper
);
884 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), name
!= NULL
,
889 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
893 fprintf (table
, " { ");
895 for (i
= 0; i
< size
- 1; i
++)
897 if (((i
+ 1) % 20) != 0)
898 fprintf (table
, "%d, ", modifier
[i
].value
);
900 fprintf (table
, "%d,", modifier
[i
].value
);
901 if (((i
+ 1) % 20) == 0)
902 fprintf (table
, "\n ");
905 fprintf (table
, "%d },\n", modifier
[i
].value
);
908 /* Returns LOG2 of element size. */
910 get_element_size (char **opnd
, int lineno
)
912 char *str
, *next
, *last
, *op
;
913 const char *full
= opnd
[0];
914 int elem_size
= INT_MAX
;
916 /* Find the memory operand. */
917 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
920 fail ("%s: %d: no memory operand\n", filename
, lineno
);
923 last
= op
+ strlen (op
);
924 for (next
= op
; next
&& next
< last
; )
926 str
= next_field (next
, '|', &next
, last
);
929 if (strcasecmp(str
, "Byte") == 0)
931 /* The smallest element size, no need to check
936 else if (strcasecmp(str
, "Word") == 0)
941 else if (strcasecmp(str
, "Dword") == 0)
946 else if (strcasecmp(str
, "Qword") == 0)
955 if (elem_size
== INT_MAX
)
956 fail ("%s: %d: unknown element size: %s\n", filename
, lineno
, full
);
962 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
963 unsigned int prefix
, const char *extension_opcode
,
964 char **opnd
, int lineno
)
966 char *str
, *next
, *last
;
967 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
968 static const char *const spaces
[] = {
969 #define SPACE(n) [SPACE_##n] = #n
984 /* Copy the default opcode modifier. */
985 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
987 if (strcmp (mod
, "0"))
989 unsigned int have_w
= 0, bwlq_suf
= 0xf;
991 last
= mod
+ strlen (mod
);
992 for (next
= mod
; next
&& next
< last
; )
994 str
= next_field (next
, '|', &next
, last
);
999 if (strncmp(str
, "OpcodeSpace", 11) == 0)
1004 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1007 val
= strtol (str
+ 12, &end
, 0);
1009 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1010 filename
, lineno
, end
);
1015 fail ("%s:%d: Conflicting opcode space specifications\n",
1018 "%s:%d: Warning: redundant opcode space specification\n",
1026 if (strcasecmp(str
, "Broadcast") == 0)
1027 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1028 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1029 val
= get_element_size (opnd
, lineno
);
1031 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1033 if (strcasecmp(str
, "IsString") == 0)
1034 active_isstring
= 1;
1036 if (strcasecmp(str
, "W") == 0)
1039 if (strcasecmp(str
, "No_bSuf") == 0)
1041 if (strcasecmp(str
, "No_wSuf") == 0)
1043 if (strcasecmp(str
, "No_lSuf") == 0)
1045 if (strcasecmp(str
, "No_qSuf") == 0)
1052 if (!modifiers
[OpcodePrefix
].value
)
1053 modifiers
[OpcodePrefix
].value
= prefix
;
1054 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1055 fail ("%s:%d: Conflicting prefix specifications\n",
1059 "%s:%d: Warning: redundant prefix specification\n",
1063 if (have_w
&& !bwlq_suf
)
1064 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1065 if (have_w
&& !(bwlq_suf
& 1))
1066 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1068 if (have_w
&& !(bwlq_suf
& ~1))
1070 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1074 if (space
>= ARRAY_SIZE (spaces
) || !spaces
[space
])
1075 fail ("%s:%d: Unknown opcode space %u\n", filename
, lineno
, space
);
1077 fprintf (table
, " SPACE_%s, %s,\n",
1078 spaces
[space
], extension_opcode
? extension_opcode
: "None");
1080 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1090 output_operand_type (FILE *table
, enum operand_class
class,
1091 enum operand_instance instance
,
1092 const bitfield
*types
, unsigned int size
,
1093 enum stage stage
, const char *indent
)
1097 fprintf (table
, "{ { %d, %d, ", class, instance
);
1099 for (i
= 0; i
< size
- 1; i
++)
1101 if (((i
+ 3) % 20) != 0)
1102 fprintf (table
, "%d, ", types
[i
].value
);
1104 fprintf (table
, "%d,", types
[i
].value
);
1105 if (((i
+ 3) % 20) == 0)
1107 /* We need \\ for macro. */
1108 if (stage
== stage_macros
)
1109 fprintf (table
, " \\\n%s", indent
);
1111 fprintf (table
, "\n%s", indent
);
1115 fprintf (table
, "%d } }", types
[i
].value
);
1119 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1120 const char *indent
, int lineno
)
1122 char *str
, *next
, *last
;
1123 enum operand_class
class = ClassNone
;
1124 enum operand_instance instance
= InstanceNone
;
1125 bitfield types
[ARRAY_SIZE (operand_types
)];
1127 /* Copy the default operand type. */
1128 memcpy (types
, operand_types
, sizeof (types
));
1130 if (strcmp (op
, "0"))
1134 last
= op
+ strlen (op
);
1135 for (next
= op
; next
&& next
< last
; )
1137 str
= next_field (next
, '|', &next
, last
);
1142 if (!strncmp(str
, "Class=", 6))
1144 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1145 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1147 class = operand_classes
[i
].value
;
1153 if (str
&& !strncmp(str
, "Instance=", 9))
1155 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1156 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1158 instance
= operand_instances
[i
].value
;
1166 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1167 if (strcasecmp(str
, "BaseIndex") == 0)
1172 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1174 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1175 if (!active_cpu_flags
.bitfield
.cpu64
1176 && !active_cpu_flags
.bitfield
.cpumpx
)
1177 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1178 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1181 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1185 static char *mkident (const char *mnem
)
1187 char *ident
= xstrdup (mnem
), *p
= ident
;
1200 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1201 char *last
, int lineno
)
1203 unsigned int i
, length
, prefix
= 0, space
= 0;
1204 char *base_opcode
, *extension_opcode
, *end
, *ident
;
1205 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1206 unsigned long long opcode
;
1208 /* Find base_opcode. */
1209 base_opcode
= next_field (str
, ',', &str
, last
);
1211 /* Find extension_opcode, if any. */
1212 extension_opcode
= strchr (base_opcode
, '/');
1213 if (extension_opcode
)
1214 *extension_opcode
++ = '\0';
1216 /* Find cpu_flags. */
1217 cpu_flags
= next_field (str
, ',', &str
, last
);
1219 /* Find opcode_modifier. */
1220 opcode_modifier
= next_field (str
, ',', &str
, last
);
1222 /* Remove the first {. */
1223 str
= remove_leading_whitespaces (str
);
1226 str
= remove_leading_whitespaces (str
+ 1);
1227 remove_trailing_whitespaces (str
);
1229 /* Remove } and trailing white space. */
1231 if (!i
|| str
[i
- 1] != '}')
1234 remove_trailing_whitespaces (str
);
1237 operand_types
[i
= 0] = NULL
;
1240 last
= str
+ strlen (str
);
1242 /* Find operand_types. */
1243 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1247 operand_types
[i
] = NULL
;
1251 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1255 opcode
= strtoull (base_opcode
, &end
, 0);
1257 /* Determine opcode length. */
1258 for (length
= 1; length
< 8; ++length
)
1259 if (!(opcode
>> (8 * length
)))
1262 /* Transform prefixes encoded in the opcode into opcode modifier
1266 switch (opcode
>> (8 * length
- 8))
1268 case 0x66: prefix
= PREFIX_0X66
; break;
1269 case 0xF3: prefix
= PREFIX_0XF3
; break;
1270 case 0xF2: prefix
= PREFIX_0XF2
; break;
1274 opcode
&= (1ULL << (8 * --length
)) - 1;
1277 /* Transform opcode space encoded in the opcode into opcode modifier
1279 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1281 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1283 default: space
= SPACE_0F
; break;
1284 case 0x38: space
= SPACE_0F38
; break;
1285 case 0x3A: space
= SPACE_0F3A
; break;
1288 if (space
!= SPACE_0F
&& --length
== 1)
1289 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1290 filename
, lineno
, name
);
1291 opcode
&= (1ULL << (8 * --length
)) - 1;
1295 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1296 filename
, lineno
, name
, 2 * length
, opcode
);
1298 ident
= mkident (name
);
1299 fprintf (table
, " { MN_%s, 0x%0*llx%s, %u,",
1300 ident
, 2 * (int)length
, opcode
, end
, i
);
1303 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1304 extension_opcode
, operand_types
, lineno
);
1306 process_i386_cpu_flag (table
, cpu_flags
, NULL
, ",", " ", lineno
, CpuMax
);
1308 fprintf (table
, " { ");
1310 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1312 if (!operand_types
[i
])
1315 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1321 fprintf (table
, ",\n ");
1323 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1326 fprintf (table
, " } },\n");
1329 struct opcode_hash_entry
1334 struct opcode_entry
*next
;
1340 /* Calculate the hash value of an opcode hash entry P. */
1343 opcode_hash_hash (const void *p
)
1345 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1346 return htab_hash_string (entry
->name
);
1349 /* Compare a string Q against an opcode hash entry P. */
1352 opcode_hash_eq (const void *p
, const void *q
)
1354 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1355 const char *name
= (const char *) q
;
1356 return strcmp (name
, entry
->name
) == 0;
1360 parse_template (char *buf
, int lineno
)
1362 char sep
, *end
, *name
;
1363 struct template *tmpl
;
1364 struct template_instance
*last_inst
= NULL
;
1366 buf
= remove_leading_whitespaces (buf
+ 1);
1367 end
= strchr (buf
, ':');
1370 struct template *prev
= NULL
;
1372 end
= strchr (buf
, '>');
1374 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1375 if (*remove_leading_whitespaces (end
+ 1))
1376 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1378 remove_trailing_whitespaces (buf
);
1379 /* Don't bother freeing the various structures. */
1380 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1381 if (!strcmp (buf
, tmpl
->name
))
1384 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1386 prev
->next
= tmpl
->next
;
1388 templates
= tmpl
->next
;
1392 remove_trailing_whitespaces (buf
);
1395 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1396 tmpl
= xmalloc (sizeof (*tmpl
));
1397 tmpl
->name
= xstrdup (buf
);
1399 tmpl
->params
= NULL
;
1401 struct template_param
*param
;
1403 buf
= remove_leading_whitespaces (end
);
1404 end
= strpbrk (buf
, ":,");
1406 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1410 remove_trailing_whitespaces (buf
);
1412 param
= xmalloc (sizeof (*param
));
1413 param
->name
= xstrdup (buf
);
1414 param
->next
= tmpl
->params
;
1415 tmpl
->params
= param
;
1416 } while (sep
== ':');
1418 tmpl
->instances
= NULL
;
1420 struct template_instance
*inst
;
1422 const struct template_param
*param
;
1424 buf
= remove_leading_whitespaces (end
);
1425 end
= strpbrk (buf
, ",>");
1427 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1432 inst
= xmalloc (sizeof (*inst
));
1436 cur
= next_field (buf
, ':', &next
, end
);
1437 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1439 for (param
= tmpl
->params
; param
; param
= param
->next
)
1441 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1443 cur
= next_field (next
, ':', &next
, end
);
1445 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1446 arg
->val
= xstrdup (cur
);
1447 arg
->next
= inst
->args
;
1451 if (tmpl
->instances
)
1452 last_inst
->next
= inst
;
1454 tmpl
->instances
= inst
;
1456 } while (sep
== ',');
1458 buf
= remove_leading_whitespaces (end
);
1460 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1461 filename
, lineno
, buf
);
1463 tmpl
->next
= templates
;
1468 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1469 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1471 static unsigned int idx
, opcode_array_size
;
1472 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1473 struct opcode_hash_entry
**hash_slot
;
1474 struct opcode_entry
*entry
;
1475 char *ptr1
= strchr(name
, '<'), *ptr2
;
1479 /* Get the slot in hash table. */
1480 hash_slot
= (struct opcode_hash_entry
**)
1481 htab_find_slot_with_hash (opcode_hash_table
, name
,
1482 htab_hash_string (name
),
1485 if (*hash_slot
== NULL
)
1487 /* It is the new one. Put it on opcode array. */
1488 if (idx
>= opcode_array_size
)
1490 /* Grow the opcode array when needed. */
1491 opcode_array_size
+= 1024;
1492 opcode_array
= (struct opcode_hash_entry
**)
1493 xrealloc (opcode_array
,
1494 sizeof (*opcode_array
) * opcode_array_size
);
1495 *opcode_array_p
= opcode_array
;
1498 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1499 xmalloc (sizeof (struct opcode_hash_entry
));
1500 opcode_array
[idx
]->name
= xstrdup (name
);
1501 *hash_slot
= opcode_array
[idx
];
1502 entry
= &opcode_array
[idx
]->entry
;
1507 /* Append it to the existing one. */
1508 struct opcode_entry
**entryp
= &(*hash_slot
)->entry
.next
;
1510 while (*entryp
!= NULL
)
1511 entryp
= &(*entryp
)->next
;
1512 entry
= (struct opcode_entry
*)xmalloc (sizeof (struct opcode_entry
));
1517 entry
->opcode
= xstrdup (str
);
1518 entry
->lineno
= lineno
;
1520 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1521 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1524 const struct template *tmpl
;
1525 const struct template_instance
*inst
;
1528 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1529 remove_trailing_whitespaces (ptr1
);
1533 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1534 if (!strcmp(ptr1
, tmpl
->name
))
1537 fail ("reference to unknown template '%s'\n", ptr1
);
1539 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1541 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1542 char *str2
= xmalloc(2 * strlen(str
));
1545 strcpy (name2
, name
);
1546 strcat (name2
, inst
->name
);
1547 strcat (name2
, ptr2
);
1549 for (ptr1
= str2
, src
= str
; *src
; )
1551 const char *ident
= tmpl
->name
, *end
;
1552 const struct template_param
*param
;
1553 const struct template_arg
*arg
;
1555 if ((*ptr1
= *src
++) != '<')
1560 while (ISSPACE(*src
))
1562 while (*ident
&& *src
== *ident
)
1564 while (ISSPACE(*src
))
1566 if (*src
!= ':' || *ident
!= '\0')
1568 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1569 ptr1
+= ident
- tmpl
->name
;
1572 while (ISSPACE(*++src
))
1576 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1579 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1580 param
= param
->next
, arg
= arg
->next
)
1582 if (end
- src
== strlen (param
->name
)
1583 && !memcmp (src
, param
->name
, end
- src
))
1591 fail ("template '%s' has no parameter '%.*s'\n",
1592 tmpl
->name
, (int)(end
- src
), src
);
1594 while (ISSPACE(*src
))
1597 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1599 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1600 ptr1
+= strlen(arg
->val
);
1606 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1617 static int mnemonic_cmp(const void *p1
, const void *p2
)
1619 const struct opcode_hash_entry
*const *e1
= p1
, *const *e2
= p2
;
1620 const char *s1
= (*e1
)->name
, *s2
= (*e2
)->name
;
1622 size_t l1
= strlen (s1
), l2
= strlen (s2
);
1624 for (i
= 1; i
<= l1
&& i
<= l2
; ++i
)
1626 if (s1
[l1
- i
] != s2
[l2
- i
])
1627 return (unsigned char)s1
[l1
- i
] - (unsigned char)s2
[l2
- i
];
1630 return (int)(l1
- l2
);
1634 process_i386_opcodes (FILE *table
)
1638 unsigned int i
, j
, nr
, offs
;
1640 char *str
, *p
, *last
;
1641 htab_t opcode_hash_table
;
1642 struct opcode_hash_entry
**opcode_array
= NULL
;
1643 int lineno
= 0, marker
= 0;
1645 filename
= "i386-opc.tbl";
1649 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1650 opcode_hash_eq
, NULL
,
1653 fprintf (table
, "\n#include \"i386-mnem.h\"\n");
1654 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1655 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1657 /* Put everything on opcode array. */
1662 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1665 p
= remove_leading_whitespaces (buf
);
1671 /* Skip comments. */
1672 str
= strstr (p
, "//");
1676 remove_trailing_whitespaces (p
);
1680 /* Look for line continuation character. */
1681 remove_trailing_whitespaces (p
);
1683 if (!j
|| buf
[j
- 1] != '+')
1685 if (j
>= sizeof (buf
) - 1)
1686 fail ("%s: %d: (continued) line too long\n", filename
, lineno
);
1688 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1690 fprintf (stderr
, "%s: Line continuation on last line?\n",
1699 if (!strcmp("### MARKER ###", buf
))
1703 /* Since we ignore all included files (we only care about their
1704 #define-s here), we don't need to monitor filenames. The final
1705 line number directive is going to refer to the main source file
1710 p
= remove_leading_whitespaces (p
+ 1);
1711 if (!strncmp(p
, "line", 4))
1713 ln
= strtoul (p
, &end
, 10);
1714 if (ln
> 1 && ln
< INT_MAX
1715 && *remove_leading_whitespaces (end
) == '"')
1718 /* Ignore comments. */
1723 parse_template (p
, lineno
);
1731 last
= p
+ strlen (p
);
1734 name
= next_field (p
, ',', &str
, last
);
1736 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1740 /* Process opcode array. */
1741 for (j
= 0; j
< i
; j
++)
1743 const char *name
= opcode_array
[j
]->name
;
1744 struct opcode_entry
*next
;
1746 for (next
= &opcode_array
[j
]->entry
; next
; next
= next
->next
)
1749 lineno
= next
->lineno
;
1750 last
= str
+ strlen (str
);
1751 output_i386_opcode (table
, name
, str
, last
, lineno
);
1757 fprintf (table
, "};\n");
1759 /* Generate opcode sets array. */
1760 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1761 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1762 fprintf (table
, " i386_optab,\n");
1764 for (nr
= j
= 0; j
< i
; j
++)
1766 struct opcode_entry
*next
= &opcode_array
[j
]->entry
;
1774 fprintf (table
, " i386_optab + %u,\n", nr
);
1777 fprintf (table
, "};\n");
1779 /* Emit mnemonics and associated #define-s. */
1780 qsort (opcode_array
, i
, sizeof (*opcode_array
), mnemonic_cmp
);
1782 fp
= fopen ("i386-mnem.h", "w");
1784 fail ("can't create i386-mnem.h, errno = %s\n",
1787 process_copyright (fp
);
1789 fprintf (table
, "\n/* i386 mnemonics table. */\n\n");
1790 fprintf (table
, "const char i386_mnemonics[] =\n");
1791 fprintf (fp
, "\nextern const char i386_mnemonics[];\n\n");
1794 for (l
= strlen (opcode_array
[offs
= j
= 0]->name
); j
< i
; j
++)
1796 const char *name
= opcode_array
[j
]->name
;
1797 const char *next
= NULL
;
1798 size_t l1
= j
+ 1 < i
? strlen(next
= opcode_array
[j
+ 1]->name
) : 0;
1801 str
= mkident (name
);
1802 if (l
< l1
&& !strcmp(name
, next
+ l1
- l
))
1804 fprintf (fp
, "#define MN_%s ", str
);
1806 str
= mkident (next
);
1807 fprintf (fp
, "(MN_%s + %u)\n", str
, l1
- l
);
1811 fprintf (table
, " \"\\0\"\"%s\"\n", name
);
1812 fprintf (fp
, "#define MN_%s %#x\n", str
, offs
+ 1);
1813 offs
+= strlen (name
) + 1;
1820 fprintf (table
, " \"\\0\"\".insn\"\n");
1821 fprintf (fp
, "#define MN__insn %#x\n", offs
+ 1);
1823 fprintf (table
, ";\n");
1829 process_i386_registers (FILE *table
)
1833 char *str
, *p
, *last
;
1834 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1835 char *dw2_32_num
, *dw2_64_num
;
1838 filename
= "i386-reg.tbl";
1839 fp
= fopen (filename
, "r");
1841 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1844 fprintf (table
, "\n/* i386 register table. */\n\n");
1845 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1849 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1854 p
= remove_leading_whitespaces (buf
);
1856 /* Skip comments. */
1857 str
= strstr (p
, "//");
1861 /* Remove trailing white spaces. */
1862 remove_trailing_whitespaces (p
);
1867 fprintf (table
, "%s\n", p
);
1875 last
= p
+ strlen (p
);
1877 /* Find reg_name. */
1878 reg_name
= next_field (p
, ',', &str
, last
);
1880 /* Find reg_type. */
1881 reg_type
= next_field (str
, ',', &str
, last
);
1883 /* Find reg_flags. */
1884 reg_flags
= next_field (str
, ',', &str
, last
);
1887 reg_num
= next_field (str
, ',', &str
, last
);
1889 fprintf (table
, " { \"%s\",\n ", reg_name
);
1891 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1894 /* Find 32-bit Dwarf2 register number. */
1895 dw2_32_num
= next_field (str
, ',', &str
, last
);
1897 /* Find 64-bit Dwarf2 register number. */
1898 dw2_64_num
= next_field (str
, ',', &str
, last
);
1900 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1901 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1906 fprintf (table
, "};\n");
1908 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1912 process_i386_initializers (void)
1915 FILE *fp
= fopen ("i386-init.h", "w");
1918 fail ("can't create i386-init.h, errno = %s\n",
1921 process_copyright (fp
);
1923 for (i
= 0; i
< Cpu64
; i
++)
1924 process_i386_cpu_flag (fp
, "0", cpu_flags
[i
].name
, "", " ", -1, i
);
1926 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); i
++)
1928 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
1930 process_i386_cpu_flag (fp
, deps
, isa_dependencies
[i
].name
,
1931 "", " ", -1, CpuMax
);
1935 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1936 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1937 one to 387. We want the reverse to be true though: Disabling 8087 also
1938 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1939 memcpy (isa_reverse_deps
[Cpu287
], isa_reverse_deps
[Cpu387
],
1940 sizeof (isa_reverse_deps
[0]));
1941 isa_reverse_deps
[Cpu287
][Cpu387
] = 1;
1942 memcpy (isa_reverse_deps
[Cpu8087
], isa_reverse_deps
[Cpu287
],
1943 sizeof (isa_reverse_deps
[0]));
1944 isa_reverse_deps
[Cpu8087
][Cpu287
] = 1;
1946 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1947 lead to disabling of anything else. */
1948 memset (isa_reverse_deps
[CpuPOPCNT
], 0, sizeof (isa_reverse_deps
[0]));
1950 for (i
= Cpu686
+ 1; i
< ARRAY_SIZE (isa_reverse_deps
); i
++)
1955 if (memchr(isa_reverse_deps
[i
], 1,
1956 ARRAY_SIZE (isa_reverse_deps
[0])) == NULL
)
1959 isa_reverse_deps
[i
][i
] = 1;
1960 process_i386_cpu_flag (fp
, NULL
, cpu_flags
[i
].name
, "", " ", -1, i
);
1968 /* Program options. */
1969 #define OPTION_SRCDIR 200
1971 struct option long_options
[] =
1973 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1974 {"debug", no_argument
, NULL
, 'd'},
1975 {"version", no_argument
, NULL
, 'V'},
1976 {"help", no_argument
, NULL
, 'h'},
1977 {0, no_argument
, NULL
, 0}
1981 print_version (void)
1983 printf ("%s: version 1.0\n", program_name
);
1988 usage (FILE * stream
, int status
)
1990 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1996 main (int argc
, char **argv
)
1998 extern int chdir (char *);
1999 char *srcdir
= NULL
;
2001 unsigned int i
, cpumax
;
2004 program_name
= *argv
;
2005 xmalloc_set_program_name (program_name
);
2007 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2032 if (chdir (srcdir
) != 0)
2033 fail ("unable to change directory to \"%s\", errno = %s\n",
2034 srcdir
, xstrerror (errno
));
2036 /* cpu_flags isn't sorted by position. */
2038 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2039 if (cpu_flags
[i
].position
> cpumax
)
2040 cpumax
= cpu_flags
[i
].position
;
2042 /* Check the unused bitfield in i386_cpu_flags. */
2044 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2046 if ((cpumax
- 1) != CpuMax
)
2047 fail ("CpuMax != %d!\n", cpumax
);
2049 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2051 if (cpumax
!= CpuMax
)
2052 fail ("CpuMax != %d!\n", cpumax
);
2054 c
= CpuNumOfBits
- CpuMax
- 1;
2056 fail ("%d unused bits in i386_cpu_flags.\n", c
);
2059 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2061 /* Check the unused bitfield in i386_operand_type. */
2063 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2066 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2069 c
= OTNumOfBits
- OTNum
;
2071 fail ("%d unused bits in i386_operand_type.\n", c
);
2074 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2077 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2078 sizeof (opcode_modifiers
[0]), compare
);
2080 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2081 sizeof (operand_types
[0]), compare
);
2083 table
= fopen ("i386-tbl.h", "w");
2085 fail ("can't create i386-tbl.h, errno = %s\n",
2088 process_copyright (table
);
2090 process_i386_opcodes (table
);
2091 process_i386_registers (table
);
2092 process_i386_initializers ();