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"
32 #define _(String) gettext (String)
34 /* Build-time checks are preferrable over runtime ones. Use this construct
35 in preference where possible. */
36 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
38 static const char *program_name
= NULL
;
41 typedef struct dependency
44 /* Note: Only direct dependencies should be enumerated. */
48 static const dependency isa_dependencies
[] =
55 "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" },
67 "GENERIC64|FISTTP|SSE3|CX16" },
69 "P4|FISTTP|SSE3|CX16" },
73 "CORE2|SSE4_2|Rdtscp" },
75 "186|286|386|486|586|SYSCALL|387|MMX" },
79 "K6_2|686:min|687|Nop|3dnowA" },
81 "ATHLON|Rdtscp|SSE2|LM" },
83 "K8|FISTTP|SSE4A|ABM" },
85 "GENERIC64|FISTTP|Rdtscp|CX16|XOP|ABM|LWP|SVME|AES|PCLMUL|PRFCHW" },
87 "BDVER1|FMA|BMI|TBM|F16C" },
89 "BDVER2|Xsaveopt|FSGSBase" },
91 "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" },
93 "GENERIC64|FISTTP|Rdtscp|CX16|AVX2|SSE4A|ABM|SVME|AES|PCLMUL|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" },
95 "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" },
97 "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" },
99 "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" },
101 "GENERIC64|FISTTP|CX16|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|CX16|Clflush|FISTTP|SVME" },
103 "BTVER1|AVX|BMI|F16C|AES|PCLMUL|Movbe|Xsaveopt|PRFCHW" },
115 "586|687|CMOV|FXSR" },
192 { "AVX512_VPOPCNTDQ",
200 { "AVX512_VP2INTERSECT",
252 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */
253 static unsigned char isa_reverse_deps
[Cpu64
][Cpu64
];
255 typedef struct bitfield
262 #define BITFIELD(n) { Cpu##n, 0, #n }
264 static bitfield cpu_flags
[] =
336 BITFIELD (ClflushOpt
),
339 BITFIELD (PREFETCHWT1
),
343 BITFIELD (AVX512IFMA
),
344 BITFIELD (AVX512VBMI
),
345 BITFIELD (AVX512_4FMAPS
),
346 BITFIELD (AVX512_4VNNIW
),
347 BITFIELD (AVX512_VPOPCNTDQ
),
348 BITFIELD (AVX512_VBMI2
),
349 BITFIELD (AVX512_VNNI
),
350 BITFIELD (AVX512_BITALG
),
351 BITFIELD (AVX512_BF16
),
352 BITFIELD (AVX512_VP2INTERSECT
),
355 BITFIELD (AVX512_FP16
),
356 BITFIELD (PREFETCHI
),
358 BITFIELD (AVX_VNNI_INT8
),
359 BITFIELD (CMPCCXADD
),
362 BITFIELD (AVX_NE_CONVERT
),
373 BITFIELD (VPCLMULQDQ
),
384 BITFIELD (MOVDIR64B
),
386 BITFIELD (SERIALIZE
),
406 #define BITFIELD(n) { n, 0, #n }
408 static bitfield opcode_modifiers
[] =
417 BITFIELD (CheckOperandSize
),
418 BITFIELD (OperandConstraint
),
419 BITFIELD (MnemonicSize
),
428 BITFIELD (BNDPrefixOk
),
436 BITFIELD (OpcodeSpace
),
437 BITFIELD (OpcodePrefix
),
438 BITFIELD (VexSources
),
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
, char **opnd
, int lineno
)
965 char *str
, *next
, *last
;
966 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
970 /* Copy the default opcode modifier. */
971 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
973 if (strcmp (mod
, "0"))
975 unsigned int have_w
= 0, bwlq_suf
= 0xf;
977 last
= mod
+ strlen (mod
);
978 for (next
= mod
; next
&& next
< last
; )
980 str
= next_field (next
, '|', &next
, last
);
984 if (strcasecmp(str
, "Broadcast") == 0)
985 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
986 else if (strcasecmp(str
, "Disp8MemShift") == 0)
987 val
= get_element_size (opnd
, lineno
);
989 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
991 if (strcasecmp(str
, "IsString") == 0)
994 if (strcasecmp(str
, "W") == 0)
997 if (strcasecmp(str
, "No_bSuf") == 0)
999 if (strcasecmp(str
, "No_wSuf") == 0)
1001 if (strcasecmp(str
, "No_lSuf") == 0)
1003 if (strcasecmp(str
, "No_qSuf") == 0)
1010 if (!modifiers
[OpcodeSpace
].value
)
1011 modifiers
[OpcodeSpace
].value
= space
;
1012 else if (modifiers
[OpcodeSpace
].value
!= space
)
1013 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1017 _("%s:%d: Warning: redundant opcode space specification\n"),
1023 if (!modifiers
[OpcodePrefix
].value
)
1024 modifiers
[OpcodePrefix
].value
= prefix
;
1025 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1026 fail (_("%s:%d: Conflicting prefix specifications\n"),
1030 _("%s:%d: Warning: redundant prefix specification\n"),
1034 if (have_w
&& !bwlq_suf
)
1035 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1036 if (have_w
&& !(bwlq_suf
& 1))
1037 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1039 if (have_w
&& !(bwlq_suf
& ~1))
1041 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1044 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1054 output_operand_type (FILE *table
, enum operand_class
class,
1055 enum operand_instance instance
,
1056 const bitfield
*types
, unsigned int size
,
1057 enum stage stage
, const char *indent
)
1061 fprintf (table
, "{ { %d, %d, ", class, instance
);
1063 for (i
= 0; i
< size
- 1; i
++)
1065 if (((i
+ 3) % 20) != 0)
1066 fprintf (table
, "%d, ", types
[i
].value
);
1068 fprintf (table
, "%d,", types
[i
].value
);
1069 if (((i
+ 3) % 20) == 0)
1071 /* We need \\ for macro. */
1072 if (stage
== stage_macros
)
1073 fprintf (table
, " \\\n%s", indent
);
1075 fprintf (table
, "\n%s", indent
);
1079 fprintf (table
, "%d } }", types
[i
].value
);
1083 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1084 const char *indent
, int lineno
)
1086 char *str
, *next
, *last
;
1087 enum operand_class
class = ClassNone
;
1088 enum operand_instance instance
= InstanceNone
;
1089 bitfield types
[ARRAY_SIZE (operand_types
)];
1091 /* Copy the default operand type. */
1092 memcpy (types
, operand_types
, sizeof (types
));
1094 if (strcmp (op
, "0"))
1098 last
= op
+ strlen (op
);
1099 for (next
= op
; next
&& next
< last
; )
1101 str
= next_field (next
, '|', &next
, last
);
1106 if (!strncmp(str
, "Class=", 6))
1108 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1109 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1111 class = operand_classes
[i
].value
;
1117 if (str
&& !strncmp(str
, "Instance=", 9))
1119 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1120 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1122 instance
= operand_instances
[i
].value
;
1130 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1131 if (strcasecmp(str
, "BaseIndex") == 0)
1136 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1138 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1139 if (!active_cpu_flags
.bitfield
.cpu64
1140 && !active_cpu_flags
.bitfield
.cpumpx
)
1141 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1142 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1145 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1149 static char *mkident (const char *mnem
)
1151 char *ident
= xstrdup (mnem
), *p
= ident
;
1164 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1165 char *last
, int lineno
)
1167 unsigned int i
, length
, prefix
= 0, space
= 0;
1168 char *base_opcode
, *extension_opcode
, *end
, *ident
;
1169 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1170 unsigned long long opcode
;
1172 /* Find base_opcode. */
1173 base_opcode
= next_field (str
, ',', &str
, last
);
1175 /* Find extension_opcode, if any. */
1176 extension_opcode
= strchr (base_opcode
, '/');
1177 if (extension_opcode
)
1178 *extension_opcode
++ = '\0';
1180 /* Find cpu_flags. */
1181 cpu_flags
= next_field (str
, ',', &str
, last
);
1183 /* Find opcode_modifier. */
1184 opcode_modifier
= next_field (str
, ',', &str
, last
);
1186 /* Remove the first {. */
1187 str
= remove_leading_whitespaces (str
);
1190 str
= remove_leading_whitespaces (str
+ 1);
1191 remove_trailing_whitespaces (str
);
1193 /* Remove } and trailing white space. */
1195 if (!i
|| str
[i
- 1] != '}')
1198 remove_trailing_whitespaces (str
);
1201 operand_types
[i
= 0] = NULL
;
1204 last
= str
+ strlen (str
);
1206 /* Find operand_types. */
1207 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1211 operand_types
[i
] = NULL
;
1215 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1219 opcode
= strtoull (base_opcode
, &end
, 0);
1221 /* Determine opcode length. */
1222 for (length
= 1; length
< 8; ++length
)
1223 if (!(opcode
>> (8 * length
)))
1226 /* Transform prefixes encoded in the opcode into opcode modifier
1230 switch (opcode
>> (8 * length
- 8))
1232 case 0x66: prefix
= PREFIX_0X66
; break;
1233 case 0xF3: prefix
= PREFIX_0XF3
; break;
1234 case 0xF2: prefix
= PREFIX_0XF2
; break;
1238 opcode
&= (1ULL << (8 * --length
)) - 1;
1241 /* Transform opcode space encoded in the opcode into opcode modifier
1243 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1245 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1247 default: space
= SPACE_0F
; break;
1248 case 0x38: space
= SPACE_0F38
; break;
1249 case 0x3A: space
= SPACE_0F3A
; break;
1252 if (space
!= SPACE_0F
&& --length
== 1)
1253 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1254 filename
, lineno
, name
);
1255 opcode
&= (1ULL << (8 * --length
)) - 1;
1259 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1260 filename
, lineno
, name
, 2 * length
, opcode
);
1262 ident
= mkident (name
);
1263 fprintf (table
, " { MN_%s, 0x%0*llx%s, %lu, %s,\n",
1264 ident
, 2 * (int)length
, opcode
, end
, i
,
1265 extension_opcode
? extension_opcode
: "None");
1268 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1269 operand_types
, lineno
);
1271 process_i386_cpu_flag (table
, cpu_flags
, NULL
, ",", " ", lineno
, CpuMax
);
1273 fprintf (table
, " { ");
1275 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1277 if (!operand_types
[i
])
1280 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1286 fprintf (table
, ",\n ");
1288 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1291 fprintf (table
, " } },\n");
1294 struct opcode_hash_entry
1296 struct opcode_hash_entry
*next
;
1302 /* Calculate the hash value of an opcode hash entry P. */
1305 opcode_hash_hash (const void *p
)
1307 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1308 return htab_hash_string (entry
->name
);
1311 /* Compare a string Q against an opcode hash entry P. */
1314 opcode_hash_eq (const void *p
, const void *q
)
1316 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1317 const char *name
= (const char *) q
;
1318 return strcmp (name
, entry
->name
) == 0;
1322 parse_template (char *buf
, int lineno
)
1324 char sep
, *end
, *name
;
1325 struct template *tmpl
;
1326 struct template_instance
*last_inst
= NULL
;
1328 buf
= remove_leading_whitespaces (buf
+ 1);
1329 end
= strchr (buf
, ':');
1332 struct template *prev
= NULL
;
1334 end
= strchr (buf
, '>');
1336 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1337 if (*remove_leading_whitespaces (end
+ 1))
1338 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1340 remove_trailing_whitespaces (buf
);
1341 /* Don't bother freeing the various structures. */
1342 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1343 if (!strcmp (buf
, tmpl
->name
))
1346 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1348 prev
->next
= tmpl
->next
;
1350 templates
= tmpl
->next
;
1354 remove_trailing_whitespaces (buf
);
1357 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1358 tmpl
= xmalloc (sizeof (*tmpl
));
1359 tmpl
->name
= xstrdup (buf
);
1361 tmpl
->params
= NULL
;
1363 struct template_param
*param
;
1365 buf
= remove_leading_whitespaces (end
);
1366 end
= strpbrk (buf
, ":,");
1368 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1372 remove_trailing_whitespaces (buf
);
1374 param
= xmalloc (sizeof (*param
));
1375 param
->name
= xstrdup (buf
);
1376 param
->next
= tmpl
->params
;
1377 tmpl
->params
= param
;
1378 } while (sep
== ':');
1380 tmpl
->instances
= NULL
;
1382 struct template_instance
*inst
;
1384 const struct template_param
*param
;
1386 buf
= remove_leading_whitespaces (end
);
1387 end
= strpbrk (buf
, ",>");
1389 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1394 inst
= xmalloc (sizeof (*inst
));
1398 cur
= next_field (buf
, ':', &next
, end
);
1399 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1401 for (param
= tmpl
->params
; param
; param
= param
->next
)
1403 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1405 cur
= next_field (next
, ':', &next
, end
);
1407 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1408 arg
->val
= xstrdup (cur
);
1409 arg
->next
= inst
->args
;
1413 if (tmpl
->instances
)
1414 last_inst
->next
= inst
;
1416 tmpl
->instances
= inst
;
1418 } while (sep
== ',');
1420 buf
= remove_leading_whitespaces (end
);
1422 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1423 filename
, lineno
, buf
);
1425 tmpl
->next
= templates
;
1430 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1431 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1433 static unsigned int idx
, opcode_array_size
;
1434 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1435 struct opcode_hash_entry
**hash_slot
, **entry
;
1436 char *ptr1
= strchr(name
, '<'), *ptr2
;
1440 /* Get the slot in hash table. */
1441 hash_slot
= (struct opcode_hash_entry
**)
1442 htab_find_slot_with_hash (opcode_hash_table
, name
,
1443 htab_hash_string (name
),
1446 if (*hash_slot
== NULL
)
1448 /* It is the new one. Put it on opcode array. */
1449 if (idx
>= opcode_array_size
)
1451 /* Grow the opcode array when needed. */
1452 opcode_array_size
+= 1024;
1453 opcode_array
= (struct opcode_hash_entry
**)
1454 xrealloc (opcode_array
,
1455 sizeof (*opcode_array
) * opcode_array_size
);
1456 *opcode_array_p
= opcode_array
;
1459 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1460 xmalloc (sizeof (struct opcode_hash_entry
));
1461 opcode_array
[idx
]->next
= NULL
;
1462 opcode_array
[idx
]->name
= xstrdup (name
);
1463 opcode_array
[idx
]->opcode
= xstrdup (str
);
1464 opcode_array
[idx
]->lineno
= lineno
;
1465 *hash_slot
= opcode_array
[idx
];
1470 /* Append it to the existing one. */
1472 while ((*entry
) != NULL
)
1473 entry
= &(*entry
)->next
;
1474 *entry
= (struct opcode_hash_entry
*)
1475 xmalloc (sizeof (struct opcode_hash_entry
));
1476 (*entry
)->next
= NULL
;
1477 (*entry
)->name
= (*hash_slot
)->name
;
1478 (*entry
)->opcode
= xstrdup (str
);
1479 (*entry
)->lineno
= lineno
;
1482 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1483 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1486 const struct template *tmpl
;
1487 const struct template_instance
*inst
;
1490 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1491 remove_trailing_whitespaces (ptr1
);
1495 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1496 if (!strcmp(ptr1
, tmpl
->name
))
1499 fail ("reference to unknown template '%s'\n", ptr1
);
1501 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1503 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1504 char *str2
= xmalloc(2 * strlen(str
));
1507 strcpy (name2
, name
);
1508 strcat (name2
, inst
->name
);
1509 strcat (name2
, ptr2
);
1511 for (ptr1
= str2
, src
= str
; *src
; )
1513 const char *ident
= tmpl
->name
, *end
;
1514 const struct template_param
*param
;
1515 const struct template_arg
*arg
;
1517 if ((*ptr1
= *src
++) != '<')
1522 while (ISSPACE(*src
))
1524 while (*ident
&& *src
== *ident
)
1526 while (ISSPACE(*src
))
1528 if (*src
!= ':' || *ident
!= '\0')
1530 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1531 ptr1
+= ident
- tmpl
->name
;
1534 while (ISSPACE(*++src
))
1538 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1541 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1542 param
= param
->next
, arg
= arg
->next
)
1544 if (end
- src
== strlen (param
->name
)
1545 && !memcmp (src
, param
->name
, end
- src
))
1553 fail ("template '%s' has no parameter '%.*s'\n",
1554 tmpl
->name
, (int)(end
- src
), src
);
1556 while (ISSPACE(*src
))
1559 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1561 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1562 ptr1
+= strlen(arg
->val
);
1568 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1579 static int mnemonic_cmp(const void *p1
, const void *p2
)
1581 const struct opcode_hash_entry
*const *e1
= p1
, *const *e2
= p2
;
1582 const char *s1
= (*e1
)->name
, *s2
= (*e2
)->name
;
1584 size_t l1
= strlen (s1
), l2
= strlen (s2
);
1586 for (i
= 1; i
<= l1
&& i
<= l2
; ++i
)
1588 if (s1
[l1
- i
] != s2
[l2
- i
])
1589 return (unsigned char)s1
[l1
- i
] - (unsigned char)s2
[l2
- i
];
1592 return (int)(l1
- l2
);
1596 process_i386_opcodes (FILE *table
)
1600 unsigned int i
, j
, nr
, offs
;
1602 char *str
, *p
, *last
, *name
;
1603 htab_t opcode_hash_table
;
1604 struct opcode_hash_entry
**opcode_array
= NULL
;
1605 int lineno
= 0, marker
= 0;
1607 filename
= "i386-opc.tbl";
1611 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1612 opcode_hash_eq
, NULL
,
1615 fprintf (table
, "\n#include \"i386-mnem.h\"\n");
1616 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1617 fprintf (table
, "static const insn_template i386_optab[] =\n{\n");
1619 /* Put everything on opcode array. */
1622 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1625 p
= remove_leading_whitespaces (buf
);
1631 /* Skip comments. */
1632 str
= strstr (p
, "//");
1636 remove_trailing_whitespaces (p
);
1640 /* Look for line continuation character. */
1641 remove_trailing_whitespaces (p
);
1643 if (!j
|| buf
[j
- 1] != '+')
1645 if (j
>= sizeof (buf
) - 1)
1646 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1648 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1650 fprintf (stderr
, "%s: Line continuation on last line?\n",
1659 if (!strcmp("### MARKER ###", buf
))
1663 /* Since we ignore all included files (we only care about their
1664 #define-s here), we don't need to monitor filenames. The final
1665 line number directive is going to refer to the main source file
1670 p
= remove_leading_whitespaces (p
+ 1);
1671 if (!strncmp(p
, "line", 4))
1673 ln
= strtoul (p
, &end
, 10);
1674 if (ln
> 1 && ln
< INT_MAX
1675 && *remove_leading_whitespaces (end
) == '"')
1678 /* Ignore comments. */
1683 parse_template (p
, lineno
);
1691 last
= p
+ strlen (p
);
1694 name
= next_field (p
, ',', &str
, last
);
1696 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1700 /* Process opcode array. */
1701 for (j
= 0; j
< i
; j
++)
1703 struct opcode_hash_entry
*next
;
1705 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1709 lineno
= next
->lineno
;
1710 last
= str
+ strlen (str
);
1711 output_i386_opcode (table
, name
, str
, last
, lineno
);
1717 fprintf (table
, "};\n");
1719 /* Generate opcode sets array. */
1720 fprintf (table
, "\n/* i386 opcode sets table. */\n\n");
1721 fprintf (table
, "static const insn_template *const i386_op_sets[] =\n{\n");
1722 fprintf (table
, " i386_optab,\n");
1724 for (nr
= j
= 0; j
< i
; j
++)
1726 struct opcode_hash_entry
*next
= opcode_array
[j
];
1734 fprintf (table
, " i386_optab + %u,\n", nr
);
1737 fprintf (table
, "};\n");
1739 /* Emit mnemonics and associated #define-s. */
1740 qsort (opcode_array
, i
, sizeof (*opcode_array
), mnemonic_cmp
);
1742 fp
= fopen ("i386-mnem.h", "w");
1744 fail (_("can't create i386-mnem.h, errno = %s\n"),
1747 process_copyright (fp
);
1749 fprintf (table
, "\n/* i386 mnemonics table. */\n\n");
1750 fprintf (table
, "const char i386_mnemonics[] =\n");
1751 fprintf (fp
, "\nextern const char i386_mnemonics[];\n\n");
1753 for (l
= strlen (opcode_array
[offs
= j
= 0]->name
); j
< i
; j
++)
1755 const char *next
= NULL
;
1756 size_t l1
= j
+ 1 < i
? strlen(next
= opcode_array
[j
+ 1]->name
) : 0;
1758 name
= opcode_array
[j
]->name
;
1759 str
= mkident (name
);
1760 if (l
< l1
&& !strcmp(name
, next
+ l1
- l
))
1762 fprintf (fp
, "#define MN_%s ", str
);
1764 str
= mkident (next
);
1765 fprintf (fp
, "(MN_%s + %u)\n", str
, l1
- l
);
1769 fprintf (table
, " \"\\0\"\"%s\"\n", name
);
1770 fprintf (fp
, "#define MN_%s %#x\n", str
, offs
+ 1);
1771 offs
+= strlen (name
) + 1;
1777 fprintf (table
, ";\n");
1783 process_i386_registers (FILE *table
)
1787 char *str
, *p
, *last
;
1788 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1789 char *dw2_32_num
, *dw2_64_num
;
1792 filename
= "i386-reg.tbl";
1793 fp
= fopen (filename
, "r");
1795 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1798 fprintf (table
, "\n/* i386 register table. */\n\n");
1799 fprintf (table
, "static const reg_entry i386_regtab[] =\n{\n");
1803 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1808 p
= remove_leading_whitespaces (buf
);
1810 /* Skip comments. */
1811 str
= strstr (p
, "//");
1815 /* Remove trailing white spaces. */
1816 remove_trailing_whitespaces (p
);
1821 fprintf (table
, "%s\n", p
);
1829 last
= p
+ strlen (p
);
1831 /* Find reg_name. */
1832 reg_name
= next_field (p
, ',', &str
, last
);
1834 /* Find reg_type. */
1835 reg_type
= next_field (str
, ',', &str
, last
);
1837 /* Find reg_flags. */
1838 reg_flags
= next_field (str
, ',', &str
, last
);
1841 reg_num
= next_field (str
, ',', &str
, last
);
1843 fprintf (table
, " { \"%s\",\n ", reg_name
);
1845 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1848 /* Find 32-bit Dwarf2 register number. */
1849 dw2_32_num
= next_field (str
, ',', &str
, last
);
1851 /* Find 64-bit Dwarf2 register number. */
1852 dw2_64_num
= next_field (str
, ',', &str
, last
);
1854 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1855 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
1860 fprintf (table
, "};\n");
1862 fprintf (table
, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1866 process_i386_initializers (void)
1869 FILE *fp
= fopen ("i386-init.h", "w");
1872 fail (_("can't create i386-init.h, errno = %s\n"),
1875 process_copyright (fp
);
1877 for (i
= 0; i
< Cpu64
; i
++)
1878 process_i386_cpu_flag (fp
, "0", cpu_flags
[i
].name
, "", " ", -1, i
);
1880 for (i
= 0; i
< ARRAY_SIZE (isa_dependencies
); i
++)
1882 char *deps
= xstrdup (isa_dependencies
[i
].deps
);
1884 process_i386_cpu_flag (fp
, deps
, isa_dependencies
[i
].name
,
1885 "", " ", -1, CpuMax
);
1889 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
1890 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
1891 one to 387. We want the reverse to be true though: Disabling 8087 also
1892 is to disable 287+ and later; disabling 287 also means disabling 387+. */
1893 memcpy (isa_reverse_deps
[Cpu287
], isa_reverse_deps
[Cpu387
],
1894 sizeof (isa_reverse_deps
[0]));
1895 isa_reverse_deps
[Cpu287
][Cpu387
] = 1;
1896 memcpy (isa_reverse_deps
[Cpu8087
], isa_reverse_deps
[Cpu287
],
1897 sizeof (isa_reverse_deps
[0]));
1898 isa_reverse_deps
[Cpu8087
][Cpu287
] = 1;
1900 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
1901 lead to disabling of anything else. */
1902 memset (isa_reverse_deps
[CpuPOPCNT
], 0, sizeof (isa_reverse_deps
[0]));
1904 for (i
= Cpu686
+ 1; i
< ARRAY_SIZE (isa_reverse_deps
); i
++)
1909 if (memchr(isa_reverse_deps
[i
], 1,
1910 ARRAY_SIZE (isa_reverse_deps
[0])) == NULL
)
1913 isa_reverse_deps
[i
][i
] = 1;
1914 process_i386_cpu_flag (fp
, NULL
, cpu_flags
[i
].name
, "", " ", -1, i
);
1922 /* Program options. */
1923 #define OPTION_SRCDIR 200
1925 struct option long_options
[] =
1927 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
1928 {"debug", no_argument
, NULL
, 'd'},
1929 {"version", no_argument
, NULL
, 'V'},
1930 {"help", no_argument
, NULL
, 'h'},
1931 {0, no_argument
, NULL
, 0}
1935 print_version (void)
1937 printf ("%s: version 1.0\n", program_name
);
1942 usage (FILE * stream
, int status
)
1944 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
1950 main (int argc
, char **argv
)
1952 extern int chdir (char *);
1953 char *srcdir
= NULL
;
1955 unsigned int i
, cpumax
;
1958 program_name
= *argv
;
1959 xmalloc_set_program_name (program_name
);
1961 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
1986 if (chdir (srcdir
) != 0)
1987 fail (_("unable to change directory to \"%s\", errno = %s\n"),
1988 srcdir
, xstrerror (errno
));
1990 /* cpu_flags isn't sorted by position. */
1992 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
1993 if (cpu_flags
[i
].position
> cpumax
)
1994 cpumax
= cpu_flags
[i
].position
;
1996 /* Check the unused bitfield in i386_cpu_flags. */
1998 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2000 if ((cpumax
- 1) != CpuMax
)
2001 fail (_("CpuMax != %d!\n"), cpumax
);
2003 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2005 if (cpumax
!= CpuMax
)
2006 fail (_("CpuMax != %d!\n"), cpumax
);
2008 c
= CpuNumOfBits
- CpuMax
- 1;
2010 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2013 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2015 /* Check the unused bitfield in i386_operand_type. */
2017 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2020 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2023 c
= OTNumOfBits
- OTNum
;
2025 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2028 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2031 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2032 sizeof (opcode_modifiers
[0]), compare
);
2034 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2035 sizeof (operand_types
[0]), compare
);
2037 table
= fopen ("i386-tbl.h", "w");
2039 fail (_("can't create i386-tbl.h, errno = %s\n"),
2042 process_copyright (table
);
2044 process_i386_opcodes (table
);
2045 process_i386_registers (table
);
2046 process_i386_initializers ();