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" },
191 { "AVX512_VPOPCNTDQ",
199 { "AVX512_VP2INTERSECT",
253 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
254 static unsigned char isa_reverse_deps
[Cpu64
][Cpu64
];
256 typedef struct bitfield
263 #define BITFIELD(n) { Cpu##n, 0, #n }
265 static bitfield cpu_flags
[] =
320 BITFIELD (LAHF_SAHF
),
339 BITFIELD (ClflushOpt
),
342 BITFIELD (PREFETCHWT1
),
346 BITFIELD (AVX512IFMA
),
347 BITFIELD (AVX512VBMI
),
348 BITFIELD (AVX512_4FMAPS
),
349 BITFIELD (AVX512_4VNNIW
),
350 BITFIELD (AVX512_VPOPCNTDQ
),
351 BITFIELD (AVX512_VBMI2
),
352 BITFIELD (AVX512_VNNI
),
353 BITFIELD (AVX512_BITALG
),
354 BITFIELD (AVX512_BF16
),
355 BITFIELD (AVX512_VP2INTERSECT
),
358 BITFIELD (AVX512_FP16
),
359 BITFIELD (PREFETCHI
),
361 BITFIELD (AVX_VNNI_INT8
),
362 BITFIELD (CMPCCXADD
),
365 BITFIELD (AVX_NE_CONVERT
),
378 BITFIELD (VPCLMULQDQ
),
387 BITFIELD (AMX_COMPLEX
),
390 BITFIELD (MOVDIR64B
),
392 BITFIELD (SERIALIZE
),
412 #define BITFIELD(n) { n, 0, #n }
414 static bitfield opcode_modifiers
[] =
423 BITFIELD (CheckOperandSize
),
424 BITFIELD (OperandConstraint
),
425 BITFIELD (MnemonicSize
),
434 BITFIELD (BNDPrefixOk
),
442 BITFIELD (OpcodePrefix
),
447 BITFIELD (Broadcast
),
448 BITFIELD (StaticRounding
),
450 BITFIELD (Disp8MemShift
),
452 BITFIELD (ATTMnemonic
),
453 BITFIELD (ATTSyntax
),
454 BITFIELD (IntelSyntax
),
458 #define CLASS(n) #n, n
460 static const struct {
462 enum operand_class value
;
463 } operand_classes
[] = {
477 #define INSTANCE(n) #n, n
479 static const struct {
481 enum operand_instance value
;
482 } operand_instances
[] = {
491 static bitfield operand_types
[] =
500 BITFIELD (BaseIndex
),
515 BITFIELD (Unspecified
),
521 static const char *filename
;
522 static i386_cpu_flags active_cpu_flags
;
523 static int active_isstring
;
525 struct template_arg
{
526 const struct template_arg
*next
;
530 struct template_instance
{
531 const struct template_instance
*next
;
533 const struct template_arg
*args
;
536 struct template_param
{
537 const struct template_param
*next
;
542 struct template *next
;
544 const struct template_instance
*instances
;
545 const struct template_param
*params
;
548 static struct template *templates
;
551 compare (const void *x
, const void *y
)
553 const bitfield
*xp
= (const bitfield
*) x
;
554 const bitfield
*yp
= (const bitfield
*) y
;
555 return xp
->position
- yp
->position
;
559 fail (const char *message
, ...)
563 va_start (args
, message
);
564 fprintf (stderr
, "%s: error: ", program_name
);
565 vfprintf (stderr
, message
, args
);
571 process_copyright (FILE *fp
)
573 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
574 /* Copyright (C) 2007-2023 Free Software Foundation, Inc.\n\
576 This file is part of the GNU opcodes library.\n\
578 This library is free software; you can redistribute it and/or modify\n\
579 it under the terms of the GNU General Public License as published by\n\
580 the Free Software Foundation; either version 3, or (at your option)\n\
581 any later version.\n\
583 It is distributed in the hope that it will be useful, but WITHOUT\n\
584 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
585 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
586 License for more details.\n\
588 You should have received a copy of the GNU General Public License\n\
589 along with this program; if not, write to the Free Software\n\
590 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
591 MA 02110-1301, USA. */\n");
594 /* Remove leading white spaces. */
597 remove_leading_whitespaces (char *str
)
599 while (ISSPACE (*str
))
604 /* Remove trailing white spaces. */
607 remove_trailing_whitespaces (char *str
)
609 size_t last
= strlen (str
);
617 if (ISSPACE (str
[last
]))
625 /* Find next field separated by SEP and terminate it. Return a
626 pointer to the one after it. */
629 next_field (char *str
, char sep
, char **next
, char *last
)
633 p
= remove_leading_whitespaces (str
);
634 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
637 remove_trailing_whitespaces (p
);
647 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
650 set_bitfield (char *f
, bitfield
*array
, int value
,
651 unsigned int size
, int lineno
)
655 /* Ignore empty fields; they may result from template expansions. */
659 for (i
= 0; i
< size
; i
++)
660 if (strcasecmp (array
[i
].name
, f
) == 0)
662 array
[i
].value
= value
;
668 const char *v
= strchr (f
, '=');
675 for (i
= 0; i
< size
; i
++)
676 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
678 value
= strtol (v
+ 1, &end
, 0);
681 array
[i
].value
= value
;
690 fail ("%s: %d: unknown bitfield: %s\n", filename
, lineno
, f
);
692 fail ("unknown bitfield: %s\n", f
);
696 add_isa_dependencies (bitfield
*flags
, const char *f
, int value
,
697 unsigned int reverse
)
702 bool is_isa
= false, is_avx
= false;
704 /* Need to find base entry for references to auxiliary ones. */
708 *strchr (str
, ':') = '\0';
711 for (i
= 0; i
< Cpu64
; ++i
)
712 if (strcasecmp (flags
[i
].name
, isa
) == 0)
714 flags
[i
].value
= value
;
715 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0])
716 /* Don't record the feature itself here. */
718 /* Don't record base architectures. */
720 isa_reverse_deps
[i
][reverse
] = 1;
722 if (i
== CpuAVX
|| i
== CpuXOP
)
728 /* Do not turn off dependencies. */
729 if (is_isa
&& !value
)
732 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); ++i
)
733 if (strcasecmp (isa_dependencies
[i
].name
, f
) == 0)
735 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
737 char *last
= deps
+ strlen (deps
);
739 for (; next
&& next
< last
; )
741 char *str
= next_field (next
, '|', &next
, last
);
743 /* No AVX/XOP -> SSE reverse dependencies. */
744 if (is_avx
&& strncmp (str
, "SSE", 3) == 0)
745 add_isa_dependencies (flags
, str
, value
, CpuMax
);
747 add_isa_dependencies (flags
, str
, value
, reverse
);
751 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
752 if (reverse
< ARRAY_SIZE (isa_reverse_deps
[0]))
753 isa_reverse_deps
[reverse
][reverse
] = 1;
759 fail ("unknown bitfield: %s\n", f
);
763 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
764 int macro
, const char *comma
, const char *indent
)
768 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
770 fprintf (table
, "%s{ { ", indent
);
772 for (i
= 0; i
< size
- 1; i
++)
774 if (((i
+ 1) % 20) != 0)
775 fprintf (table
, "%d, ", flags
[i
].value
);
777 fprintf (table
, "%d,", flags
[i
].value
);
778 if (((i
+ 1) % 20) == 0)
780 /* We need \\ for macro. */
782 fprintf (table
, " \\\n %s", indent
);
784 fprintf (table
, "\n %s", indent
);
787 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
790 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
794 process_i386_cpu_flag (FILE *table
, char *flag
,
796 const char *comma
, const char *indent
,
797 int lineno
, unsigned int reverse
)
799 char *str
, *next
= flag
, *last
;
803 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
805 /* Copy the default cpu flags. */
806 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
810 for (i
= 0; i
< ARRAY_SIZE (isa_reverse_deps
[0]); ++i
)
811 flags
[i
].value
= isa_reverse_deps
[reverse
][i
];
817 last
= flag
+ strlen (flag
);
824 fail ("%s: %d: missing `)' in bitfield: %s\n", filename
,
831 /* First we turn on everything except for cpu64, cpuno64, and - if
832 present - the padding field. */
833 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
834 if (flags
[i
].position
< Cpu64
)
837 /* Turn off selective bits. */
841 if (name
!= NULL
&& value
!= 0)
843 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
844 if (strcasecmp (flags
[i
].name
, name
) == 0)
846 add_isa_dependencies (flags
, name
, 1, reverse
);
852 if (strcmp (flag
, "0"))
857 /* Turn on/off selective bits. */
858 last
= flag
+ strlen (flag
);
859 for (; next
&& next
< last
; )
861 str
= next_field (next
, '|', &next
, last
);
863 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
865 add_isa_dependencies (flags
, str
, value
, reverse
);
872 size_t len
= strlen (name
);
873 char *upper
= xmalloc (len
+ 1);
875 for (i
= 0; i
< len
; ++i
)
877 /* Don't emit #define-s for auxiliary entries. */
880 upper
[i
] = TOUPPER (name
[i
]);
883 fprintf (table
, "\n#define CPU_%s%s_FLAGS \\\n",
884 flag
!= NULL
? "": "ANY_", upper
);
888 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), name
!= NULL
,
893 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
897 fprintf (table
, " { ");
899 for (i
= 0; i
< size
- 1; i
++)
901 if (((i
+ 1) % 20) != 0)
902 fprintf (table
, "%d, ", modifier
[i
].value
);
904 fprintf (table
, "%d,", modifier
[i
].value
);
905 if (((i
+ 1) % 20) == 0)
906 fprintf (table
, "\n ");
909 fprintf (table
, "%d },\n", modifier
[i
].value
);
912 /* Returns LOG2 of element size. */
914 get_element_size (char **opnd
, int lineno
)
916 char *str
, *next
, *last
, *op
;
917 const char *full
= opnd
[0];
918 int elem_size
= INT_MAX
;
920 /* Find the memory operand. */
921 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
924 fail ("%s: %d: no memory operand\n", filename
, lineno
);
927 last
= op
+ strlen (op
);
928 for (next
= op
; next
&& next
< last
; )
930 str
= next_field (next
, '|', &next
, last
);
933 if (strcasecmp(str
, "Byte") == 0)
935 /* The smallest element size, no need to check
940 else if (strcasecmp(str
, "Word") == 0)
945 else if (strcasecmp(str
, "Dword") == 0)
950 else if (strcasecmp(str
, "Qword") == 0)
959 if (elem_size
== INT_MAX
)
960 fail ("%s: %d: unknown element size: %s\n", filename
, lineno
, full
);
966 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
967 unsigned int prefix
, const char *extension_opcode
,
968 char **opnd
, int lineno
)
970 char *str
, *next
, *last
;
971 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
972 static const char *const spaces
[] = {
973 #define SPACE(n) [SPACE_##n] = #n
988 /* Copy the default opcode modifier. */
989 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
991 if (strcmp (mod
, "0"))
993 unsigned int have_w
= 0, bwlq_suf
= 0xf;
995 last
= mod
+ strlen (mod
);
996 for (next
= mod
; next
&& next
< last
; )
998 str
= next_field (next
, '|', &next
, last
);
1003 if (strncmp(str
, "OpcodeSpace", 11) == 0)
1008 fail ("%s:%d: Missing value for `OpcodeSpace'\n",
1011 val
= strtol (str
+ 12, &end
, 0);
1013 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
1014 filename
, lineno
, end
);
1019 fail ("%s:%d: Conflicting opcode space specifications\n",
1022 "%s:%d: Warning: redundant opcode space specification\n",
1030 if (strcasecmp(str
, "Broadcast") == 0)
1031 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1032 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1033 val
= get_element_size (opnd
, lineno
);
1035 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1037 if (strcasecmp(str
, "IsString") == 0)
1038 active_isstring
= 1;
1040 if (strcasecmp(str
, "W") == 0)
1043 if (strcasecmp(str
, "No_bSuf") == 0)
1045 if (strcasecmp(str
, "No_wSuf") == 0)
1047 if (strcasecmp(str
, "No_lSuf") == 0)
1049 if (strcasecmp(str
, "No_qSuf") == 0)
1056 if (!modifiers
[OpcodePrefix
].value
)
1057 modifiers
[OpcodePrefix
].value
= prefix
;
1058 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1059 fail ("%s:%d: Conflicting prefix specifications\n",
1063 "%s:%d: Warning: redundant prefix specification\n",
1067 if (have_w
&& !bwlq_suf
)
1068 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1069 if (have_w
&& !(bwlq_suf
& 1))
1070 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1072 if (have_w
&& !(bwlq_suf
& ~1))
1074 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1078 if (space
>= ARRAY_SIZE (spaces
) || !spaces
[space
])
1079 fail ("%s:%d: Unknown opcode space %u\n", filename
, lineno
, space
);
1081 fprintf (table
, " SPACE_%s, %s,\n",
1082 spaces
[space
], extension_opcode
? extension_opcode
: "None");
1084 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1094 output_operand_type (FILE *table
, enum operand_class
class,
1095 enum operand_instance instance
,
1096 const bitfield
*types
, unsigned int size
,
1097 enum stage stage
, const char *indent
)
1101 fprintf (table
, "{ { %d, %d, ", class, instance
);
1103 for (i
= 0; i
< size
- 1; i
++)
1105 if (((i
+ 3) % 20) != 0)
1106 fprintf (table
, "%d, ", types
[i
].value
);
1108 fprintf (table
, "%d,", types
[i
].value
);
1109 if (((i
+ 3) % 20) == 0)
1111 /* We need \\ for macro. */
1112 if (stage
== stage_macros
)
1113 fprintf (table
, " \\\n%s", indent
);
1115 fprintf (table
, "\n%s", indent
);
1119 fprintf (table
, "%d } }", types
[i
].value
);
1123 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1124 const char *indent
, int lineno
)
1126 char *str
, *next
, *last
;
1127 enum operand_class
class = ClassNone
;
1128 enum operand_instance instance
= InstanceNone
;
1129 bitfield types
[ARRAY_SIZE (operand_types
)];
1131 /* Copy the default operand type. */
1132 memcpy (types
, operand_types
, sizeof (types
));
1134 if (strcmp (op
, "0"))
1138 last
= op
+ strlen (op
);
1139 for (next
= op
; next
&& next
< last
; )
1141 str
= next_field (next
, '|', &next
, last
);
1146 if (!strncmp(str
, "Class=", 6))
1148 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1149 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1151 class = operand_classes
[i
].value
;
1157 if (str
&& !strncmp(str
, "Instance=", 9))
1159 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1160 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1162 instance
= operand_instances
[i
].value
;
1170 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1171 if (strcasecmp(str
, "BaseIndex") == 0)
1176 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1178 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1179 if (!active_cpu_flags
.bitfield
.cpu64
1180 && !active_cpu_flags
.bitfield
.cpumpx
)
1181 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1182 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1185 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1189 static char *mkident (const char *mnem
)
1191 char *ident
= xstrdup (mnem
), *p
= ident
;
1204 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1205 char *last
, int lineno
)
1207 unsigned int i
, length
, prefix
= 0, space
= 0;
1208 char *base_opcode
, *extension_opcode
, *end
, *ident
;
1209 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1210 unsigned long long opcode
;
1212 /* Find base_opcode. */
1213 base_opcode
= next_field (str
, ',', &str
, last
);
1215 /* Find extension_opcode, if any. */
1216 extension_opcode
= strchr (base_opcode
, '/');
1217 if (extension_opcode
)
1218 *extension_opcode
++ = '\0';
1220 /* Find cpu_flags. */
1221 cpu_flags
= next_field (str
, ',', &str
, last
);
1223 /* Find opcode_modifier. */
1224 opcode_modifier
= next_field (str
, ',', &str
, last
);
1226 /* Remove the first {. */
1227 str
= remove_leading_whitespaces (str
);
1230 str
= remove_leading_whitespaces (str
+ 1);
1231 remove_trailing_whitespaces (str
);
1233 /* Remove } and trailing white space. */
1235 if (!i
|| str
[i
- 1] != '}')
1238 remove_trailing_whitespaces (str
);
1241 operand_types
[i
= 0] = NULL
;
1244 last
= str
+ strlen (str
);
1246 /* Find operand_types. */
1247 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1251 operand_types
[i
] = NULL
;
1255 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1259 opcode
= strtoull (base_opcode
, &end
, 0);
1261 /* Determine opcode length. */
1262 for (length
= 1; length
< 8; ++length
)
1263 if (!(opcode
>> (8 * length
)))
1266 /* Transform prefixes encoded in the opcode into opcode modifier
1270 switch (opcode
>> (8 * length
- 8))
1272 case 0x66: prefix
= PREFIX_0X66
; break;
1273 case 0xF3: prefix
= PREFIX_0XF3
; break;
1274 case 0xF2: prefix
= PREFIX_0XF2
; break;
1278 opcode
&= (1ULL << (8 * --length
)) - 1;
1281 /* Transform opcode space encoded in the opcode into opcode modifier
1283 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1285 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1287 default: space
= SPACE_0F
; break;
1288 case 0x38: space
= SPACE_0F38
; break;
1289 case 0x3A: space
= SPACE_0F3A
; break;
1292 if (space
!= SPACE_0F
&& --length
== 1)
1293 fail ("%s:%d: %s: unrecognized opcode encoding space\n",
1294 filename
, lineno
, name
);
1295 opcode
&= (1ULL << (8 * --length
)) - 1;
1299 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n",
1300 filename
, lineno
, name
, 2 * length
, opcode
);
1302 ident
= mkident (name
);
1303 fprintf (table
, " { MN_%s, 0x%0*llx%s, %u,",
1304 ident
, 2 * (int)length
, opcode
, end
, i
);
1307 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1308 extension_opcode
, operand_types
, lineno
);
1310 process_i386_cpu_flag (table
, cpu_flags
, NULL
, ",", " ", lineno
, CpuMax
);
1312 fprintf (table
, " { ");
1314 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1316 if (!operand_types
[i
])
1319 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1325 fprintf (table
, ",\n ");
1327 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1330 fprintf (table
, " } },\n");
1333 struct opcode_hash_entry
1338 struct opcode_entry
*next
;
1344 /* Calculate the hash value of an opcode hash entry P. */
1347 opcode_hash_hash (const void *p
)
1349 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1350 return htab_hash_string (entry
->name
);
1353 /* Compare a string Q against an opcode hash entry P. */
1356 opcode_hash_eq (const void *p
, const void *q
)
1358 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1359 const char *name
= (const char *) q
;
1360 return strcmp (name
, entry
->name
) == 0;
1364 parse_template (char *buf
, int lineno
)
1366 char sep
, *end
, *name
;
1367 struct template *tmpl
;
1368 struct template_instance
*last_inst
= NULL
;
1370 buf
= remove_leading_whitespaces (buf
+ 1);
1371 end
= strchr (buf
, ':');
1374 struct template *prev
= NULL
;
1376 end
= strchr (buf
, '>');
1378 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1379 if (*remove_leading_whitespaces (end
+ 1))
1380 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1382 remove_trailing_whitespaces (buf
);
1383 /* Don't bother freeing the various structures. */
1384 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1385 if (!strcmp (buf
, tmpl
->name
))
1388 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1390 prev
->next
= tmpl
->next
;
1392 templates
= tmpl
->next
;
1396 remove_trailing_whitespaces (buf
);
1399 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1400 tmpl
= xmalloc (sizeof (*tmpl
));
1401 tmpl
->name
= xstrdup (buf
);
1403 tmpl
->params
= NULL
;
1405 struct template_param
*param
;
1407 buf
= remove_leading_whitespaces (end
);
1408 end
= strpbrk (buf
, ":,");
1410 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1414 remove_trailing_whitespaces (buf
);
1416 param
= xmalloc (sizeof (*param
));
1417 param
->name
= xstrdup (buf
);
1418 param
->next
= tmpl
->params
;
1419 tmpl
->params
= param
;
1420 } while (sep
== ':');
1422 tmpl
->instances
= NULL
;
1424 struct template_instance
*inst
;
1426 const struct template_param
*param
;
1428 buf
= remove_leading_whitespaces (end
);
1429 end
= strpbrk (buf
, ",>");
1431 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1436 inst
= xmalloc (sizeof (*inst
));
1440 cur
= next_field (buf
, ':', &next
, end
);
1441 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1443 for (param
= tmpl
->params
; param
; param
= param
->next
)
1445 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1447 cur
= next_field (next
, ':', &next
, end
);
1449 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1450 arg
->val
= xstrdup (cur
);
1451 arg
->next
= inst
->args
;
1455 if (tmpl
->instances
)
1456 last_inst
->next
= inst
;
1458 tmpl
->instances
= inst
;
1460 } while (sep
== ',');
1462 buf
= remove_leading_whitespaces (end
);
1464 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1465 filename
, lineno
, buf
);
1467 tmpl
->next
= templates
;
1472 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1473 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1475 static unsigned int idx
, opcode_array_size
;
1476 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1477 struct opcode_hash_entry
**hash_slot
;
1478 struct opcode_entry
*entry
;
1479 char *ptr1
= strchr(name
, '<'), *ptr2
;
1483 /* Get the slot in hash table. */
1484 hash_slot
= (struct opcode_hash_entry
**)
1485 htab_find_slot_with_hash (opcode_hash_table
, name
,
1486 htab_hash_string (name
),
1489 if (*hash_slot
== NULL
)
1491 /* It is the new one. Put it on opcode array. */
1492 if (idx
>= opcode_array_size
)
1494 /* Grow the opcode array when needed. */
1495 opcode_array_size
+= 1024;
1496 opcode_array
= (struct opcode_hash_entry
**)
1497 xrealloc (opcode_array
,
1498 sizeof (*opcode_array
) * opcode_array_size
);
1499 *opcode_array_p
= opcode_array
;
1502 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1503 xmalloc (sizeof (struct opcode_hash_entry
));
1504 opcode_array
[idx
]->name
= xstrdup (name
);
1505 *hash_slot
= opcode_array
[idx
];
1506 entry
= &opcode_array
[idx
]->entry
;
1511 /* Append it to the existing one. */
1512 struct opcode_entry
**entryp
= &(*hash_slot
)->entry
.next
;
1514 while (*entryp
!= NULL
)
1515 entryp
= &(*entryp
)->next
;
1516 entry
= (struct opcode_entry
*)xmalloc (sizeof (struct opcode_entry
));
1521 entry
->opcode
= xstrdup (str
);
1522 entry
->lineno
= lineno
;
1524 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1525 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1528 const struct template *tmpl
;
1529 const struct template_instance
*inst
;
1532 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1533 remove_trailing_whitespaces (ptr1
);
1537 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1538 if (!strcmp(ptr1
, tmpl
->name
))
1541 fail ("reference to unknown template '%s'\n", ptr1
);
1543 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1545 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1546 char *str2
= xmalloc(2 * strlen(str
));
1549 strcpy (name2
, name
);
1550 strcat (name2
, inst
->name
);
1551 strcat (name2
, ptr2
);
1553 for (ptr1
= str2
, src
= str
; *src
; )
1555 const char *ident
= tmpl
->name
, *end
;
1556 const struct template_param
*param
;
1557 const struct template_arg
*arg
;
1559 if ((*ptr1
= *src
++) != '<')
1564 while (ISSPACE(*src
))
1566 while (*ident
&& *src
== *ident
)
1568 while (ISSPACE(*src
))
1570 if (*src
!= ':' || *ident
!= '\0')
1572 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1573 ptr1
+= ident
- tmpl
->name
;
1576 while (ISSPACE(*++src
))
1580 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1583 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1584 param
= param
->next
, arg
= arg
->next
)
1586 if (end
- src
== strlen (param
->name
)
1587 && !memcmp (src
, param
->name
, end
- src
))
1595 fail ("template '%s' has no parameter '%.*s'\n",
1596 tmpl
->name
, (int)(end
- src
), src
);
1598 while (ISSPACE(*src
))
1601 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1603 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1604 ptr1
+= strlen(arg
->val
);
1610 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1621 static int mnemonic_cmp(const void *p1
, const void *p2
)
1623 const struct opcode_hash_entry
*const *e1
= p1
, *const *e2
= p2
;
1624 const char *s1
= (*e1
)->name
, *s2
= (*e2
)->name
;
1626 size_t l1
= strlen (s1
), l2
= strlen (s2
);
1628 for (i
= 1; i
<= l1
&& i
<= l2
; ++i
)
1630 if (s1
[l1
- i
] != s2
[l2
- i
])
1631 return (unsigned char)s1
[l1
- i
] - (unsigned char)s2
[l2
- i
];
1634 return (int)(l1
- l2
);
1638 process_i386_opcodes (FILE *table
)
1642 unsigned int i
, j
, nr
, offs
;
1644 char *str
, *p
, *last
;
1645 htab_t opcode_hash_table
;
1646 struct opcode_hash_entry
**opcode_array
= NULL
;
1647 int lineno
= 0, marker
= 0;
1649 filename
= "i386-opc.tbl";
1653 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1654 opcode_hash_eq
, NULL
,
1657 fprintf (table
, "\n#include \"i386-mnem.h\"\n");
1658 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1659 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1661 /* Put everything on opcode array. */
1666 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1669 p
= remove_leading_whitespaces (buf
);
1675 /* Skip comments. */
1676 str
= strstr (p
, "//");
1680 remove_trailing_whitespaces (p
);
1684 /* Look for line continuation character. */
1685 remove_trailing_whitespaces (p
);
1687 if (!j
|| buf
[j
- 1] != '+')
1689 if (j
>= sizeof (buf
) - 1)
1690 fail ("%s: %d: (continued) line too long\n", filename
, lineno
);
1692 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1694 fprintf (stderr
, "%s: Line continuation on last line?\n",
1703 if (!strcmp("### MARKER ###", buf
))
1707 /* Since we ignore all included files (we only care about their
1708 #define-s here), we don't need to monitor filenames. The final
1709 line number directive is going to refer to the main source file
1714 p
= remove_leading_whitespaces (p
+ 1);
1715 if (!strncmp(p
, "line", 4))
1717 ln
= strtoul (p
, &end
, 10);
1718 if (ln
> 1 && ln
< INT_MAX
1719 && *remove_leading_whitespaces (end
) == '"')
1722 /* Ignore comments. */
1727 parse_template (p
, lineno
);
1735 last
= p
+ strlen (p
);
1738 name
= next_field (p
, ',', &str
, last
);
1740 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1744 /* Process opcode array. */
1745 for (j
= 0; j
< i
; j
++)
1747 const char *name
= opcode_array
[j
]->name
;
1748 struct opcode_entry
*next
;
1750 for (next
= &opcode_array
[j
]->entry
; next
; next
= next
->next
)
1753 lineno
= next
->lineno
;
1754 last
= str
+ strlen (str
);
1755 output_i386_opcode (table
, name
, str
, last
, lineno
);
1761 fprintf (table
, "};\n");
1763 /* Generate opcode sets array. */
1764 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1765 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1766 fprintf (table
, " i386_optab,\n");
1768 for (nr
= j
= 0; j
< i
; j
++)
1770 struct opcode_entry
*next
= &opcode_array
[j
]->entry
;
1778 fprintf (table
, " i386_optab + %u,\n", nr
);
1781 fprintf (table
, "};\n");
1783 /* Emit mnemonics and associated #define-s. */
1784 qsort (opcode_array
, i
, sizeof (*opcode_array
), mnemonic_cmp
);
1786 fp
= fopen ("i386-mnem.h", "w");
1788 fail ("can't create i386-mnem.h, errno = %s\n",
1791 process_copyright (fp
);
1793 fprintf (table
, "\n/* i386 mnemonics table. */\n\n");
1794 fprintf (table
, "const char i386_mnemonics[] =\n");
1795 fprintf (fp
, "\nextern const char i386_mnemonics[];\n\n");
1798 for (l
= strlen (opcode_array
[offs
= j
= 0]->name
); j
< i
; j
++)
1800 const char *name
= opcode_array
[j
]->name
;
1801 const char *next
= NULL
;
1802 size_t l1
= j
+ 1 < i
? strlen(next
= opcode_array
[j
+ 1]->name
) : 0;
1805 str
= mkident (name
);
1806 if (l
< l1
&& !strcmp(name
, next
+ l1
- l
))
1808 fprintf (fp
, "#define MN_%s ", str
);
1810 str
= mkident (next
);
1811 fprintf (fp
, "(MN_%s + %u)\n", str
, l1
- l
);
1815 fprintf (table
, " \"\\0\"\"%s\"\n", name
);
1816 fprintf (fp
, "#define MN_%s %#x\n", str
, offs
+ 1);
1817 offs
+= strlen (name
) + 1;
1824 fprintf (table
, " \"\\0\"\".insn\"\n");
1825 fprintf (fp
, "#define MN__insn %#x\n", offs
+ 1);
1827 fprintf (table
, ";\n");
1833 process_i386_registers (FILE *table
)
1837 char *str
, *p
, *last
;
1838 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1839 char *dw2_32_num
, *dw2_64_num
;
1842 filename
= "i386-reg.tbl";
1843 fp
= fopen (filename
, "r");
1845 fail ("can't find i386-reg.tbl for reading, errno = %s\n",
1848 fprintf (table
, "\n/* i386 register table. */\n\n");
1849 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1853 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1858 p
= remove_leading_whitespaces (buf
);
1860 /* Skip comments. */
1861 str
= strstr (p
, "//");
1865 /* Remove trailing white spaces. */
1866 remove_trailing_whitespaces (p
);
1871 fprintf (table
, "%s\n", p
);
1879 last
= p
+ strlen (p
);
1881 /* Find reg_name. */
1882 reg_name
= next_field (p
, ',', &str
, last
);
1884 /* Find reg_type. */
1885 reg_type
= next_field (str
, ',', &str
, last
);
1887 /* Find reg_flags. */
1888 reg_flags
= next_field (str
, ',', &str
, last
);
1891 reg_num
= next_field (str
, ',', &str
, last
);
1893 fprintf (table
, " { \"%s\",\n ", reg_name
);
1895 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1898 /* Find 32-bit Dwarf2 register number. */
1899 dw2_32_num
= next_field (str
, ',', &str
, last
);
1901 /* Find 64-bit Dwarf2 register number. */
1902 dw2_64_num
= next_field (str
, ',', &str
, last
);
1904 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1905 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1910 fprintf (table
, "};\n");
1912 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1916 process_i386_initializers (void)
1919 FILE *fp
= fopen ("i386-init.h", "w");
1922 fail ("can't create i386-init.h, errno = %s\n",
1925 process_copyright (fp
);
1927 for (i
= 0; i
< Cpu64
; i
++)
1928 process_i386_cpu_flag (fp
, "0", cpu_flags
[i
].name
, "", " ", -1, i
);
1930 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); i
++)
1932 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
1934 process_i386_cpu_flag (fp
, deps
, isa_dependencies
[i
].name
,
1935 "", " ", -1, CpuMax
);
1939 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1940 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1941 one to 387. We want the reverse to be true though: Disabling 8087 also
1942 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1943 memcpy (isa_reverse_deps
[Cpu287
], isa_reverse_deps
[Cpu387
],
1944 sizeof (isa_reverse_deps
[0]));
1945 isa_reverse_deps
[Cpu287
][Cpu387
] = 1;
1946 memcpy (isa_reverse_deps
[Cpu8087
], isa_reverse_deps
[Cpu287
],
1947 sizeof (isa_reverse_deps
[0]));
1948 isa_reverse_deps
[Cpu8087
][Cpu287
] = 1;
1950 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1951 lead to disabling of anything else. */
1952 memset (isa_reverse_deps
[CpuPOPCNT
], 0, sizeof (isa_reverse_deps
[0]));
1954 for (i
= Cpu686
+ 1; i
< ARRAY_SIZE (isa_reverse_deps
); i
++)
1959 if (memchr(isa_reverse_deps
[i
], 1,
1960 ARRAY_SIZE (isa_reverse_deps
[0])) == NULL
)
1963 isa_reverse_deps
[i
][i
] = 1;
1964 process_i386_cpu_flag (fp
, NULL
, cpu_flags
[i
].name
, "", " ", -1, i
);
1972 /* Program options. */
1973 #define OPTION_SRCDIR 200
1975 struct option long_options
[] =
1977 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1978 {"debug", no_argument
, NULL
, 'd'},
1979 {"version", no_argument
, NULL
, 'V'},
1980 {"help", no_argument
, NULL
, 'h'},
1981 {0, no_argument
, NULL
, 0}
1985 print_version (void)
1987 printf ("%s: version 1.0\n", program_name
);
1992 usage (FILE * stream
, int status
)
1994 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2000 main (int argc
, char **argv
)
2002 extern int chdir (char *);
2003 char *srcdir
= NULL
;
2005 unsigned int i
, cpumax
;
2008 program_name
= *argv
;
2009 xmalloc_set_program_name (program_name
);
2011 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2036 if (chdir (srcdir
) != 0)
2037 fail ("unable to change directory to \"%s\", errno = %s\n",
2038 srcdir
, xstrerror (errno
));
2040 /* cpu_flags isn't sorted by position. */
2042 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2043 if (cpu_flags
[i
].position
> cpumax
)
2044 cpumax
= cpu_flags
[i
].position
;
2046 /* Check the unused bitfield in i386_cpu_flags. */
2048 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2050 if ((cpumax
- 1) != CpuMax
)
2051 fail ("CpuMax != %d!\n", cpumax
);
2053 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2055 if (cpumax
!= CpuMax
)
2056 fail ("CpuMax != %d!\n", cpumax
);
2058 c
= CpuNumOfBits
- CpuMax
- 1;
2060 fail ("%d unused bits in i386_cpu_flags.\n", c
);
2063 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2065 /* Check the unused bitfield in i386_operand_type. */
2067 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2070 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2073 c
= OTNumOfBits
- OTNum
;
2075 fail ("%d unused bits in i386_operand_type.\n", c
);
2078 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2081 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2082 sizeof (opcode_modifiers
[0]), compare
);
2084 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2085 sizeof (operand_types
[0]), compare
);
2087 table
= fopen ("i386-tbl.h", "w");
2089 fail ("can't create i386-tbl.h, errno = %s\n",
2092 process_copyright (table
);
2094 process_i386_opcodes (table
);
2095 process_i386_registers (table
);
2096 process_i386_initializers ();