x86: correct CPU_AMX_{BF16,INT8}_FLAGS
[binutils-gdb.git] / opcodes / i386-gen.c
1 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
2
3 This file is part of the GNU opcodes library.
4
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)
8 any later version.
9
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.
14
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. */
19
20 #include "sysdep.h"
21 #include <stdio.h>
22 #include <errno.h>
23 #include "getopt.h"
24 #include "libiberty.h"
25 #include "hashtab.h"
26 #include "safe-ctype.h"
27
28 #include "i386-opc.h"
29
30 #include <libintl.h>
31 #define _(String) gettext (String)
32
33 /* Build-time checks are preferrable over runtime ones. Use this construct
34 in preference where possible. */
35 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
36
37 static const char *program_name = NULL;
38 static int debug = 0;
39
40 typedef struct initializer
41 {
42 const char *name;
43 const char *init;
44 } initializer;
45
46 static initializer cpu_flag_init[] =
47 {
48 { "CPU_UNKNOWN_FLAGS",
49 "~CpuIAMCU" },
50 { "CPU_GENERIC32_FLAGS",
51 "Cpu186|Cpu286|Cpu386" },
52 { "CPU_GENERIC64_FLAGS",
53 "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
54 { "CPU_NONE_FLAGS",
55 "0" },
56 { "CPU_I186_FLAGS",
57 "Cpu186" },
58 { "CPU_I286_FLAGS",
59 "CPU_I186_FLAGS|Cpu286" },
60 { "CPU_I386_FLAGS",
61 "CPU_I286_FLAGS|Cpu386" },
62 { "CPU_I486_FLAGS",
63 "CPU_I386_FLAGS|Cpu486" },
64 { "CPU_I586_FLAGS",
65 "CPU_I486_FLAGS|Cpu387|Cpu586" },
66 { "CPU_I686_FLAGS",
67 "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68 { "CPU_PENTIUMPRO_FLAGS",
69 "CPU_I686_FLAGS|CpuNop" },
70 { "CPU_P2_FLAGS",
71 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
72 { "CPU_P3_FLAGS",
73 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
74 { "CPU_P4_FLAGS",
75 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
76 { "CPU_NOCONA_FLAGS",
77 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
78 { "CPU_CORE_FLAGS",
79 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
80 { "CPU_CORE2_FLAGS",
81 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
82 { "CPU_COREI7_FLAGS",
83 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
84 { "CPU_K6_FLAGS",
85 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
86 { "CPU_K6_2_FLAGS",
87 "CPU_K6_FLAGS|Cpu3dnow" },
88 { "CPU_ATHLON_FLAGS",
89 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
90 { "CPU_K8_FLAGS",
91 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92 { "CPU_AMDFAM10_FLAGS",
93 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
94 { "CPU_BDVER1_FLAGS",
95 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
96 { "CPU_BDVER2_FLAGS",
97 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
98 { "CPU_BDVER3_FLAGS",
99 "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
100 { "CPU_BDVER4_FLAGS",
101 "CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
102 { "CPU_ZNVER1_FLAGS",
103 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
104 { "CPU_ZNVER2_FLAGS",
105 "CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
106 { "CPU_ZNVER3_FLAGS",
107 "CPU_ZNVER2_FLAGS|CpuINVLPGB|CpuTLBSYNC|CpuVAES|CpuVPCLMULQDQ|CpuINVPCID|CpuSNP|CpuOSPKE" },
108 { "CPU_BTVER1_FLAGS",
109 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
110 { "CPU_BTVER2_FLAGS",
111 "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
112 { "CPU_8087_FLAGS",
113 "Cpu8087" },
114 { "CPU_287_FLAGS",
115 "Cpu287" },
116 { "CPU_387_FLAGS",
117 "Cpu387" },
118 { "CPU_687_FLAGS",
119 "CPU_387_FLAGS|Cpu687" },
120 { "CPU_CMOV_FLAGS",
121 "CpuCMOV" },
122 { "CPU_FXSR_FLAGS",
123 "CpuFXSR" },
124 { "CPU_CLFLUSH_FLAGS",
125 "CpuClflush" },
126 { "CPU_NOP_FLAGS",
127 "CpuNop" },
128 { "CPU_SYSCALL_FLAGS",
129 "CpuSYSCALL" },
130 { "CPU_MMX_FLAGS",
131 "CpuMMX" },
132 { "CPU_SSE_FLAGS",
133 "CpuSSE" },
134 { "CPU_SSE2_FLAGS",
135 "CPU_SSE_FLAGS|CpuSSE2" },
136 { "CPU_SSE3_FLAGS",
137 "CPU_SSE2_FLAGS|CpuSSE3" },
138 { "CPU_SSSE3_FLAGS",
139 "CPU_SSE3_FLAGS|CpuSSSE3" },
140 { "CPU_SSE4_1_FLAGS",
141 "CPU_SSSE3_FLAGS|CpuSSE4_1" },
142 { "CPU_SSE4_2_FLAGS",
143 "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
144 { "CPU_VMX_FLAGS",
145 "CpuVMX" },
146 { "CPU_SMX_FLAGS",
147 "CpuSMX" },
148 { "CPU_XSAVE_FLAGS",
149 "CpuXsave" },
150 { "CPU_XSAVEOPT_FLAGS",
151 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
152 { "CPU_AES_FLAGS",
153 "CPU_SSE2_FLAGS|CpuAES" },
154 { "CPU_PCLMUL_FLAGS",
155 "CPU_SSE2_FLAGS|CpuPCLMUL" },
156 { "CPU_FMA_FLAGS",
157 "CPU_AVX_FLAGS|CpuFMA" },
158 { "CPU_FMA4_FLAGS",
159 "CPU_AVX_FLAGS|CpuFMA4" },
160 { "CPU_XOP_FLAGS",
161 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
162 { "CPU_LWP_FLAGS",
163 "CPU_XSAVE_FLAGS|CpuLWP" },
164 { "CPU_BMI_FLAGS",
165 "CpuBMI" },
166 { "CPU_TBM_FLAGS",
167 "CpuTBM" },
168 { "CPU_MOVBE_FLAGS",
169 "CpuMovbe" },
170 { "CPU_CX16_FLAGS",
171 "CpuCX16" },
172 { "CPU_RDTSCP_FLAGS",
173 "CpuRdtscp" },
174 { "CPU_EPT_FLAGS",
175 "CpuEPT" },
176 { "CPU_FSGSBASE_FLAGS",
177 "CpuFSGSBase" },
178 { "CPU_RDRND_FLAGS",
179 "CpuRdRnd" },
180 { "CPU_F16C_FLAGS",
181 "CPU_AVX_FLAGS|CpuF16C" },
182 { "CPU_BMI2_FLAGS",
183 "CpuBMI2" },
184 { "CPU_LZCNT_FLAGS",
185 "CpuLZCNT" },
186 { "CPU_POPCNT_FLAGS",
187 "CpuPOPCNT" },
188 { "CPU_HLE_FLAGS",
189 "CpuHLE" },
190 { "CPU_RTM_FLAGS",
191 "CpuRTM" },
192 { "CPU_INVPCID_FLAGS",
193 "CpuINVPCID" },
194 { "CPU_VMFUNC_FLAGS",
195 "CpuVMFUNC" },
196 { "CPU_3DNOW_FLAGS",
197 "CPU_MMX_FLAGS|Cpu3dnow" },
198 { "CPU_3DNOWA_FLAGS",
199 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
200 { "CPU_PADLOCK_FLAGS",
201 "CpuPadLock" },
202 { "CPU_SVME_FLAGS",
203 "CpuSVME" },
204 { "CPU_SSE4A_FLAGS",
205 "CPU_SSE3_FLAGS|CpuSSE4a" },
206 { "CPU_ABM_FLAGS",
207 "CpuLZCNT|CpuPOPCNT" },
208 { "CPU_AVX_FLAGS",
209 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
210 { "CPU_AVX2_FLAGS",
211 "CPU_AVX_FLAGS|CpuAVX2" },
212 { "CPU_AVX_VNNI_FLAGS",
213 "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
214 { "CPU_AVX512F_FLAGS",
215 "CPU_AVX2_FLAGS|CpuAVX512F" },
216 { "CPU_AVX512CD_FLAGS",
217 "CPU_AVX512F_FLAGS|CpuAVX512CD" },
218 { "CPU_AVX512ER_FLAGS",
219 "CPU_AVX512F_FLAGS|CpuAVX512ER" },
220 { "CPU_AVX512PF_FLAGS",
221 "CPU_AVX512F_FLAGS|CpuAVX512PF" },
222 { "CPU_AVX512DQ_FLAGS",
223 "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
224 { "CPU_AVX512BW_FLAGS",
225 "CPU_AVX512F_FLAGS|CpuAVX512BW" },
226 { "CPU_AVX512VL_FLAGS",
227 "CPU_AVX512F_FLAGS|CpuAVX512VL" },
228 { "CPU_AVX512IFMA_FLAGS",
229 "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
230 { "CPU_AVX512VBMI_FLAGS",
231 "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
232 { "CPU_AVX512_4FMAPS_FLAGS",
233 "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
234 { "CPU_AVX512_4VNNIW_FLAGS",
235 "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
236 { "CPU_AVX512_VPOPCNTDQ_FLAGS",
237 "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
238 { "CPU_AVX512_VBMI2_FLAGS",
239 "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
240 { "CPU_AVX512_VNNI_FLAGS",
241 "CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
242 { "CPU_AVX512_BITALG_FLAGS",
243 "CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
244 { "CPU_AVX512_BF16_FLAGS",
245 "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
246 { "CPU_AVX512_FP16_FLAGS",
247 "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
248 { "CPU_IAMCU_FLAGS",
249 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
250 { "CPU_ADX_FLAGS",
251 "CpuADX" },
252 { "CPU_RDSEED_FLAGS",
253 "CpuRdSeed" },
254 { "CPU_PRFCHW_FLAGS",
255 "CpuPRFCHW" },
256 { "CPU_SMAP_FLAGS",
257 "CpuSMAP" },
258 { "CPU_MPX_FLAGS",
259 "CPU_XSAVE_FLAGS|CpuMPX" },
260 { "CPU_SHA_FLAGS",
261 "CPU_SSE2_FLAGS|CpuSHA" },
262 { "CPU_CLFLUSHOPT_FLAGS",
263 "CpuClflushOpt" },
264 { "CPU_XSAVES_FLAGS",
265 "CPU_XSAVE_FLAGS|CpuXSAVES" },
266 { "CPU_XSAVEC_FLAGS",
267 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
268 { "CPU_PREFETCHWT1_FLAGS",
269 "CpuPREFETCHWT1" },
270 { "CPU_SE1_FLAGS",
271 "CpuSE1" },
272 { "CPU_CLWB_FLAGS",
273 "CpuCLWB" },
274 { "CPU_CLZERO_FLAGS",
275 "CpuCLZERO" },
276 { "CPU_MWAITX_FLAGS",
277 "CpuMWAITX" },
278 { "CPU_OSPKE_FLAGS",
279 "CPU_XSAVE_FLAGS|CpuOSPKE" },
280 { "CPU_RDPID_FLAGS",
281 "CpuRDPID" },
282 { "CPU_PTWRITE_FLAGS",
283 "CpuPTWRITE" },
284 { "CPU_IBT_FLAGS",
285 "CpuIBT" },
286 { "CPU_SHSTK_FLAGS",
287 "CpuSHSTK" },
288 { "CPU_GFNI_FLAGS",
289 "CpuGFNI" },
290 { "CPU_VAES_FLAGS",
291 "CpuVAES" },
292 { "CPU_VPCLMULQDQ_FLAGS",
293 "CpuVPCLMULQDQ" },
294 { "CPU_WBNOINVD_FLAGS",
295 "CpuWBNOINVD" },
296 { "CPU_PCONFIG_FLAGS",
297 "CpuPCONFIG" },
298 { "CPU_WAITPKG_FLAGS",
299 "CpuWAITPKG" },
300 { "CPU_UINTR_FLAGS",
301 "CpuUINTR" },
302 { "CPU_CLDEMOTE_FLAGS",
303 "CpuCLDEMOTE" },
304 { "CPU_AMX_INT8_FLAGS",
305 "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
306 { "CPU_AMX_BF16_FLAGS",
307 "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
308 { "CPU_AMX_TILE_FLAGS",
309 "CpuAMX_TILE" },
310 { "CPU_MOVDIRI_FLAGS",
311 "CpuMOVDIRI" },
312 { "CPU_MOVDIR64B_FLAGS",
313 "CpuMOVDIR64B" },
314 { "CPU_ENQCMD_FLAGS",
315 "CpuENQCMD" },
316 { "CPU_SERIALIZE_FLAGS",
317 "CpuSERIALIZE" },
318 { "CPU_AVX512_VP2INTERSECT_FLAGS",
319 "CpuAVX512_VP2INTERSECT" },
320 { "CPU_TDX_FLAGS",
321 "CpuTDX" },
322 { "CPU_RDPRU_FLAGS",
323 "CpuRDPRU" },
324 { "CPU_MCOMMIT_FLAGS",
325 "CpuMCOMMIT" },
326 { "CPU_SEV_ES_FLAGS",
327 "CpuSEV_ES" },
328 { "CPU_TSXLDTRK_FLAGS",
329 "CpuTSXLDTRK"},
330 { "CPU_KL_FLAGS",
331 "CpuKL" },
332 { "CPU_WIDEKL_FLAGS",
333 "CpuWideKL" },
334 { "CPU_HRESET_FLAGS",
335 "CpuHRESET"},
336 { "CPU_INVLPGB_FLAGS",
337 "CpuINVLPGB" },
338 { "CPU_TLBSYNC_FLAGS",
339 "CpuTLBSYNC" },
340 { "CPU_SNP_FLAGS",
341 "CpuSNP" },
342 { "CPU_ANY_X87_FLAGS",
343 "CPU_ANY_287_FLAGS|Cpu8087" },
344 { "CPU_ANY_287_FLAGS",
345 "CPU_ANY_387_FLAGS|Cpu287" },
346 { "CPU_ANY_387_FLAGS",
347 "CPU_ANY_687_FLAGS|Cpu387" },
348 { "CPU_ANY_687_FLAGS",
349 "Cpu687|CpuFISTTP" },
350 { "CPU_ANY_CMOV_FLAGS",
351 "CpuCMOV" },
352 { "CPU_ANY_FXSR_FLAGS",
353 "CpuFXSR" },
354 { "CPU_ANY_MMX_FLAGS",
355 "CPU_3DNOWA_FLAGS" },
356 { "CPU_ANY_SSE_FLAGS",
357 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
358 { "CPU_ANY_SSE2_FLAGS",
359 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
360 { "CPU_ANY_SSE3_FLAGS",
361 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
362 { "CPU_ANY_SSSE3_FLAGS",
363 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
364 { "CPU_ANY_SSE4_1_FLAGS",
365 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
366 { "CPU_ANY_SSE4_2_FLAGS",
367 "CpuSSE4_2" },
368 { "CPU_ANY_SSE4A_FLAGS",
369 "CpuSSE4a" },
370 { "CPU_ANY_AVX_FLAGS",
371 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
372 { "CPU_ANY_AVX2_FLAGS",
373 "CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
374 { "CPU_ANY_AVX512F_FLAGS",
375 "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CPU_ANY_AVX512BW_FLAGS|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
376 { "CPU_ANY_AVX512CD_FLAGS",
377 "CpuAVX512CD" },
378 { "CPU_ANY_AVX512ER_FLAGS",
379 "CpuAVX512ER" },
380 { "CPU_ANY_AVX512PF_FLAGS",
381 "CpuAVX512PF" },
382 { "CPU_ANY_AVX512DQ_FLAGS",
383 "CpuAVX512DQ" },
384 { "CPU_ANY_AVX512BW_FLAGS",
385 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
386 { "CPU_ANY_AVX512VL_FLAGS",
387 "CpuAVX512VL" },
388 { "CPU_ANY_AVX512IFMA_FLAGS",
389 "CpuAVX512IFMA" },
390 { "CPU_ANY_AVX512VBMI_FLAGS",
391 "CpuAVX512VBMI" },
392 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
393 "CpuAVX512_4FMAPS" },
394 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
395 "CpuAVX512_4VNNIW" },
396 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
397 "CpuAVX512_VPOPCNTDQ" },
398 { "CPU_ANY_IBT_FLAGS",
399 "CpuIBT" },
400 { "CPU_ANY_SHSTK_FLAGS",
401 "CpuSHSTK" },
402 { "CPU_ANY_AVX512_VBMI2_FLAGS",
403 "CpuAVX512_VBMI2" },
404 { "CPU_ANY_AVX512_VNNI_FLAGS",
405 "CpuAVX512_VNNI" },
406 { "CPU_ANY_AVX512_BITALG_FLAGS",
407 "CpuAVX512_BITALG" },
408 { "CPU_ANY_AVX512_BF16_FLAGS",
409 "CpuAVX512_BF16" },
410 { "CPU_ANY_AMX_INT8_FLAGS",
411 "CpuAMX_INT8" },
412 { "CPU_ANY_AMX_BF16_FLAGS",
413 "CpuAMX_BF16" },
414 { "CPU_ANY_AMX_TILE_FLAGS",
415 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
416 { "CPU_ANY_AVX_VNNI_FLAGS",
417 "CpuAVX_VNNI" },
418 { "CPU_ANY_MOVDIRI_FLAGS",
419 "CpuMOVDIRI" },
420 { "CPU_ANY_UINTR_FLAGS",
421 "CpuUINTR" },
422 { "CPU_ANY_MOVDIR64B_FLAGS",
423 "CpuMOVDIR64B" },
424 { "CPU_ANY_ENQCMD_FLAGS",
425 "CpuENQCMD" },
426 { "CPU_ANY_SERIALIZE_FLAGS",
427 "CpuSERIALIZE" },
428 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
429 "CpuAVX512_VP2INTERSECT" },
430 { "CPU_ANY_TDX_FLAGS",
431 "CpuTDX" },
432 { "CPU_ANY_TSXLDTRK_FLAGS",
433 "CpuTSXLDTRK" },
434 { "CPU_ANY_KL_FLAGS",
435 "CpuKL|CpuWideKL" },
436 { "CPU_ANY_WIDEKL_FLAGS",
437 "CpuWideKL" },
438 { "CPU_ANY_HRESET_FLAGS",
439 "CpuHRESET" },
440 { "CPU_ANY_AVX512_FP16_FLAGS",
441 "CpuAVX512_FP16" },
442 };
443
444 static initializer operand_type_init[] =
445 {
446 { "OPERAND_TYPE_NONE",
447 "0" },
448 { "OPERAND_TYPE_REG8",
449 "Class=Reg|Byte" },
450 { "OPERAND_TYPE_REG16",
451 "Class=Reg|Word" },
452 { "OPERAND_TYPE_REG32",
453 "Class=Reg|Dword" },
454 { "OPERAND_TYPE_REG64",
455 "Class=Reg|Qword" },
456 { "OPERAND_TYPE_IMM1",
457 "Imm1" },
458 { "OPERAND_TYPE_IMM8",
459 "Imm8" },
460 { "OPERAND_TYPE_IMM8S",
461 "Imm8S" },
462 { "OPERAND_TYPE_IMM16",
463 "Imm16" },
464 { "OPERAND_TYPE_IMM32",
465 "Imm32" },
466 { "OPERAND_TYPE_IMM32S",
467 "Imm32S" },
468 { "OPERAND_TYPE_IMM64",
469 "Imm64" },
470 { "OPERAND_TYPE_BASEINDEX",
471 "BaseIndex" },
472 { "OPERAND_TYPE_DISP8",
473 "Disp8" },
474 { "OPERAND_TYPE_DISP16",
475 "Disp16" },
476 { "OPERAND_TYPE_DISP32",
477 "Disp32" },
478 { "OPERAND_TYPE_DISP64",
479 "Disp64" },
480 { "OPERAND_TYPE_INOUTPORTREG",
481 "Instance=RegD|Word" },
482 { "OPERAND_TYPE_SHIFTCOUNT",
483 "Instance=RegC|Byte" },
484 { "OPERAND_TYPE_CONTROL",
485 "Class=RegCR" },
486 { "OPERAND_TYPE_TEST",
487 "Class=RegTR" },
488 { "OPERAND_TYPE_DEBUG",
489 "Class=RegDR" },
490 { "OPERAND_TYPE_FLOATREG",
491 "Class=Reg|Tbyte" },
492 { "OPERAND_TYPE_FLOATACC",
493 "Instance=Accum|Tbyte" },
494 { "OPERAND_TYPE_SREG",
495 "Class=SReg" },
496 { "OPERAND_TYPE_REGMMX",
497 "Class=RegMMX" },
498 { "OPERAND_TYPE_REGXMM",
499 "Class=RegSIMD|Xmmword" },
500 { "OPERAND_TYPE_REGYMM",
501 "Class=RegSIMD|Ymmword" },
502 { "OPERAND_TYPE_REGZMM",
503 "Class=RegSIMD|Zmmword" },
504 { "OPERAND_TYPE_REGTMM",
505 "Class=RegSIMD|Tmmword" },
506 { "OPERAND_TYPE_REGMASK",
507 "Class=RegMask" },
508 { "OPERAND_TYPE_REGBND",
509 "Class=RegBND" },
510 { "OPERAND_TYPE_ACC8",
511 "Instance=Accum|Byte" },
512 { "OPERAND_TYPE_ACC16",
513 "Instance=Accum|Word" },
514 { "OPERAND_TYPE_ACC32",
515 "Instance=Accum|Dword" },
516 { "OPERAND_TYPE_ACC64",
517 "Instance=Accum|Qword" },
518 { "OPERAND_TYPE_DISP16_32",
519 "Disp16|Disp32" },
520 { "OPERAND_TYPE_ANYDISP",
521 "Disp8|Disp16|Disp32|Disp64" },
522 { "OPERAND_TYPE_IMM16_32",
523 "Imm16|Imm32" },
524 { "OPERAND_TYPE_IMM16_32S",
525 "Imm16|Imm32S" },
526 { "OPERAND_TYPE_IMM16_32_32S",
527 "Imm16|Imm32|Imm32S" },
528 { "OPERAND_TYPE_IMM32_64",
529 "Imm32|Imm64" },
530 { "OPERAND_TYPE_IMM32_32S_DISP32",
531 "Imm32|Imm32S|Disp32" },
532 { "OPERAND_TYPE_IMM64_DISP64",
533 "Imm64|Disp64" },
534 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
535 "Imm32|Imm32S|Imm64|Disp32" },
536 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
537 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
538 { "OPERAND_TYPE_ANYIMM",
539 "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
540 };
541
542 typedef struct bitfield
543 {
544 int position;
545 int value;
546 const char *name;
547 } bitfield;
548
549 #define BITFIELD(n) { n, 0, #n }
550
551 static bitfield cpu_flags[] =
552 {
553 BITFIELD (Cpu186),
554 BITFIELD (Cpu286),
555 BITFIELD (Cpu386),
556 BITFIELD (Cpu486),
557 BITFIELD (Cpu586),
558 BITFIELD (Cpu686),
559 BITFIELD (CpuCMOV),
560 BITFIELD (CpuFXSR),
561 BITFIELD (CpuClflush),
562 BITFIELD (CpuNop),
563 BITFIELD (CpuSYSCALL),
564 BITFIELD (Cpu8087),
565 BITFIELD (Cpu287),
566 BITFIELD (Cpu387),
567 BITFIELD (Cpu687),
568 BITFIELD (CpuFISTTP),
569 BITFIELD (CpuMMX),
570 BITFIELD (CpuSSE),
571 BITFIELD (CpuSSE2),
572 BITFIELD (CpuSSE3),
573 BITFIELD (CpuSSSE3),
574 BITFIELD (CpuSSE4_1),
575 BITFIELD (CpuSSE4_2),
576 BITFIELD (CpuAVX),
577 BITFIELD (CpuAVX2),
578 BITFIELD (CpuAVX512F),
579 BITFIELD (CpuAVX512CD),
580 BITFIELD (CpuAVX512ER),
581 BITFIELD (CpuAVX512PF),
582 BITFIELD (CpuAVX512VL),
583 BITFIELD (CpuAVX512DQ),
584 BITFIELD (CpuAVX512BW),
585 BITFIELD (CpuIAMCU),
586 BITFIELD (CpuSSE4a),
587 BITFIELD (Cpu3dnow),
588 BITFIELD (Cpu3dnowA),
589 BITFIELD (CpuPadLock),
590 BITFIELD (CpuSVME),
591 BITFIELD (CpuVMX),
592 BITFIELD (CpuSMX),
593 BITFIELD (CpuXsave),
594 BITFIELD (CpuXsaveopt),
595 BITFIELD (CpuAES),
596 BITFIELD (CpuPCLMUL),
597 BITFIELD (CpuFMA),
598 BITFIELD (CpuFMA4),
599 BITFIELD (CpuXOP),
600 BITFIELD (CpuLWP),
601 BITFIELD (CpuBMI),
602 BITFIELD (CpuTBM),
603 BITFIELD (CpuLM),
604 BITFIELD (CpuMovbe),
605 BITFIELD (CpuCX16),
606 BITFIELD (CpuEPT),
607 BITFIELD (CpuRdtscp),
608 BITFIELD (CpuFSGSBase),
609 BITFIELD (CpuRdRnd),
610 BITFIELD (CpuF16C),
611 BITFIELD (CpuBMI2),
612 BITFIELD (CpuLZCNT),
613 BITFIELD (CpuPOPCNT),
614 BITFIELD (CpuHLE),
615 BITFIELD (CpuRTM),
616 BITFIELD (CpuINVPCID),
617 BITFIELD (CpuVMFUNC),
618 BITFIELD (CpuRDSEED),
619 BITFIELD (CpuADX),
620 BITFIELD (CpuPRFCHW),
621 BITFIELD (CpuSMAP),
622 BITFIELD (CpuSHA),
623 BITFIELD (CpuClflushOpt),
624 BITFIELD (CpuXSAVES),
625 BITFIELD (CpuXSAVEC),
626 BITFIELD (CpuPREFETCHWT1),
627 BITFIELD (CpuSE1),
628 BITFIELD (CpuCLWB),
629 BITFIELD (CpuMPX),
630 BITFIELD (CpuAVX512IFMA),
631 BITFIELD (CpuAVX512VBMI),
632 BITFIELD (CpuAVX512_4FMAPS),
633 BITFIELD (CpuAVX512_4VNNIW),
634 BITFIELD (CpuAVX512_VPOPCNTDQ),
635 BITFIELD (CpuAVX512_VBMI2),
636 BITFIELD (CpuAVX512_VNNI),
637 BITFIELD (CpuAVX512_BITALG),
638 BITFIELD (CpuAVX512_BF16),
639 BITFIELD (CpuAVX512_VP2INTERSECT),
640 BITFIELD (CpuTDX),
641 BITFIELD (CpuAVX_VNNI),
642 BITFIELD (CpuAVX512_FP16),
643 BITFIELD (CpuMWAITX),
644 BITFIELD (CpuCLZERO),
645 BITFIELD (CpuOSPKE),
646 BITFIELD (CpuRDPID),
647 BITFIELD (CpuPTWRITE),
648 BITFIELD (CpuIBT),
649 BITFIELD (CpuSHSTK),
650 BITFIELD (CpuGFNI),
651 BITFIELD (CpuVAES),
652 BITFIELD (CpuVPCLMULQDQ),
653 BITFIELD (CpuWBNOINVD),
654 BITFIELD (CpuPCONFIG),
655 BITFIELD (CpuWAITPKG),
656 BITFIELD (CpuUINTR),
657 BITFIELD (CpuCLDEMOTE),
658 BITFIELD (CpuAMX_INT8),
659 BITFIELD (CpuAMX_BF16),
660 BITFIELD (CpuAMX_TILE),
661 BITFIELD (CpuMOVDIRI),
662 BITFIELD (CpuMOVDIR64B),
663 BITFIELD (CpuENQCMD),
664 BITFIELD (CpuSERIALIZE),
665 BITFIELD (CpuRDPRU),
666 BITFIELD (CpuMCOMMIT),
667 BITFIELD (CpuSEV_ES),
668 BITFIELD (CpuTSXLDTRK),
669 BITFIELD (CpuKL),
670 BITFIELD (CpuWideKL),
671 BITFIELD (CpuHRESET),
672 BITFIELD (CpuINVLPGB),
673 BITFIELD (CpuTLBSYNC),
674 BITFIELD (CpuSNP),
675 BITFIELD (Cpu64),
676 BITFIELD (CpuNo64),
677 #ifdef CpuUnused
678 BITFIELD (CpuUnused),
679 #endif
680 };
681
682 static bitfield opcode_modifiers[] =
683 {
684 BITFIELD (D),
685 BITFIELD (W),
686 BITFIELD (Load),
687 BITFIELD (Modrm),
688 BITFIELD (Jump),
689 BITFIELD (FloatMF),
690 BITFIELD (FloatR),
691 BITFIELD (Size),
692 BITFIELD (CheckRegSize),
693 BITFIELD (DistinctDest),
694 BITFIELD (MnemonicSize),
695 BITFIELD (Anysize),
696 BITFIELD (No_bSuf),
697 BITFIELD (No_wSuf),
698 BITFIELD (No_lSuf),
699 BITFIELD (No_sSuf),
700 BITFIELD (No_qSuf),
701 BITFIELD (No_ldSuf),
702 BITFIELD (FWait),
703 BITFIELD (IsString),
704 BITFIELD (RegMem),
705 BITFIELD (BNDPrefixOk),
706 BITFIELD (RegKludge),
707 BITFIELD (Implicit1stXmm0),
708 BITFIELD (PrefixOk),
709 BITFIELD (AddrPrefixOpReg),
710 BITFIELD (IsPrefix),
711 BITFIELD (ImmExt),
712 BITFIELD (NoRex64),
713 BITFIELD (Ugh),
714 BITFIELD (PseudoVexPrefix),
715 BITFIELD (Vex),
716 BITFIELD (VexVVVV),
717 BITFIELD (VexW),
718 BITFIELD (OpcodeSpace),
719 BITFIELD (OpcodePrefix),
720 BITFIELD (VexSources),
721 BITFIELD (SIB),
722 BITFIELD (SSE2AVX),
723 BITFIELD (EVex),
724 BITFIELD (Masking),
725 BITFIELD (Broadcast),
726 BITFIELD (StaticRounding),
727 BITFIELD (SAE),
728 BITFIELD (Disp8MemShift),
729 BITFIELD (NoDefMask),
730 BITFIELD (ImplicitQuadGroup),
731 BITFIELD (SwapSources),
732 BITFIELD (Optimize),
733 BITFIELD (ATTMnemonic),
734 BITFIELD (ATTSyntax),
735 BITFIELD (IntelSyntax),
736 BITFIELD (ISA64),
737 };
738
739 #define CLASS(n) #n, n
740
741 static const struct {
742 const char *name;
743 enum operand_class value;
744 } operand_classes[] = {
745 CLASS (Reg),
746 CLASS (SReg),
747 CLASS (RegCR),
748 CLASS (RegDR),
749 CLASS (RegTR),
750 CLASS (RegMMX),
751 CLASS (RegSIMD),
752 CLASS (RegMask),
753 CLASS (RegBND),
754 };
755
756 #undef CLASS
757
758 #define INSTANCE(n) #n, n
759
760 static const struct {
761 const char *name;
762 enum operand_instance value;
763 } operand_instances[] = {
764 INSTANCE (Accum),
765 INSTANCE (RegC),
766 INSTANCE (RegD),
767 INSTANCE (RegB),
768 };
769
770 #undef INSTANCE
771
772 static bitfield operand_types[] =
773 {
774 BITFIELD (Imm1),
775 BITFIELD (Imm8),
776 BITFIELD (Imm8S),
777 BITFIELD (Imm16),
778 BITFIELD (Imm32),
779 BITFIELD (Imm32S),
780 BITFIELD (Imm64),
781 BITFIELD (BaseIndex),
782 BITFIELD (Disp8),
783 BITFIELD (Disp16),
784 BITFIELD (Disp32),
785 BITFIELD (Disp64),
786 BITFIELD (Byte),
787 BITFIELD (Word),
788 BITFIELD (Dword),
789 BITFIELD (Fword),
790 BITFIELD (Qword),
791 BITFIELD (Tbyte),
792 BITFIELD (Xmmword),
793 BITFIELD (Ymmword),
794 BITFIELD (Zmmword),
795 BITFIELD (Tmmword),
796 BITFIELD (Unspecified),
797 #ifdef OTUnused
798 BITFIELD (OTUnused),
799 #endif
800 };
801
802 static const char *filename;
803 static i386_cpu_flags active_cpu_flags;
804 static int active_isstring;
805
806 struct template_arg {
807 const struct template_arg *next;
808 const char *val;
809 };
810
811 struct template_instance {
812 const struct template_instance *next;
813 const char *name;
814 const struct template_arg *args;
815 };
816
817 struct template_param {
818 const struct template_param *next;
819 const char *name;
820 };
821
822 struct template {
823 struct template *next;
824 const char *name;
825 const struct template_instance *instances;
826 const struct template_param *params;
827 };
828
829 static struct template *templates;
830
831 static int
832 compare (const void *x, const void *y)
833 {
834 const bitfield *xp = (const bitfield *) x;
835 const bitfield *yp = (const bitfield *) y;
836 return xp->position - yp->position;
837 }
838
839 static void
840 fail (const char *message, ...)
841 {
842 va_list args;
843
844 va_start (args, message);
845 fprintf (stderr, _("%s: error: "), program_name);
846 vfprintf (stderr, message, args);
847 va_end (args);
848 xexit (1);
849 }
850
851 static void
852 process_copyright (FILE *fp)
853 {
854 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
855 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
856 \n\
857 This file is part of the GNU opcodes library.\n\
858 \n\
859 This library is free software; you can redistribute it and/or modify\n\
860 it under the terms of the GNU General Public License as published by\n\
861 the Free Software Foundation; either version 3, or (at your option)\n\
862 any later version.\n\
863 \n\
864 It is distributed in the hope that it will be useful, but WITHOUT\n\
865 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
866 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
867 License for more details.\n\
868 \n\
869 You should have received a copy of the GNU General Public License\n\
870 along with this program; if not, write to the Free Software\n\
871 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
872 MA 02110-1301, USA. */\n");
873 }
874
875 /* Remove leading white spaces. */
876
877 static char *
878 remove_leading_whitespaces (char *str)
879 {
880 while (ISSPACE (*str))
881 str++;
882 return str;
883 }
884
885 /* Remove trailing white spaces. */
886
887 static void
888 remove_trailing_whitespaces (char *str)
889 {
890 size_t last = strlen (str);
891
892 if (last == 0)
893 return;
894
895 do
896 {
897 last--;
898 if (ISSPACE (str [last]))
899 str[last] = '\0';
900 else
901 break;
902 }
903 while (last != 0);
904 }
905
906 /* Find next field separated by SEP and terminate it. Return a
907 pointer to the one after it. */
908
909 static char *
910 next_field (char *str, char sep, char **next, char *last)
911 {
912 char *p;
913
914 p = remove_leading_whitespaces (str);
915 for (str = p; *str != sep && *str != '\0'; str++);
916
917 *str = '\0';
918 remove_trailing_whitespaces (p);
919
920 *next = str + 1;
921
922 if (p >= last)
923 abort ();
924
925 return p;
926 }
927
928 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
929
930 static int
931 set_bitfield_from_cpu_flag_init (char *f, bitfield *array, unsigned int size,
932 int lineno)
933 {
934 char *str, *next, *last;
935 unsigned int i;
936
937 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
938 if (strcmp (cpu_flag_init[i].name, f) == 0)
939 {
940 /* Turn on selective bits. */
941 char *init = xstrdup (cpu_flag_init[i].init);
942 last = init + strlen (init);
943 for (next = init; next && next < last; )
944 {
945 str = next_field (next, '|', &next, last);
946 if (str)
947 set_bitfield (str, array, 1, size, lineno);
948 }
949 free (init);
950 return 0;
951 }
952
953 return -1;
954 }
955
956 static void
957 set_bitfield (char *f, bitfield *array, int value,
958 unsigned int size, int lineno)
959 {
960 unsigned int i;
961
962 /* Ignore empty fields; they may result from template expansions. */
963 if (*f == '\0')
964 return;
965
966 for (i = 0; i < size; i++)
967 if (strcasecmp (array[i].name, f) == 0)
968 {
969 array[i].value = value;
970 return;
971 }
972
973 if (value)
974 {
975 const char *v = strchr (f, '=');
976
977 if (v)
978 {
979 size_t n = v - f;
980 char *end;
981
982 for (i = 0; i < size; i++)
983 if (strncasecmp (array[i].name, f, n) == 0)
984 {
985 value = strtol (v + 1, &end, 0);
986 if (*end == '\0')
987 {
988 array[i].value = value;
989 return;
990 }
991 break;
992 }
993 }
994 }
995
996 /* Handle CPU_XXX_FLAGS. */
997 if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
998 return;
999
1000 if (lineno != -1)
1001 fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
1002 else
1003 fail (_("unknown bitfield: %s\n"), f);
1004 }
1005
1006 static void
1007 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
1008 int macro, const char *comma, const char *indent)
1009 {
1010 unsigned int i;
1011
1012 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
1013
1014 fprintf (table, "%s{ { ", indent);
1015
1016 for (i = 0; i < size - 1; i++)
1017 {
1018 if (((i + 1) % 20) != 0)
1019 fprintf (table, "%d, ", flags[i].value);
1020 else
1021 fprintf (table, "%d,", flags[i].value);
1022 if (((i + 1) % 20) == 0)
1023 {
1024 /* We need \\ for macro. */
1025 if (macro)
1026 fprintf (table, " \\\n %s", indent);
1027 else
1028 fprintf (table, "\n %s", indent);
1029 }
1030 if (flags[i].value)
1031 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
1032 }
1033
1034 fprintf (table, "%d } }%s\n", flags[i].value, comma);
1035 }
1036
1037 static void
1038 process_i386_cpu_flag (FILE *table, char *flag, int macro,
1039 const char *comma, const char *indent,
1040 int lineno)
1041 {
1042 char *str, *next = flag, *last;
1043 unsigned int i;
1044 int value = 1;
1045 bitfield flags [ARRAY_SIZE (cpu_flags)];
1046
1047 /* Copy the default cpu flags. */
1048 memcpy (flags, cpu_flags, sizeof (cpu_flags));
1049
1050 if (flag[0] == '~')
1051 {
1052 last = flag + strlen (flag);
1053
1054 if (flag[1] == '(')
1055 {
1056 last -= 1;
1057 next = flag + 2;
1058 if (*last != ')')
1059 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
1060 lineno, flag);
1061 *last = '\0';
1062 }
1063 else
1064 next = flag + 1;
1065
1066 /* First we turn on everything except for cpu64, cpuno64, and - if
1067 present - the padding field. */
1068 for (i = 0; i < ARRAY_SIZE (flags); i++)
1069 if (flags[i].position < Cpu64)
1070 flags[i].value = 1;
1071
1072 /* Turn off selective bits. */
1073 value = 0;
1074 }
1075
1076 if (strcmp (flag, "0"))
1077 {
1078 /* Turn on/off selective bits. */
1079 last = flag + strlen (flag);
1080 for (; next && next < last; )
1081 {
1082 str = next_field (next, '|', &next, last);
1083 if (str)
1084 set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
1085 }
1086 }
1087
1088 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
1089 comma, indent);
1090 }
1091
1092 static void
1093 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1094 {
1095 unsigned int i;
1096
1097 fprintf (table, " { ");
1098
1099 for (i = 0; i < size - 1; i++)
1100 {
1101 if (((i + 1) % 20) != 0)
1102 fprintf (table, "%d, ", modifier[i].value);
1103 else
1104 fprintf (table, "%d,", modifier[i].value);
1105 if (((i + 1) % 20) == 0)
1106 fprintf (table, "\n ");
1107 }
1108
1109 fprintf (table, "%d },\n", modifier[i].value);
1110 }
1111
1112 /* Returns LOG2 of element size. */
1113 static int
1114 get_element_size (char **opnd, int lineno)
1115 {
1116 char *str, *next, *last, *op;
1117 const char *full = opnd[0];
1118 int elem_size = INT_MAX;
1119
1120 /* Find the memory operand. */
1121 while (full != NULL && strstr(full, "BaseIndex") == NULL)
1122 full = *++opnd;
1123 if (full == NULL)
1124 fail (_("%s: %d: no memory operand\n"), filename, lineno);
1125
1126 op = xstrdup (full);
1127 last = op + strlen (op);
1128 for (next = op; next && next < last; )
1129 {
1130 str = next_field (next, '|', &next, last);
1131 if (str)
1132 {
1133 if (strcasecmp(str, "Byte") == 0)
1134 {
1135 /* The smallest element size, no need to check
1136 further. */
1137 elem_size = 0;
1138 break;
1139 }
1140 else if (strcasecmp(str, "Word") == 0)
1141 {
1142 if (elem_size > 1)
1143 elem_size = 1;
1144 }
1145 else if (strcasecmp(str, "Dword") == 0)
1146 {
1147 if (elem_size > 2)
1148 elem_size = 2;
1149 }
1150 else if (strcasecmp(str, "Qword") == 0)
1151 {
1152 if (elem_size > 3)
1153 elem_size = 3;
1154 }
1155 }
1156 }
1157 free (op);
1158
1159 if (elem_size == INT_MAX)
1160 fail (_("%s: %d: unknown element size: %s\n"), filename, lineno, full);
1161
1162 return elem_size;
1163 }
1164
1165 static void
1166 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1167 unsigned int prefix, char **opnd, int lineno)
1168 {
1169 char *str, *next, *last;
1170 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1171
1172 active_isstring = 0;
1173
1174 /* Copy the default opcode modifier. */
1175 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1176
1177 if (strcmp (mod, "0"))
1178 {
1179 unsigned int have_w = 0, bwlq_suf = 0xf;
1180
1181 last = mod + strlen (mod);
1182 for (next = mod; next && next < last; )
1183 {
1184 str = next_field (next, '|', &next, last);
1185 if (str)
1186 {
1187 int val = 1;
1188 if (strcasecmp(str, "Broadcast") == 0)
1189 val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1190 else if (strcasecmp(str, "Disp8MemShift") == 0)
1191 val = get_element_size (opnd, lineno);
1192
1193 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1194 lineno);
1195 if (strcasecmp(str, "IsString") == 0)
1196 active_isstring = 1;
1197
1198 if (strcasecmp(str, "W") == 0)
1199 have_w = 1;
1200
1201 if (strcasecmp(str, "No_bSuf") == 0)
1202 bwlq_suf &= ~1;
1203 if (strcasecmp(str, "No_wSuf") == 0)
1204 bwlq_suf &= ~2;
1205 if (strcasecmp(str, "No_lSuf") == 0)
1206 bwlq_suf &= ~4;
1207 if (strcasecmp(str, "No_qSuf") == 0)
1208 bwlq_suf &= ~8;
1209 }
1210 }
1211
1212 if (space)
1213 {
1214 if (!modifiers[OpcodeSpace].value)
1215 modifiers[OpcodeSpace].value = space;
1216 else if (modifiers[OpcodeSpace].value != space)
1217 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1218 filename, lineno);
1219 else
1220 fprintf (stderr,
1221 _("%s:%d: Warning: redundant opcode space specification\n"),
1222 filename, lineno);
1223 }
1224
1225 if (prefix)
1226 {
1227 if (!modifiers[OpcodePrefix].value)
1228 modifiers[OpcodePrefix].value = prefix;
1229 else if (modifiers[OpcodePrefix].value != prefix)
1230 fail (_("%s:%d: Conflicting prefix specifications\n"),
1231 filename, lineno);
1232 else
1233 fprintf (stderr,
1234 _("%s:%d: Warning: redundant prefix specification\n"),
1235 filename, lineno);
1236 }
1237
1238 if (have_w && !bwlq_suf)
1239 fail ("%s: %d: stray W modifier\n", filename, lineno);
1240 if (have_w && !(bwlq_suf & 1))
1241 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1242 filename, lineno);
1243 if (have_w && !(bwlq_suf & ~1))
1244 fprintf (stderr,
1245 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1246 filename, lineno);
1247 }
1248 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1249 }
1250
1251 enum stage {
1252 stage_macros,
1253 stage_opcodes,
1254 stage_registers,
1255 };
1256
1257 static void
1258 output_operand_type (FILE *table, enum operand_class class,
1259 enum operand_instance instance,
1260 const bitfield *types, unsigned int size,
1261 enum stage stage, const char *indent)
1262 {
1263 unsigned int i;
1264
1265 fprintf (table, "{ { %d, %d, ", class, instance);
1266
1267 for (i = 0; i < size - 1; i++)
1268 {
1269 if (((i + 3) % 20) != 0)
1270 fprintf (table, "%d, ", types[i].value);
1271 else
1272 fprintf (table, "%d,", types[i].value);
1273 if (((i + 3) % 20) == 0)
1274 {
1275 /* We need \\ for macro. */
1276 if (stage == stage_macros)
1277 fprintf (table, " \\\n%s", indent);
1278 else
1279 fprintf (table, "\n%s", indent);
1280 }
1281 }
1282
1283 fprintf (table, "%d } }", types[i].value);
1284 }
1285
1286 static void
1287 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1288 const char *indent, int lineno)
1289 {
1290 char *str, *next, *last;
1291 enum operand_class class = ClassNone;
1292 enum operand_instance instance = InstanceNone;
1293 bitfield types [ARRAY_SIZE (operand_types)];
1294
1295 /* Copy the default operand type. */
1296 memcpy (types, operand_types, sizeof (types));
1297
1298 if (strcmp (op, "0"))
1299 {
1300 int baseindex = 0;
1301
1302 last = op + strlen (op);
1303 for (next = op; next && next < last; )
1304 {
1305 str = next_field (next, '|', &next, last);
1306 if (str)
1307 {
1308 unsigned int i;
1309
1310 if (!strncmp(str, "Class=", 6))
1311 {
1312 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1313 if (!strcmp(str + 6, operand_classes[i].name))
1314 {
1315 class = operand_classes[i].value;
1316 str = NULL;
1317 break;
1318 }
1319 }
1320
1321 if (str && !strncmp(str, "Instance=", 9))
1322 {
1323 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1324 if (!strcmp(str + 9, operand_instances[i].name))
1325 {
1326 instance = operand_instances[i].value;
1327 str = NULL;
1328 break;
1329 }
1330 }
1331 }
1332 if (str)
1333 {
1334 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1335 if (strcasecmp(str, "BaseIndex") == 0)
1336 baseindex = 1;
1337 }
1338 }
1339
1340 if (stage == stage_opcodes && baseindex && !active_isstring)
1341 {
1342 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1343 if (!active_cpu_flags.bitfield.cpu64
1344 && !active_cpu_flags.bitfield.cpumpx)
1345 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1346 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1347 }
1348 }
1349 output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1350 stage, indent);
1351 }
1352
1353 static void
1354 output_i386_opcode (FILE *table, const char *name, char *str,
1355 char *last, int lineno)
1356 {
1357 unsigned int i, length, prefix = 0, space = 0;
1358 char *base_opcode, *extension_opcode, *end;
1359 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1360 unsigned long long opcode;
1361
1362 /* Find base_opcode. */
1363 base_opcode = next_field (str, ',', &str, last);
1364
1365 /* Find extension_opcode. */
1366 extension_opcode = next_field (str, ',', &str, last);
1367
1368 /* Find cpu_flags. */
1369 cpu_flags = next_field (str, ',', &str, last);
1370
1371 /* Find opcode_modifier. */
1372 opcode_modifier = next_field (str, ',', &str, last);
1373
1374 /* Remove the first {. */
1375 str = remove_leading_whitespaces (str);
1376 if (*str != '{')
1377 abort ();
1378 str = remove_leading_whitespaces (str + 1);
1379 remove_trailing_whitespaces (str);
1380
1381 /* Remove } and trailing white space. */
1382 i = strlen (str);
1383 if (!i || str[i - 1] != '}')
1384 abort ();
1385 str[--i] = '\0';
1386 remove_trailing_whitespaces (str);
1387
1388 if (!*str)
1389 operand_types [i = 0] = NULL;
1390 else
1391 {
1392 last = str + strlen (str);
1393
1394 /* Find operand_types. */
1395 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1396 {
1397 if (str >= last)
1398 {
1399 operand_types [i] = NULL;
1400 break;
1401 }
1402
1403 operand_types [i] = next_field (str, ',', &str, last);
1404 }
1405 }
1406
1407 opcode = strtoull (base_opcode, &end, 0);
1408
1409 /* Determine opcode length. */
1410 for (length = 1; length < 8; ++length)
1411 if (!(opcode >> (8 * length)))
1412 break;
1413
1414 /* Transform prefixes encoded in the opcode into opcode modifier
1415 representation. */
1416 if (length > 1)
1417 {
1418 switch (opcode >> (8 * length - 8))
1419 {
1420 case 0x66: prefix = PREFIX_0X66; break;
1421 case 0xF3: prefix = PREFIX_0XF3; break;
1422 case 0xF2: prefix = PREFIX_0XF2; break;
1423 }
1424
1425 if (prefix)
1426 opcode &= (1ULL << (8 * --length)) - 1;
1427 }
1428
1429 /* Transform opcode space encoded in the opcode into opcode modifier
1430 representation. */
1431 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1432 {
1433 switch ((opcode >> (8 * length - 16)) & 0xff)
1434 {
1435 default: space = SPACE_0F; break;
1436 case 0x38: space = SPACE_0F38; break;
1437 case 0x3A: space = SPACE_0F3A; break;
1438 }
1439
1440 if (space != SPACE_0F && --length == 1)
1441 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1442 filename, lineno, name);
1443 opcode &= (1ULL << (8 * --length)) - 1;
1444 }
1445
1446 if (length > 2)
1447 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1448 filename, lineno, name, 2 * length, opcode);
1449
1450 fprintf (table, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1451 name, 2 * (int)length, opcode, end, i, extension_opcode);
1452
1453 process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1454 operand_types, lineno);
1455
1456 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1457
1458 fprintf (table, " { ");
1459
1460 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1461 {
1462 if (!operand_types[i])
1463 {
1464 if (i == 0)
1465 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1466 lineno);
1467 break;
1468 }
1469
1470 if (i != 0)
1471 fprintf (table, ",\n ");
1472
1473 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1474 "\t ", lineno);
1475 }
1476 fprintf (table, " } },\n");
1477 }
1478
1479 struct opcode_hash_entry
1480 {
1481 struct opcode_hash_entry *next;
1482 char *name;
1483 char *opcode;
1484 int lineno;
1485 };
1486
1487 /* Calculate the hash value of an opcode hash entry P. */
1488
1489 static hashval_t
1490 opcode_hash_hash (const void *p)
1491 {
1492 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1493 return htab_hash_string (entry->name);
1494 }
1495
1496 /* Compare a string Q against an opcode hash entry P. */
1497
1498 static int
1499 opcode_hash_eq (const void *p, const void *q)
1500 {
1501 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1502 const char *name = (const char *) q;
1503 return strcmp (name, entry->name) == 0;
1504 }
1505
1506 static void
1507 parse_template (char *buf, int lineno)
1508 {
1509 char sep, *end, *name;
1510 struct template *tmpl;
1511 struct template_instance *last_inst = NULL;
1512
1513 buf = remove_leading_whitespaces (buf + 1);
1514 end = strchr (buf, ':');
1515 if (end == NULL)
1516 {
1517 struct template *prev = NULL;
1518
1519 end = strchr (buf, '>');
1520 if (end == NULL)
1521 fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1522 if (*remove_leading_whitespaces (end + 1))
1523 fail ("%s: %d: malformed template purge\n", filename, lineno);
1524 *end = '\0';
1525 remove_trailing_whitespaces (buf);
1526 /* Don't bother freeing the various structures. */
1527 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1528 if (!strcmp (buf, tmpl->name))
1529 break;
1530 if (tmpl == NULL)
1531 fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1532 if (prev)
1533 prev->next = tmpl->next;
1534 else
1535 templates = tmpl->next;
1536 return;
1537 }
1538 *end++ = '\0';
1539 remove_trailing_whitespaces (buf);
1540
1541 if (*buf == '\0')
1542 fail ("%s: %d: missing template identifier\n", filename, lineno);
1543 tmpl = xmalloc (sizeof (*tmpl));
1544 tmpl->name = xstrdup (buf);
1545
1546 tmpl->params = NULL;
1547 do {
1548 struct template_param *param;
1549
1550 buf = remove_leading_whitespaces (end);
1551 end = strpbrk (buf, ":,");
1552 if (end == NULL)
1553 fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1554
1555 sep = *end;
1556 *end++ = '\0';
1557 remove_trailing_whitespaces (buf);
1558
1559 param = xmalloc (sizeof (*param));
1560 param->name = xstrdup (buf);
1561 param->next = tmpl->params;
1562 tmpl->params = param;
1563 } while (sep == ':');
1564
1565 tmpl->instances = NULL;
1566 do {
1567 struct template_instance *inst;
1568 char *cur, *next;
1569 const struct template_param *param;
1570
1571 buf = remove_leading_whitespaces (end);
1572 end = strpbrk (buf, ",>");
1573 if (end == NULL)
1574 fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1575
1576 sep = *end;
1577 *end++ = '\0';
1578
1579 inst = xmalloc (sizeof (*inst));
1580 inst->next = NULL;
1581 inst->args = NULL;
1582
1583 cur = next_field (buf, ':', &next, end);
1584 inst->name = *cur != '$' ? xstrdup (cur) : "";
1585
1586 for (param = tmpl->params; param; param = param->next)
1587 {
1588 struct template_arg *arg = xmalloc (sizeof (*arg));
1589
1590 cur = next_field (next, ':', &next, end);
1591 if (next > end)
1592 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1593 arg->val = xstrdup (cur);
1594 arg->next = inst->args;
1595 inst->args = arg;
1596 }
1597
1598 if (tmpl->instances)
1599 last_inst->next = inst;
1600 else
1601 tmpl->instances = inst;
1602 last_inst = inst;
1603 } while (sep == ',');
1604
1605 buf = remove_leading_whitespaces (end);
1606 if (*buf)
1607 fprintf(stderr, "%s: %d: excess characters '%s'\n",
1608 filename, lineno, buf);
1609
1610 tmpl->next = templates;
1611 templates = tmpl;
1612 }
1613
1614 static unsigned int
1615 expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1616 struct opcode_hash_entry ***opcode_array_p, int lineno)
1617 {
1618 static unsigned int idx, opcode_array_size;
1619 struct opcode_hash_entry **opcode_array = *opcode_array_p;
1620 struct opcode_hash_entry **hash_slot, **entry;
1621 char *ptr1 = strchr(name, '<'), *ptr2;
1622
1623 if (ptr1 == NULL)
1624 {
1625 /* Get the slot in hash table. */
1626 hash_slot = (struct opcode_hash_entry **)
1627 htab_find_slot_with_hash (opcode_hash_table, name,
1628 htab_hash_string (name),
1629 INSERT);
1630
1631 if (*hash_slot == NULL)
1632 {
1633 /* It is the new one. Put it on opcode array. */
1634 if (idx >= opcode_array_size)
1635 {
1636 /* Grow the opcode array when needed. */
1637 opcode_array_size += 1024;
1638 opcode_array = (struct opcode_hash_entry **)
1639 xrealloc (opcode_array,
1640 sizeof (*opcode_array) * opcode_array_size);
1641 *opcode_array_p = opcode_array;
1642 }
1643
1644 opcode_array[idx] = (struct opcode_hash_entry *)
1645 xmalloc (sizeof (struct opcode_hash_entry));
1646 opcode_array[idx]->next = NULL;
1647 opcode_array[idx]->name = xstrdup (name);
1648 opcode_array[idx]->opcode = xstrdup (str);
1649 opcode_array[idx]->lineno = lineno;
1650 *hash_slot = opcode_array[idx];
1651 idx++;
1652 }
1653 else
1654 {
1655 /* Append it to the existing one. */
1656 entry = hash_slot;
1657 while ((*entry) != NULL)
1658 entry = &(*entry)->next;
1659 *entry = (struct opcode_hash_entry *)
1660 xmalloc (sizeof (struct opcode_hash_entry));
1661 (*entry)->next = NULL;
1662 (*entry)->name = (*hash_slot)->name;
1663 (*entry)->opcode = xstrdup (str);
1664 (*entry)->lineno = lineno;
1665 }
1666 }
1667 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1668 fail ("%s: %d: missing '>'\n", filename, lineno);
1669 else
1670 {
1671 const struct template *tmpl;
1672 const struct template_instance *inst;
1673
1674 *ptr1 = '\0';
1675 ptr1 = remove_leading_whitespaces (ptr1 + 1);
1676 remove_trailing_whitespaces (ptr1);
1677
1678 *ptr2++ = '\0';
1679
1680 for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1681 if (!strcmp(ptr1, tmpl->name))
1682 break;
1683 if (!tmpl)
1684 fail ("reference to unknown template '%s'\n", ptr1);
1685
1686 for (inst = tmpl->instances; inst; inst = inst->next)
1687 {
1688 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1689 char *str2 = xmalloc(2 * strlen(str));
1690 const char *src;
1691
1692 strcpy (name2, name);
1693 strcat (name2, inst->name);
1694 strcat (name2, ptr2);
1695
1696 for (ptr1 = str2, src = str; *src; )
1697 {
1698 const char *ident = tmpl->name, *end;
1699 const struct template_param *param;
1700 const struct template_arg *arg;
1701
1702 if ((*ptr1 = *src++) != '<')
1703 {
1704 ++ptr1;
1705 continue;
1706 }
1707 while (ISSPACE(*src))
1708 ++src;
1709 while (*ident && *src == *ident)
1710 ++src, ++ident;
1711 while (ISSPACE(*src))
1712 ++src;
1713 if (*src != ':' || *ident != '\0')
1714 {
1715 memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1716 ptr1 += ident - tmpl->name;
1717 continue;
1718 }
1719 while (ISSPACE(*++src))
1720 ;
1721
1722 end = src;
1723 while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1724 ++end;
1725
1726 for (param = tmpl->params, arg = inst->args; param;
1727 param = param->next, arg = arg->next)
1728 {
1729 if (end - src == strlen (param->name)
1730 && !memcmp (src, param->name, end - src))
1731 {
1732 src = end;
1733 break;
1734 }
1735 }
1736
1737 if (param == NULL)
1738 fail ("template '%s' has no parameter '%.*s'\n",
1739 tmpl->name, (int)(end - src), src);
1740
1741 while (ISSPACE(*src))
1742 ++src;
1743 if (*src != '>')
1744 fail ("%s: %d: missing '>'\n", filename, lineno);
1745
1746 memcpy(ptr1, arg->val, strlen(arg->val));
1747 ptr1 += strlen(arg->val);
1748 ++src;
1749 }
1750
1751 *ptr1 = '\0';
1752
1753 expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1754 lineno);
1755
1756 free (str2);
1757 free (name2);
1758 }
1759 }
1760
1761 return idx;
1762 }
1763
1764 static void
1765 process_i386_opcodes (FILE *table)
1766 {
1767 FILE *fp;
1768 char buf[2048];
1769 unsigned int i, j;
1770 char *str, *p, *last, *name;
1771 htab_t opcode_hash_table;
1772 struct opcode_hash_entry **opcode_array = NULL;
1773 int lineno = 0, marker = 0;
1774
1775 filename = "i386-opc.tbl";
1776 fp = stdin;
1777
1778 i = 0;
1779 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1780 opcode_hash_eq, NULL,
1781 xcalloc, free);
1782
1783 fprintf (table, "\n/* i386 opcode table. */\n\n");
1784 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1785
1786 /* Put everything on opcode array. */
1787 while (!feof (fp))
1788 {
1789 if (fgets (buf, sizeof (buf), fp) == NULL)
1790 break;
1791
1792 p = remove_leading_whitespaces (buf);
1793
1794 for ( ; ; )
1795 {
1796 lineno++;
1797
1798 /* Skip comments. */
1799 str = strstr (p, "//");
1800 if (str != NULL)
1801 {
1802 str[0] = '\0';
1803 remove_trailing_whitespaces (p);
1804 break;
1805 }
1806
1807 /* Look for line continuation character. */
1808 remove_trailing_whitespaces (p);
1809 j = strlen (buf);
1810 if (!j || buf[j - 1] != '+')
1811 break;
1812 if (j >= sizeof (buf) - 1)
1813 fail (_("%s: %d: (continued) line too long\n"), filename, lineno);
1814
1815 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1816 {
1817 fprintf (stderr, "%s: Line continuation on last line?\n",
1818 filename);
1819 break;
1820 }
1821 }
1822
1823 switch (p[0])
1824 {
1825 case '#':
1826 if (!strcmp("### MARKER ###", buf))
1827 marker = 1;
1828 else
1829 {
1830 /* Since we ignore all included files (we only care about their
1831 #define-s here), we don't need to monitor filenames. The final
1832 line number directive is going to refer to the main source file
1833 again. */
1834 char *end;
1835 unsigned long ln;
1836
1837 p = remove_leading_whitespaces (p + 1);
1838 if (!strncmp(p, "line", 4))
1839 p += 4;
1840 ln = strtoul (p, &end, 10);
1841 if (ln > 1 && ln < INT_MAX
1842 && *remove_leading_whitespaces (end) == '"')
1843 lineno = ln - 1;
1844 }
1845 /* Ignore comments. */
1846 case '\0':
1847 continue;
1848 break;
1849 case '<':
1850 parse_template (p, lineno);
1851 continue;
1852 default:
1853 if (!marker)
1854 continue;
1855 break;
1856 }
1857
1858 last = p + strlen (p);
1859
1860 /* Find name. */
1861 name = next_field (p, ',', &str, last);
1862
1863 i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1864 lineno);
1865 }
1866
1867 /* Process opcode array. */
1868 for (j = 0; j < i; j++)
1869 {
1870 struct opcode_hash_entry *next;
1871
1872 for (next = opcode_array[j]; next; next = next->next)
1873 {
1874 name = next->name;
1875 str = next->opcode;
1876 lineno = next->lineno;
1877 last = str + strlen (str);
1878 output_i386_opcode (table, name, str, last, lineno);
1879 }
1880 }
1881
1882 fclose (fp);
1883
1884 fprintf (table, " { NULL, 0, 0, 0,\n");
1885
1886 process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
1887
1888 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1889
1890 fprintf (table, " { ");
1891 process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);
1892 fprintf (table, " } }\n");
1893
1894 fprintf (table, "};\n");
1895 }
1896
1897 static void
1898 process_i386_registers (FILE *table)
1899 {
1900 FILE *fp;
1901 char buf[2048];
1902 char *str, *p, *last;
1903 char *reg_name, *reg_type, *reg_flags, *reg_num;
1904 char *dw2_32_num, *dw2_64_num;
1905 int lineno = 0;
1906
1907 filename = "i386-reg.tbl";
1908 fp = fopen (filename, "r");
1909 if (fp == NULL)
1910 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1911 xstrerror (errno));
1912
1913 fprintf (table, "\n/* i386 register table. */\n\n");
1914 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1915
1916 while (!feof (fp))
1917 {
1918 if (fgets (buf, sizeof (buf), fp) == NULL)
1919 break;
1920
1921 lineno++;
1922
1923 p = remove_leading_whitespaces (buf);
1924
1925 /* Skip comments. */
1926 str = strstr (p, "//");
1927 if (str != NULL)
1928 str[0] = '\0';
1929
1930 /* Remove trailing white spaces. */
1931 remove_trailing_whitespaces (p);
1932
1933 switch (p[0])
1934 {
1935 case '#':
1936 fprintf (table, "%s\n", p);
1937 case '\0':
1938 continue;
1939 break;
1940 default:
1941 break;
1942 }
1943
1944 last = p + strlen (p);
1945
1946 /* Find reg_name. */
1947 reg_name = next_field (p, ',', &str, last);
1948
1949 /* Find reg_type. */
1950 reg_type = next_field (str, ',', &str, last);
1951
1952 /* Find reg_flags. */
1953 reg_flags = next_field (str, ',', &str, last);
1954
1955 /* Find reg_num. */
1956 reg_num = next_field (str, ',', &str, last);
1957
1958 fprintf (table, " { \"%s\",\n ", reg_name);
1959
1960 process_i386_operand_type (table, reg_type, stage_registers, "\t",
1961 lineno);
1962
1963 /* Find 32-bit Dwarf2 register number. */
1964 dw2_32_num = next_field (str, ',', &str, last);
1965
1966 /* Find 64-bit Dwarf2 register number. */
1967 dw2_64_num = next_field (str, ',', &str, last);
1968
1969 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
1970 reg_flags, reg_num, dw2_32_num, dw2_64_num);
1971 }
1972
1973 fclose (fp);
1974
1975 fprintf (table, "};\n");
1976
1977 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
1978 }
1979
1980 static void
1981 process_i386_initializers (void)
1982 {
1983 unsigned int i;
1984 FILE *fp = fopen ("i386-init.h", "w");
1985 char *init;
1986
1987 if (fp == NULL)
1988 fail (_("can't create i386-init.h, errno = %s\n"),
1989 xstrerror (errno));
1990
1991 process_copyright (fp);
1992
1993 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
1994 {
1995 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
1996 init = xstrdup (cpu_flag_init[i].init);
1997 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
1998 free (init);
1999 }
2000
2001 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
2002 {
2003 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
2004 init = xstrdup (operand_type_init[i].init);
2005 process_i386_operand_type (fp, init, stage_macros, " ", -1);
2006 free (init);
2007 }
2008 fprintf (fp, "\n");
2009
2010 fclose (fp);
2011 }
2012
2013 /* Program options. */
2014 #define OPTION_SRCDIR 200
2015
2016 struct option long_options[] =
2017 {
2018 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2019 {"debug", no_argument, NULL, 'd'},
2020 {"version", no_argument, NULL, 'V'},
2021 {"help", no_argument, NULL, 'h'},
2022 {0, no_argument, NULL, 0}
2023 };
2024
2025 static void
2026 print_version (void)
2027 {
2028 printf ("%s: version 1.0\n", program_name);
2029 xexit (0);
2030 }
2031
2032 static void
2033 usage (FILE * stream, int status)
2034 {
2035 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2036 program_name);
2037 xexit (status);
2038 }
2039
2040 int
2041 main (int argc, char **argv)
2042 {
2043 extern int chdir (char *);
2044 char *srcdir = NULL;
2045 int c;
2046 unsigned int i, cpumax;
2047 FILE *table;
2048
2049 program_name = *argv;
2050 xmalloc_set_program_name (program_name);
2051
2052 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2053 switch (c)
2054 {
2055 case OPTION_SRCDIR:
2056 srcdir = optarg;
2057 break;
2058 case 'V':
2059 case 'v':
2060 print_version ();
2061 break;
2062 case 'd':
2063 debug = 1;
2064 break;
2065 case 'h':
2066 case '?':
2067 usage (stderr, 0);
2068 default:
2069 case 0:
2070 break;
2071 }
2072
2073 if (optind != argc)
2074 usage (stdout, 1);
2075
2076 if (srcdir != NULL)
2077 if (chdir (srcdir) != 0)
2078 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2079 srcdir, xstrerror (errno));
2080
2081 /* cpu_flags isn't sorted by position. */
2082 cpumax = 0;
2083 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2084 if (cpu_flags[i].position > cpumax)
2085 cpumax = cpu_flags[i].position;
2086
2087 /* Check the unused bitfield in i386_cpu_flags. */
2088 #ifdef CpuUnused
2089 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2090
2091 if ((cpumax - 1) != CpuMax)
2092 fail (_("CpuMax != %d!\n"), cpumax);
2093 #else
2094 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2095
2096 if (cpumax != CpuMax)
2097 fail (_("CpuMax != %d!\n"), cpumax);
2098
2099 c = CpuNumOfBits - CpuMax - 1;
2100 if (c)
2101 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
2102 #endif
2103
2104 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2105
2106 /* Check the unused bitfield in i386_operand_type. */
2107 #ifdef OTUnused
2108 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2109 == OTNum + 1);
2110 #else
2111 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2112 == OTNum);
2113
2114 c = OTNumOfBits - OTNum;
2115 if (c)
2116 fail (_("%d unused bits in i386_operand_type.\n"), c);
2117 #endif
2118
2119 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2120 compare);
2121
2122 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2123 sizeof (opcode_modifiers [0]), compare);
2124
2125 qsort (operand_types, ARRAY_SIZE (operand_types),
2126 sizeof (operand_types [0]), compare);
2127
2128 table = fopen ("i386-tbl.h", "w");
2129 if (table == NULL)
2130 fail (_("can't create i386-tbl.h, errno = %s\n"),
2131 xstrerror (errno));
2132
2133 process_copyright (table);
2134
2135 process_i386_opcodes (table);
2136 process_i386_registers (table);
2137 process_i386_initializers ();
2138
2139 fclose (table);
2140
2141 exit (0);
2142 }