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