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",
249 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
250 static unsigned char isa_reverse_deps
[Cpu64
][Cpu64
];
252 typedef struct bitfield
259 #define BITFIELD(n) { Cpu##n, 0, #n }
261 static bitfield cpu_flags
[] =
316 BITFIELD (LAHF_SAHF
),
335 BITFIELD (ClflushOpt
),
338 BITFIELD (PREFETCHWT1
),
342 BITFIELD (AVX512IFMA
),
343 BITFIELD (AVX512VBMI
),
344 BITFIELD (AVX512_4FMAPS
),
345 BITFIELD (AVX512_4VNNIW
),
346 BITFIELD (AVX512_VPOPCNTDQ
),
347 BITFIELD (AVX512_VBMI2
),
348 BITFIELD (AVX512_VNNI
),
349 BITFIELD (AVX512_BITALG
),
350 BITFIELD (AVX512_BF16
),
351 BITFIELD (AVX512_VP2INTERSECT
),
354 BITFIELD (AVX512_FP16
),
355 BITFIELD (PREFETCHI
),
357 BITFIELD (AVX_VNNI_INT8
),
358 BITFIELD (CMPCCXADD
),
361 BITFIELD (AVX_NE_CONVERT
),
372 BITFIELD (VPCLMULQDQ
),
383 BITFIELD (MOVDIR64B
),
385 BITFIELD (SERIALIZE
),
405 #define BITFIELD(n) { n, 0, #n }
407 static bitfield opcode_modifiers
[] =
416 BITFIELD (CheckOperandSize
),
417 BITFIELD (OperandConstraint
),
418 BITFIELD (MnemonicSize
),
427 BITFIELD (BNDPrefixOk
),
435 BITFIELD (OpcodePrefix
),
440 BITFIELD (Broadcast
),
441 BITFIELD (StaticRounding
),
443 BITFIELD (Disp8MemShift
),
445 BITFIELD (ATTMnemonic
),
446 BITFIELD (ATTSyntax
),
447 BITFIELD (IntelSyntax
),
451 #define CLASS(n) #n, n
453 static const struct {
455 enum operand_class value
;
456 } operand_classes
[] = {
470 #define INSTANCE(n) #n, n
472 static const struct {
474 enum operand_instance value
;
475 } operand_instances
[] = {
484 static bitfield operand_types
[] =
493 BITFIELD (BaseIndex
),
508 BITFIELD (Unspecified
),
514 static const char *filename
;
515 static i386_cpu_flags active_cpu_flags
;
516 static int active_isstring
;
518 struct template_arg
{
519 const struct template_arg
*next
;
523 struct template_instance
{
524 const struct template_instance
*next
;
526 const struct template_arg
*args
;
529 struct template_param
{
530 const struct template_param
*next
;
535 struct template *next
;
537 const struct template_instance
*instances
;
538 const struct template_param
*params
;
541 static struct template *templates
;
544 compare (const void *x
, const void *y
)
546 const bitfield
*xp
= (const bitfield
*) x
;
547 const bitfield
*yp
= (const bitfield
*) y
;
548 return xp
->position
- yp
->position
;
552 fail (const char *message
, ...)
556 va_start (args
, message
);
557 fprintf (stderr
, "%s: error: ", program_name
);
558 vfprintf (stderr
, message
, args
);
564 process_copyright (FILE *fp
)
566 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
567 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
569 This file is part of the GNU opcodes library.\n\
571 This library is free software; you can redistribute it and/or modify\n\
572 it under the terms of the GNU General Public License as published by\n\
573 the Free Software Foundation; either version 3, or (at your option)\n\
574 any later version.\n\
576 It is distributed in the hope that it will be useful, but WITHOUT\n\
577 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
578 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
579 License for more details.\n\
581 You should have received a copy of the GNU General Public License\n\
582 along with this program; if not, write to the Free Software\n\
583 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
584 MA 02110-1301, USA. */\n");
587 /* Remove leading white spaces. */
590 remove_leading_whitespaces (char *str
)
592 while (ISSPACE (*str
))
597 /* Remove trailing white spaces. */
600 remove_trailing_whitespaces (char *str
)
602 size_t last
= strlen (str
);
610 if (ISSPACE (str
[last
]))
618 /* Find next field separated by SEP and terminate it. Return a
619 pointer to the one after it. */
622 next_field (char *str
, char sep
, char **next
, char *last
)
626 p
= remove_leading_whitespaces (str
);
627 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
630 remove_trailing_whitespaces (p
);
640 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
643 set_bitfield (char *f
, bitfield
*array
, int value
,
644 unsigned int size
, int lineno
)
648 /* Ignore empty fields; they may result from template expansions. */
652 for (i
= 0; i
< size
; i
++)
653 if (strcasecmp (array
[i
].name
, f
) == 0)
655 array
[i
].value
= value
;
661 const char *v
= strchr (f
, '=');
668 for (i
= 0; i
< size
; i
++)
669 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
671 value
= strtol (v
+ 1, &end
, 0);
674 array
[i
].value
= value
;
683 fail ("%s: %d: unknown bitfield: %s\n", filename
, lineno
, f
);
685 fail ("unknown bitfield: %s\n", f
);
689 add_isa_dependencies (bitfield
*flags
, const char *f
, int value
,
690 unsigned int reverse
)
695 bool is_isa
= false, is_avx
= false;
697 /* Need to find base entry for references to auxiliary ones. */
701 *strchr (str
, ':') = '\0';
704 for (i
= 0; i
< Cpu64
; ++i
)
705 if (strcasecmp (flags
[i
].name
, isa
) == 0)
707 flags
[i
].value
= value
;
708 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0])
709 /* Don't record the feature itself here. */
711 /* Don't record base architectures. */
713 isa_reverse_deps
[i
][reverse
] = 1;
715 if (i
== CpuAVX
|| i
== CpuXOP
)
721 /* Do not turn off dependencies. */
722 if (is_isa
&& !value
)
725 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); ++i
)
726 if (strcasecmp (isa_dependencies
[i
].name
, f
) == 0)
728 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
730 char *last
= deps
+ strlen (deps
);
732 for (; next
&& next
< last
; )
734 char *str
= next_field (next
, '|', &next
, last
);
736 /* No AVX/XOP -> SSE reverse dependencies. */
737 if (is_avx
&& strncmp (str
, "SSE", 3) == 0)
738 add_isa_dependencies (flags
, str
, value
, CpuMax
);
740 add_isa_dependencies (flags
, str
, value
, reverse
);
744 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
745 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0]))
746 isa_reverse_deps
[reverse
][reverse
] = 1;
752 fail ("unknown bitfield: %s\n", f
);
756 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
757 int macro
, const char *comma
, const char *indent
)
761 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
763 fprintf (table
, "%s{ { ", indent
);
765 for (i
= 0; i
< size
- 1; i
++)
767 if (((i
+ 1) % 20) != 0)
768 fprintf (table
, "%d, ", flags
[i
].value
);
770 fprintf (table
, "%d,", flags
[i
].value
);
771 if (((i
+ 1) % 20) == 0)
773 /* We need \\ for macro. */
775 fprintf (table
, " \\\n %s", indent
);
777 fprintf (table
, "\n %s", indent
);
780 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
783 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
787 process_i386_cpu_flag (FILE *table
, char *flag
,
789 const char *comma
, const char *indent
,
790 int lineno
, unsigned int reverse
)
792 char *str
, *next
= flag
, *last
;
796 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
798 /* Copy the default cpu flags. */
799 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
803 for (i
= 0; i
< ARRAY_SIZE (isa_reverse_deps
[0]); ++i
)
804 flags
[i
].value
= isa_reverse_deps
[reverse
][i
];
810 last
= flag
+ strlen (flag
);
817 fail ("%s: %d: missing `)' in bitfield: %s\n", filename
,
824 /* First we turn on everything except for cpu64, cpuno64, and - if
825 present - the padding field. */
826 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
827 if (flags
[i
].position
< Cpu64
)
830 /* Turn off selective bits. */
834 if (name
!= NULL
&& value
!= 0)
836 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
837 if (strcasecmp (flags
[i
].name
, name
) == 0)
839 add_isa_dependencies (flags
, name
, 1, reverse
);
845 if (strcmp (flag
, "0"))
850 /* Turn on/off selective bits. */
851 last
= flag
+ strlen (flag
);
852 for (; next
&& next
< last
; )
854 str
= next_field (next
, '|', &next
, last
);
856 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
858 add_isa_dependencies (flags
, str
, value
, reverse
);
865 size_t len
= strlen (name
);
866 char *upper
= xmalloc (len
+ 1);
868 for (i
= 0; i
< len
; ++i
)
870 /* Don't emit #define-s for auxiliary entries. */
873 upper
[i
] = TOUPPER (name
[i
]);
876 fprintf (table
, "\n#define CPU_%s%s_FLAGS \\\n",
877 flag
!= NULL
? "": "ANY_", upper
);
881 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), name
!= NULL
,
886 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
890 fprintf (table
, " { ");
892 for (i
= 0; i
< size
- 1; i
++)
894 if (((i
+ 1) % 20) != 0)
895 fprintf (table
, "%d, ", modifier
[i
].value
);
897 fprintf (table
, "%d,", modifier
[i
].value
);
898 if (((i
+ 1) % 20) == 0)
899 fprintf (table
, "\n ");
902 fprintf (table
, "%d },\n", modifier
[i
].value
);
905 /* Returns LOG2 of element size. */
907 get_element_size (char **opnd
, int lineno
)
909 char *str
, *next
, *last
, *op
;
910 const char *full
= opnd
[0];
911 int elem_size
= INT_MAX
;
913 /* Find the memory operand. */
914 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
917 fail ("%s: %d: no memory operand\n", filename
, lineno
);
920 last
= op
+ strlen (op
);
921 for (next
= op
; next
&& next
< last
; )
923 str
= next_field (next
, '|', &next
, last
);
926 if (strcasecmp(str
, "Byte") == 0)
928 /* The smallest element size, no need to check
933 else if (strcasecmp(str
, "Word") == 0)
938 else if (strcasecmp(str
, "Dword") == 0)
943 else if (strcasecmp(str
, "Qword") == 0)
952 if (elem_size
== INT_MAX
)
953 fail ("%s: %d: unknown element size: %s\n", filename
, lineno
, full
);
959 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
960 unsigned int prefix
, const char *extension_opcode
,
961 char **opnd
, int lineno
)
963 char *str
, *next
, *last
;
964 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
965 static const char *const spaces
[] = {
966 #define SPACE(n) [SPACE_##n] = #n
981 /* Copy the default opcode modifier. */
982 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
984 if (strcmp (mod
, "0"))
986 unsigned int have_w
= 0, bwlq_suf
= 0xf;
988 last
= mod
+ strlen (mod
);
989 for (next
= mod
; next
&& next
< last
; )
991 str
= next_field (next
, '|', &next
, last
);
996 if (strncmp(str
, "OpcodeSpace", 11) == 0)
1001 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1004 val
= strtol (str
+ 12, &end
, 0);
1006 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1007 filename
, lineno
, end
);
1012 fail ("%s:%d: Conflicting opcode space specifications\n",
1015 "%s:%d: Warning: redundant opcode space specification\n",
1023 if (strcasecmp(str
, "Broadcast") == 0)
1024 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1025 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1026 val
= get_element_size (opnd
, lineno
);
1028 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1030 if (strcasecmp(str
, "IsString") == 0)
1031 active_isstring
= 1;
1033 if (strcasecmp(str
, "W") == 0)
1036 if (strcasecmp(str
, "No_bSuf") == 0)
1038 if (strcasecmp(str
, "No_wSuf") == 0)
1040 if (strcasecmp(str
, "No_lSuf") == 0)
1042 if (strcasecmp(str
, "No_qSuf") == 0)
1049 if (!modifiers
[OpcodePrefix
].value
)
1050 modifiers
[OpcodePrefix
].value
= prefix
;
1051 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1052 fail ("%s:%d: Conflicting prefix specifications\n",
1056 "%s:%d: Warning: redundant prefix specification\n",
1060 if (have_w
&& !bwlq_suf
)
1061 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1062 if (have_w
&& !(bwlq_suf
& 1))
1063 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1065 if (have_w
&& !(bwlq_suf
& ~1))
1067 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1071 if (space
>= ARRAY_SIZE (spaces
) || !spaces
[space
])
1072 fail ("%s:%d: Unknown opcode space %u\n", filename
, lineno
, space
);
1074 fprintf (table
, " SPACE_%s, %s,\n",
1075 spaces
[space
], extension_opcode
? extension_opcode
: "None");
1077 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1087 output_operand_type (FILE *table
, enum operand_class
class,
1088 enum operand_instance instance
,
1089 const bitfield
*types
, unsigned int size
,
1090 enum stage stage
, const char *indent
)
1094 fprintf (table
, "{ { %d, %d, ", class, instance
);
1096 for (i
= 0; i
< size
- 1; i
++)
1098 if (((i
+ 3) % 20) != 0)
1099 fprintf (table
, "%d, ", types
[i
].value
);
1101 fprintf (table
, "%d,", types
[i
].value
);
1102 if (((i
+ 3) % 20) == 0)
1104 /* We need \\ for macro. */
1105 if (stage
== stage_macros
)
1106 fprintf (table
, " \\\n%s", indent
);
1108 fprintf (table
, "\n%s", indent
);
1112 fprintf (table
, "%d } }", types
[i
].value
);
1116 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1117 const char *indent
, int lineno
)
1119 char *str
, *next
, *last
;
1120 enum operand_class
class = ClassNone
;
1121 enum operand_instance instance
= InstanceNone
;
1122 bitfield types
[ARRAY_SIZE (operand_types
)];
1124 /* Copy the default operand type. */
1125 memcpy (types
, operand_types
, sizeof (types
));
1127 if (strcmp (op
, "0"))
1131 last
= op
+ strlen (op
);
1132 for (next
= op
; next
&& next
< last
; )
1134 str
= next_field (next
, '|', &next
, last
);
1139 if (!strncmp(str
, "Class=", 6))
1141 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1142 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1144 class = operand_classes
[i
].value
;
1150 if (str
&& !strncmp(str
, "Instance=", 9))
1152 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1153 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1155 instance
= operand_instances
[i
].value
;
1163 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1164 if (strcasecmp(str
, "BaseIndex") == 0)
1169 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1171 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1172 if (!active_cpu_flags
.bitfield
.cpu64
1173 && !active_cpu_flags
.bitfield
.cpumpx
)
1174 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1175 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1178 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1182 static char *mkident (const char *mnem
)
1184 char *ident
= xstrdup (mnem
), *p
= ident
;
1197 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1198 char *last
, int lineno
)
1200 unsigned int i
, length
, prefix
= 0, space
= 0;
1201 char *base_opcode
, *extension_opcode
, *end
, *ident
;
1202 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1203 unsigned long long opcode
;
1205 /* Find base_opcode. */
1206 base_opcode
= next_field (str
, ',', &str
, last
);
1208 /* Find extension_opcode, if any. */
1209 extension_opcode
= strchr (base_opcode
, '/');
1210 if (extension_opcode
)
1211 *extension_opcode
++ = '\0';
1213 /* Find cpu_flags. */
1214 cpu_flags
= next_field (str
, ',', &str
, last
);
1216 /* Find opcode_modifier. */
1217 opcode_modifier
= next_field (str
, ',', &str
, last
);
1219 /* Remove the first {. */
1220 str
= remove_leading_whitespaces (str
);
1223 str
= remove_leading_whitespaces (str
+ 1);
1224 remove_trailing_whitespaces (str
);
1226 /* Remove } and trailing white space. */
1228 if (!i
|| str
[i
- 1] != '}')
1231 remove_trailing_whitespaces (str
);
1234 operand_types
[i
= 0] = NULL
;
1237 last
= str
+ strlen (str
);
1239 /* Find operand_types. */
1240 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1244 operand_types
[i
] = NULL
;
1248 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1252 opcode
= strtoull (base_opcode
, &end
, 0);
1254 /* Determine opcode length. */
1255 for (length
= 1; length
< 8; ++length
)
1256 if (!(opcode
>> (8 * length
)))
1259 /* Transform prefixes encoded in the opcode into opcode modifier
1263 switch (opcode
>> (8 * length
- 8))
1265 case 0x66: prefix
= PREFIX_0X66
; break;
1266 case 0xF3: prefix
= PREFIX_0XF3
; break;
1267 case 0xF2: prefix
= PREFIX_0XF2
; break;
1271 opcode
&= (1ULL << (8 * --length
)) - 1;
1274 /* Transform opcode space encoded in the opcode into opcode modifier
1276 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1278 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1280 default: space
= SPACE_0F
; break;
1281 case 0x38: space
= SPACE_0F38
; break;
1282 case 0x3A: space
= SPACE_0F3A
; break;
1285 if (space
!= SPACE_0F
&& --length
== 1)
1286 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1287 filename
, lineno
, name
);
1288 opcode
&= (1ULL << (8 * --length
)) - 1;
1292 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1293 filename
, lineno
, name
, 2 * length
, opcode
);
1295 ident
= mkident (name
);
1296 fprintf (table
, " { MN_%s, 0x%0*llx%s, %u,",
1297 ident
, 2 * (int)length
, opcode
, end
, i
);
1300 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1301 extension_opcode
, operand_types
, lineno
);
1303 process_i386_cpu_flag (table
, cpu_flags
, NULL
, ",", " ", lineno
, CpuMax
);
1305 fprintf (table
, " { ");
1307 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1309 if (!operand_types
[i
])
1312 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1318 fprintf (table
, ",\n ");
1320 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1323 fprintf (table
, " } },\n");
1326 struct opcode_hash_entry
1331 struct opcode_entry
*next
;
1337 /* Calculate the hash value of an opcode hash entry P. */
1340 opcode_hash_hash (const void *p
)
1342 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1343 return htab_hash_string (entry
->name
);
1346 /* Compare a string Q against an opcode hash entry P. */
1349 opcode_hash_eq (const void *p
, const void *q
)
1351 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1352 const char *name
= (const char *) q
;
1353 return strcmp (name
, entry
->name
) == 0;
1357 parse_template (char *buf
, int lineno
)
1359 char sep
, *end
, *name
;
1360 struct template *tmpl
;
1361 struct template_instance
*last_inst
= NULL
;
1363 buf
= remove_leading_whitespaces (buf
+ 1);
1364 end
= strchr (buf
, ':');
1367 struct template *prev
= NULL
;
1369 end
= strchr (buf
, '>');
1371 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1372 if (*remove_leading_whitespaces (end
+ 1))
1373 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1375 remove_trailing_whitespaces (buf
);
1376 /* Don't bother freeing the various structures. */
1377 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1378 if (!strcmp (buf
, tmpl
->name
))
1381 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1383 prev
->next
= tmpl
->next
;
1385 templates
= tmpl
->next
;
1389 remove_trailing_whitespaces (buf
);
1392 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1393 tmpl
= xmalloc (sizeof (*tmpl
));
1394 tmpl
->name
= xstrdup (buf
);
1396 tmpl
->params
= NULL
;
1398 struct template_param
*param
;
1400 buf
= remove_leading_whitespaces (end
);
1401 end
= strpbrk (buf
, ":,");
1403 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1407 remove_trailing_whitespaces (buf
);
1409 param
= xmalloc (sizeof (*param
));
1410 param
->name
= xstrdup (buf
);
1411 param
->next
= tmpl
->params
;
1412 tmpl
->params
= param
;
1413 } while (sep
== ':');
1415 tmpl
->instances
= NULL
;
1417 struct template_instance
*inst
;
1419 const struct template_param
*param
;
1421 buf
= remove_leading_whitespaces (end
);
1422 end
= strpbrk (buf
, ",>");
1424 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1429 inst
= xmalloc (sizeof (*inst
));
1433 cur
= next_field (buf
, ':', &next
, end
);
1434 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1436 for (param
= tmpl
->params
; param
; param
= param
->next
)
1438 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1440 cur
= next_field (next
, ':', &next
, end
);
1442 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1443 arg
->val
= xstrdup (cur
);
1444 arg
->next
= inst
->args
;
1448 if (tmpl
->instances
)
1449 last_inst
->next
= inst
;
1451 tmpl
->instances
= inst
;
1453 } while (sep
== ',');
1455 buf
= remove_leading_whitespaces (end
);
1457 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1458 filename
, lineno
, buf
);
1460 tmpl
->next
= templates
;
1465 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1466 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1468 static unsigned int idx
, opcode_array_size
;
1469 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1470 struct opcode_hash_entry
**hash_slot
;
1471 struct opcode_entry
*entry
;
1472 char *ptr1
= strchr(name
, '<'), *ptr2
;
1476 /* Get the slot in hash table. */
1477 hash_slot
= (struct opcode_hash_entry
**)
1478 htab_find_slot_with_hash (opcode_hash_table
, name
,
1479 htab_hash_string (name
),
1482 if (*hash_slot
== NULL
)
1484 /* It is the new one. Put it on opcode array. */
1485 if (idx
>= opcode_array_size
)
1487 /* Grow the opcode array when needed. */
1488 opcode_array_size
+= 1024;
1489 opcode_array
= (struct opcode_hash_entry
**)
1490 xrealloc (opcode_array
,
1491 sizeof (*opcode_array
) * opcode_array_size
);
1492 *opcode_array_p
= opcode_array
;
1495 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1496 xmalloc (sizeof (struct opcode_hash_entry
));
1497 opcode_array
[idx
]->name
= xstrdup (name
);
1498 *hash_slot
= opcode_array
[idx
];
1499 entry
= &opcode_array
[idx
]->entry
;
1504 /* Append it to the existing one. */
1505 struct opcode_entry
**entryp
= &(*hash_slot
)->entry
.next
;
1507 while (*entryp
!= NULL
)
1508 entryp
= &(*entryp
)->next
;
1509 entry
= (struct opcode_entry
*)xmalloc (sizeof (struct opcode_entry
));
1514 entry
->opcode
= xstrdup (str
);
1515 entry
->lineno
= lineno
;
1517 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1518 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1521 const struct template *tmpl
;
1522 const struct template_instance
*inst
;
1525 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1526 remove_trailing_whitespaces (ptr1
);
1530 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1531 if (!strcmp(ptr1
, tmpl
->name
))
1534 fail ("reference to unknown template '%s'\n", ptr1
);
1536 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1538 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1539 char *str2
= xmalloc(2 * strlen(str
));
1542 strcpy (name2
, name
);
1543 strcat (name2
, inst
->name
);
1544 strcat (name2
, ptr2
);
1546 for (ptr1
= str2
, src
= str
; *src
; )
1548 const char *ident
= tmpl
->name
, *end
;
1549 const struct template_param
*param
;
1550 const struct template_arg
*arg
;
1552 if ((*ptr1
= *src
++) != '<')
1557 while (ISSPACE(*src
))
1559 while (*ident
&& *src
== *ident
)
1561 while (ISSPACE(*src
))
1563 if (*src
!= ':' || *ident
!= '\0')
1565 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1566 ptr1
+= ident
- tmpl
->name
;
1569 while (ISSPACE(*++src
))
1573 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1576 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1577 param
= param
->next
, arg
= arg
->next
)
1579 if (end
- src
== strlen (param
->name
)
1580 && !memcmp (src
, param
->name
, end
- src
))
1588 fail ("template '%s' has no parameter '%.*s'\n",
1589 tmpl
->name
, (int)(end
- src
), src
);
1591 while (ISSPACE(*src
))
1594 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1596 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1597 ptr1
+= strlen(arg
->val
);
1603 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1614 static int mnemonic_cmp(const void *p1
, const void *p2
)
1616 const struct opcode_hash_entry
*const *e1
= p1
, *const *e2
= p2
;
1617 const char *s1
= (*e1
)->name
, *s2
= (*e2
)->name
;
1619 size_t l1
= strlen (s1
), l2
= strlen (s2
);
1621 for (i
= 1; i
<= l1
&& i
<= l2
; ++i
)
1623 if (s1
[l1
- i
] != s2
[l2
- i
])
1624 return (unsigned char)s1
[l1
- i
] - (unsigned char)s2
[l2
- i
];
1627 return (int)(l1
- l2
);
1631 process_i386_opcodes (FILE *table
)
1635 unsigned int i
, j
, nr
, offs
;
1637 char *str
, *p
, *last
;
1638 htab_t opcode_hash_table
;
1639 struct opcode_hash_entry
**opcode_array
= NULL
;
1640 int lineno
= 0, marker
= 0;
1642 filename
= "i386-opc.tbl";
1646 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1647 opcode_hash_eq
, NULL
,
1650 fprintf (table
, "\n#include \"i386-mnem.h\"\n");
1651 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1652 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1654 /* Put everything on opcode array. */
1659 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1662 p
= remove_leading_whitespaces (buf
);
1668 /* Skip comments. */
1669 str
= strstr (p
, "//");
1673 remove_trailing_whitespaces (p
);
1677 /* Look for line continuation character. */
1678 remove_trailing_whitespaces (p
);
1680 if (!j
|| buf
[j
- 1] != '+')
1682 if (j
>= sizeof (buf
) - 1)
1683 fail ("%s: %d: (continued) line too long\n", filename
, lineno
);
1685 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1687 fprintf (stderr
, "%s: Line continuation on last line?\n",
1696 if (!strcmp("### MARKER ###", buf
))
1700 /* Since we ignore all included files (we only care about their
1701 #define-s here), we don't need to monitor filenames. The final
1702 line number directive is going to refer to the main source file
1707 p
= remove_leading_whitespaces (p
+ 1);
1708 if (!strncmp(p
, "line", 4))
1710 ln
= strtoul (p
, &end
, 10);
1711 if (ln
> 1 && ln
< INT_MAX
1712 && *remove_leading_whitespaces (end
) == '"')
1715 /* Ignore comments. */
1720 parse_template (p
, lineno
);
1728 last
= p
+ strlen (p
);
1731 name
= next_field (p
, ',', &str
, last
);
1733 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1737 /* Process opcode array. */
1738 for (j
= 0; j
< i
; j
++)
1740 const char *name
= opcode_array
[j
]->name
;
1741 struct opcode_entry
*next
;
1743 for (next
= &opcode_array
[j
]->entry
; next
; next
= next
->next
)
1746 lineno
= next
->lineno
;
1747 last
= str
+ strlen (str
);
1748 output_i386_opcode (table
, name
, str
, last
, lineno
);
1754 fprintf (table
, "};\n");
1756 /* Generate opcode sets array. */
1757 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1758 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1759 fprintf (table
, " i386_optab,\n");
1761 for (nr
= j
= 0; j
< i
; j
++)
1763 struct opcode_entry
*next
= &opcode_array
[j
]->entry
;
1771 fprintf (table
, " i386_optab + %u,\n", nr
);
1774 fprintf (table
, "};\n");
1776 /* Emit mnemonics and associated #define-s. */
1777 qsort (opcode_array
, i
, sizeof (*opcode_array
), mnemonic_cmp
);
1779 fp
= fopen ("i386-mnem.h", "w");
1781 fail ("can't create i386-mnem.h, errno = %s\n",
1784 process_copyright (fp
);
1786 fprintf (table
, "\n/* i386 mnemonics table. */\n\n");
1787 fprintf (table
, "const char i386_mnemonics[] =\n");
1788 fprintf (fp
, "\nextern const char i386_mnemonics[];\n\n");
1791 for (l
= strlen (opcode_array
[offs
= j
= 0]->name
); j
< i
; j
++)
1793 const char *name
= opcode_array
[j
]->name
;
1794 const char *next
= NULL
;
1795 size_t l1
= j
+ 1 < i
? strlen(next
= opcode_array
[j
+ 1]->name
) : 0;
1798 str
= mkident (name
);
1799 if (l
< l1
&& !strcmp(name
, next
+ l1
- l
))
1801 fprintf (fp
, "#define MN_%s ", str
);
1803 str
= mkident (next
);
1804 fprintf (fp
, "(MN_%s + %u)\n", str
, l1
- l
);
1808 fprintf (table
, " \"\\0\"\"%s\"\n", name
);
1809 fprintf (fp
, "#define MN_%s %#x\n", str
, offs
+ 1);
1810 offs
+= strlen (name
) + 1;
1817 fprintf (table
, ";\n");
1823 process_i386_registers (FILE *table
)
1827 char *str
, *p
, *last
;
1828 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1829 char *dw2_32_num
, *dw2_64_num
;
1832 filename
= "i386-reg.tbl";
1833 fp
= fopen (filename
, "r");
1835 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1838 fprintf (table
, "\n/* i386 register table. */\n\n");
1839 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1843 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1848 p
= remove_leading_whitespaces (buf
);
1850 /* Skip comments. */
1851 str
= strstr (p
, "//");
1855 /* Remove trailing white spaces. */
1856 remove_trailing_whitespaces (p
);
1861 fprintf (table
, "%s\n", p
);
1869 last
= p
+ strlen (p
);
1871 /* Find reg_name. */
1872 reg_name
= next_field (p
, ',', &str
, last
);
1874 /* Find reg_type. */
1875 reg_type
= next_field (str
, ',', &str
, last
);
1877 /* Find reg_flags. */
1878 reg_flags
= next_field (str
, ',', &str
, last
);
1881 reg_num
= next_field (str
, ',', &str
, last
);
1883 fprintf (table
, " { \"%s\",\n ", reg_name
);
1885 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1888 /* Find 32-bit Dwarf2 register number. */
1889 dw2_32_num
= next_field (str
, ',', &str
, last
);
1891 /* Find 64-bit Dwarf2 register number. */
1892 dw2_64_num
= next_field (str
, ',', &str
, last
);
1894 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1895 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1900 fprintf (table
, "};\n");
1902 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1906 process_i386_initializers (void)
1909 FILE *fp
= fopen ("i386-init.h", "w");
1912 fail ("can't create i386-init.h, errno = %s\n",
1915 process_copyright (fp
);
1917 for (i
= 0; i
< Cpu64
; i
++)
1918 process_i386_cpu_flag (fp
, "0", cpu_flags
[i
].name
, "", " ", -1, i
);
1920 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); i
++)
1922 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
1924 process_i386_cpu_flag (fp
, deps
, isa_dependencies
[i
].name
,
1925 "", " ", -1, CpuMax
);
1929 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1930 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1931 one to 387. We want the reverse to be true though: Disabling 8087 also
1932 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1933 memcpy (isa_reverse_deps
[Cpu287
], isa_reverse_deps
[Cpu387
],
1934 sizeof (isa_reverse_deps
[0]));
1935 isa_reverse_deps
[Cpu287
][Cpu387
] = 1;
1936 memcpy (isa_reverse_deps
[Cpu8087
], isa_reverse_deps
[Cpu287
],
1937 sizeof (isa_reverse_deps
[0]));
1938 isa_reverse_deps
[Cpu8087
][Cpu287
] = 1;
1940 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1941 lead to disabling of anything else. */
1942 memset (isa_reverse_deps
[CpuPOPCNT
], 0, sizeof (isa_reverse_deps
[0]));
1944 for (i
= Cpu686
+ 1; i
< ARRAY_SIZE (isa_reverse_deps
); i
++)
1949 if (memchr(isa_reverse_deps
[i
], 1,
1950 ARRAY_SIZE (isa_reverse_deps
[0])) == NULL
)
1953 isa_reverse_deps
[i
][i
] = 1;
1954 process_i386_cpu_flag (fp
, NULL
, cpu_flags
[i
].name
, "", " ", -1, i
);
1962 /* Program options. */
1963 #define OPTION_SRCDIR 200
1965 struct option long_options
[] =
1967 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1968 {"debug", no_argument
, NULL
, 'd'},
1969 {"version", no_argument
, NULL
, 'V'},
1970 {"help", no_argument
, NULL
, 'h'},
1971 {0, no_argument
, NULL
, 0}
1975 print_version (void)
1977 printf ("%s: version 1.0\n", program_name
);
1982 usage (FILE * stream
, int status
)
1984 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1990 main (int argc
, char **argv
)
1992 extern int chdir (char *);
1993 char *srcdir
= NULL
;
1995 unsigned int i
, cpumax
;
1998 program_name
= *argv
;
1999 xmalloc_set_program_name (program_name
);
2001 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2026 if (chdir (srcdir
) != 0)
2027 fail ("unable to change directory to \"%s\", errno = %s\n",
2028 srcdir
, xstrerror (errno
));
2030 /* cpu_flags isn't sorted by position. */
2032 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2033 if (cpu_flags
[i
].position
> cpumax
)
2034 cpumax
= cpu_flags
[i
].position
;
2036 /* Check the unused bitfield in i386_cpu_flags. */
2038 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2040 if ((cpumax
- 1) != CpuMax
)
2041 fail ("CpuMax != %d!\n", cpumax
);
2043 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2045 if (cpumax
!= CpuMax
)
2046 fail ("CpuMax != %d!\n", cpumax
);
2048 c
= CpuNumOfBits
- CpuMax
- 1;
2050 fail ("%d unused bits in i386_cpu_flags.\n", c
);
2053 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2055 /* Check the unused bitfield in i386_operand_type. */
2057 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2060 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2063 c
= OTNumOfBits
- OTNum
;
2065 fail ("%d unused bits in i386_operand_type.\n", c
);
2068 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2071 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2072 sizeof (opcode_modifiers
[0]), compare
);
2074 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2075 sizeof (operand_types
[0]), compare
);
2077 table
= fopen ("i386-tbl.h", "w");
2079 fail ("can't create i386-tbl.h, errno = %s\n",
2082 process_copyright (table
);
2084 process_i386_opcodes (table
);
2085 process_i386_registers (table
);
2086 process_i386_initializers ();