x86: fold special-operand insn attributes into a single enum
[binutils-gdb.git] / opcodes / i386-gen.c
blob48c15844ce3a89805b3acb50a79111ee3234d72e
1 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.
3 This file is part of the GNU opcodes library.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
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"
28 #include "i386-opc.h"
30 #include <libintl.h>
31 #define _(String) gettext (String)
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); }))
37 static const char *program_name = NULL;
38 static int debug = 0;
40 typedef struct initializer
42 const char *name;
43 const char *init;
44 } initializer;
46 static initializer cpu_flag_init[] =
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_PREFETCHI_FLAGS",
249 "CpuPREFETCHI"},
250 { "CPU_AVX_IFMA_FLAGS",
251 "CPU_AVX2_FLAGS|CpuAVX_IFMA" },
252 { "CPU_AVX_VNNI_INT8_FLAGS",
253 "CPU_AVX2_FLAGS|CpuAVX_VNNI_INT8" },
254 { "CPU_CMPCCXADD_FLAGS",
255 "CpuCMPCCXADD" },
256 { "CPU_WRMSRNS_FLAGS",
257 "CpuWRMSRNS" },
258 { "CPU_MSRLIST_FLAGS",
259 "CpuMSRLIST" },
260 { "CPU_AVX_NE_CONVERT_FLAGS",
261 "CPU_AVX2_FLAGS|CpuAVX_NE_CONVERT" },
262 { "CPU_RAO_INT_FLAGS",
263 "CpuRAO_INT" },
264 { "CPU_IAMCU_FLAGS",
265 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
266 { "CPU_ADX_FLAGS",
267 "CpuADX" },
268 { "CPU_RDSEED_FLAGS",
269 "CpuRdSeed" },
270 { "CPU_PRFCHW_FLAGS",
271 "CpuPRFCHW" },
272 { "CPU_SMAP_FLAGS",
273 "CpuSMAP" },
274 { "CPU_MPX_FLAGS",
275 "CPU_XSAVE_FLAGS|CpuMPX" },
276 { "CPU_SHA_FLAGS",
277 "CPU_SSE2_FLAGS|CpuSHA" },
278 { "CPU_CLFLUSHOPT_FLAGS",
279 "CpuClflushOpt" },
280 { "CPU_XSAVES_FLAGS",
281 "CPU_XSAVE_FLAGS|CpuXSAVES" },
282 { "CPU_XSAVEC_FLAGS",
283 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
284 { "CPU_PREFETCHWT1_FLAGS",
285 "CpuPREFETCHWT1" },
286 { "CPU_SE1_FLAGS",
287 "CpuSE1" },
288 { "CPU_CLWB_FLAGS",
289 "CpuCLWB" },
290 { "CPU_CLZERO_FLAGS",
291 "CpuCLZERO" },
292 { "CPU_MWAITX_FLAGS",
293 "CpuMWAITX" },
294 { "CPU_OSPKE_FLAGS",
295 "CPU_XSAVE_FLAGS|CpuOSPKE" },
296 { "CPU_RDPID_FLAGS",
297 "CpuRDPID" },
298 { "CPU_PTWRITE_FLAGS",
299 "CpuPTWRITE" },
300 { "CPU_IBT_FLAGS",
301 "CpuIBT" },
302 { "CPU_SHSTK_FLAGS",
303 "CpuSHSTK" },
304 { "CPU_GFNI_FLAGS",
305 "CpuGFNI" },
306 { "CPU_VAES_FLAGS",
307 "CpuVAES" },
308 { "CPU_VPCLMULQDQ_FLAGS",
309 "CpuVPCLMULQDQ" },
310 { "CPU_WBNOINVD_FLAGS",
311 "CpuWBNOINVD" },
312 { "CPU_PCONFIG_FLAGS",
313 "CpuPCONFIG" },
314 { "CPU_WAITPKG_FLAGS",
315 "CpuWAITPKG" },
316 { "CPU_UINTR_FLAGS",
317 "CpuUINTR" },
318 { "CPU_CLDEMOTE_FLAGS",
319 "CpuCLDEMOTE" },
320 { "CPU_AMX_INT8_FLAGS",
321 "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
322 { "CPU_AMX_BF16_FLAGS",
323 "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
324 { "CPU_AMX_FP16_FLAGS",
325 "CPU_AMX_TILE_FLAGS|CpuAMX_FP16" },
326 { "CPU_AMX_TILE_FLAGS",
327 "CpuAMX_TILE" },
328 { "CPU_MOVDIRI_FLAGS",
329 "CpuMOVDIRI" },
330 { "CPU_MOVDIR64B_FLAGS",
331 "CpuMOVDIR64B" },
332 { "CPU_ENQCMD_FLAGS",
333 "CpuENQCMD" },
334 { "CPU_SERIALIZE_FLAGS",
335 "CpuSERIALIZE" },
336 { "CPU_AVX512_VP2INTERSECT_FLAGS",
337 "CpuAVX512_VP2INTERSECT" },
338 { "CPU_TDX_FLAGS",
339 "CpuTDX" },
340 { "CPU_RDPRU_FLAGS",
341 "CpuRDPRU" },
342 { "CPU_MCOMMIT_FLAGS",
343 "CpuMCOMMIT" },
344 { "CPU_SEV_ES_FLAGS",
345 "CpuSEV_ES" },
346 { "CPU_TSXLDTRK_FLAGS",
347 "CpuTSXLDTRK"},
348 { "CPU_KL_FLAGS",
349 "CpuKL" },
350 { "CPU_WIDEKL_FLAGS",
351 "CpuWideKL" },
352 { "CPU_HRESET_FLAGS",
353 "CpuHRESET"},
354 { "CPU_INVLPGB_FLAGS",
355 "CpuINVLPGB" },
356 { "CPU_TLBSYNC_FLAGS",
357 "CpuTLBSYNC" },
358 { "CPU_SNP_FLAGS",
359 "CpuSNP" },
360 { "CPU_ANY_X87_FLAGS",
361 "CPU_ANY_287_FLAGS|Cpu8087" },
362 { "CPU_ANY_287_FLAGS",
363 "CPU_ANY_387_FLAGS|Cpu287" },
364 { "CPU_ANY_387_FLAGS",
365 "CPU_ANY_687_FLAGS|Cpu387" },
366 { "CPU_ANY_687_FLAGS",
367 "Cpu687|CpuFISTTP" },
368 { "CPU_ANY_CMOV_FLAGS",
369 "CpuCMOV" },
370 { "CPU_ANY_FXSR_FLAGS",
371 "CpuFXSR" },
372 { "CPU_ANY_MMX_FLAGS",
373 "CPU_3DNOWA_FLAGS" },
374 { "CPU_ANY_SSE_FLAGS",
375 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
376 { "CPU_ANY_SSE2_FLAGS",
377 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
378 { "CPU_ANY_SSE3_FLAGS",
379 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
380 { "CPU_ANY_SSSE3_FLAGS",
381 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
382 { "CPU_ANY_SSE4_1_FLAGS",
383 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
384 { "CPU_ANY_SSE4_2_FLAGS",
385 "CpuSSE4_2" },
386 { "CPU_ANY_SSE4A_FLAGS",
387 "CpuSSE4a" },
388 { "CPU_ANY_AVX_FLAGS",
389 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
390 { "CPU_ANY_AVX2_FLAGS",
391 "CPU_ANY_AVX512F_FLAGS|CpuAVX2|CpuAVX_VNNI|CpuAVX_IFMA|CpuAVX_VNNI_INT8|CpuAVX_NE_CONVERT" },
392 { "CPU_ANY_AVX512F_FLAGS",
393 "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" },
394 { "CPU_ANY_AVX512CD_FLAGS",
395 "CpuAVX512CD" },
396 { "CPU_ANY_AVX512ER_FLAGS",
397 "CpuAVX512ER" },
398 { "CPU_ANY_AVX512PF_FLAGS",
399 "CpuAVX512PF" },
400 { "CPU_ANY_AVX512DQ_FLAGS",
401 "CpuAVX512DQ" },
402 { "CPU_ANY_AVX512BW_FLAGS",
403 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
404 { "CPU_ANY_AVX512VL_FLAGS",
405 "CpuAVX512VL" },
406 { "CPU_ANY_AVX512IFMA_FLAGS",
407 "CpuAVX512IFMA" },
408 { "CPU_ANY_AVX512VBMI_FLAGS",
409 "CpuAVX512VBMI" },
410 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
411 "CpuAVX512_4FMAPS" },
412 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
413 "CpuAVX512_4VNNIW" },
414 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
415 "CpuAVX512_VPOPCNTDQ" },
416 { "CPU_ANY_IBT_FLAGS",
417 "CpuIBT" },
418 { "CPU_ANY_SHSTK_FLAGS",
419 "CpuSHSTK" },
420 { "CPU_ANY_AVX512_VBMI2_FLAGS",
421 "CpuAVX512_VBMI2" },
422 { "CPU_ANY_AVX512_VNNI_FLAGS",
423 "CpuAVX512_VNNI" },
424 { "CPU_ANY_AVX512_BITALG_FLAGS",
425 "CpuAVX512_BITALG" },
426 { "CPU_ANY_AVX512_BF16_FLAGS",
427 "CpuAVX512_BF16" },
428 { "CPU_ANY_AMX_INT8_FLAGS",
429 "CpuAMX_INT8" },
430 { "CPU_ANY_AMX_BF16_FLAGS",
431 "CpuAMX_BF16" },
432 { "CPU_ANY_AMX_TILE_FLAGS",
433 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16|CpuAMX_FP16" },
434 { "CPU_ANY_AVX_VNNI_FLAGS",
435 "CpuAVX_VNNI" },
436 { "CPU_ANY_MOVDIRI_FLAGS",
437 "CpuMOVDIRI" },
438 { "CPU_ANY_UINTR_FLAGS",
439 "CpuUINTR" },
440 { "CPU_ANY_MOVDIR64B_FLAGS",
441 "CpuMOVDIR64B" },
442 { "CPU_ANY_ENQCMD_FLAGS",
443 "CpuENQCMD" },
444 { "CPU_ANY_SERIALIZE_FLAGS",
445 "CpuSERIALIZE" },
446 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
447 "CpuAVX512_VP2INTERSECT" },
448 { "CPU_ANY_TDX_FLAGS",
449 "CpuTDX" },
450 { "CPU_ANY_TSXLDTRK_FLAGS",
451 "CpuTSXLDTRK" },
452 { "CPU_ANY_KL_FLAGS",
453 "CpuKL|CpuWideKL" },
454 { "CPU_ANY_WIDEKL_FLAGS",
455 "CpuWideKL" },
456 { "CPU_ANY_HRESET_FLAGS",
457 "CpuHRESET" },
458 { "CPU_ANY_AVX512_FP16_FLAGS",
459 "CpuAVX512_FP16" },
460 { "CPU_ANY_AVX_IFMA_FLAGS",
461 "CpuAVX_IFMA" },
462 { "CPU_ANY_AVX_VNNI_INT8_FLAGS",
463 "CpuAVX_VNNI_INT8" },
464 { "CPU_ANY_CMPCCXADD_FLAGS",
465 "CpuCMPCCXADD" },
466 { "CPU_ANY_WRMSRNS_FLAGS",
467 "CpuWRMSRNS" },
468 { "CPU_ANY_MSRLIST_FLAGS",
469 "CpuMSRLIST" },
470 { "CPU_ANY_AVX_NE_CONVERT_FLAGS",
471 "CpuAVX_NE_CONVERT" },
472 { "CPU_ANY_RAO_INT_FLAGS",
473 "CpuRAO_INT"},
476 static initializer operand_type_init[] =
478 { "OPERAND_TYPE_NONE",
479 "0" },
480 { "OPERAND_TYPE_REG8",
481 "Class=Reg|Byte" },
482 { "OPERAND_TYPE_REG16",
483 "Class=Reg|Word" },
484 { "OPERAND_TYPE_REG32",
485 "Class=Reg|Dword" },
486 { "OPERAND_TYPE_REG64",
487 "Class=Reg|Qword" },
488 { "OPERAND_TYPE_IMM1",
489 "Imm1" },
490 { "OPERAND_TYPE_IMM8",
491 "Imm8" },
492 { "OPERAND_TYPE_IMM8S",
493 "Imm8S" },
494 { "OPERAND_TYPE_IMM16",
495 "Imm16" },
496 { "OPERAND_TYPE_IMM32",
497 "Imm32" },
498 { "OPERAND_TYPE_IMM32S",
499 "Imm32S" },
500 { "OPERAND_TYPE_IMM64",
501 "Imm64" },
502 { "OPERAND_TYPE_BASEINDEX",
503 "BaseIndex" },
504 { "OPERAND_TYPE_DISP8",
505 "Disp8" },
506 { "OPERAND_TYPE_DISP16",
507 "Disp16" },
508 { "OPERAND_TYPE_DISP32",
509 "Disp32" },
510 { "OPERAND_TYPE_DISP64",
511 "Disp64" },
512 { "OPERAND_TYPE_INOUTPORTREG",
513 "Instance=RegD|Word" },
514 { "OPERAND_TYPE_SHIFTCOUNT",
515 "Instance=RegC|Byte" },
516 { "OPERAND_TYPE_CONTROL",
517 "Class=RegCR" },
518 { "OPERAND_TYPE_TEST",
519 "Class=RegTR" },
520 { "OPERAND_TYPE_DEBUG",
521 "Class=RegDR" },
522 { "OPERAND_TYPE_FLOATREG",
523 "Class=Reg|Tbyte" },
524 { "OPERAND_TYPE_FLOATACC",
525 "Instance=Accum|Tbyte" },
526 { "OPERAND_TYPE_SREG",
527 "Class=SReg" },
528 { "OPERAND_TYPE_REGMMX",
529 "Class=RegMMX" },
530 { "OPERAND_TYPE_REGXMM",
531 "Class=RegSIMD|Xmmword" },
532 { "OPERAND_TYPE_REGYMM",
533 "Class=RegSIMD|Ymmword" },
534 { "OPERAND_TYPE_REGZMM",
535 "Class=RegSIMD|Zmmword" },
536 { "OPERAND_TYPE_REGTMM",
537 "Class=RegSIMD|Tmmword" },
538 { "OPERAND_TYPE_REGMASK",
539 "Class=RegMask" },
540 { "OPERAND_TYPE_REGBND",
541 "Class=RegBND" },
542 { "OPERAND_TYPE_ACC8",
543 "Instance=Accum|Byte" },
544 { "OPERAND_TYPE_ACC16",
545 "Instance=Accum|Word" },
546 { "OPERAND_TYPE_ACC32",
547 "Instance=Accum|Dword" },
548 { "OPERAND_TYPE_ACC64",
549 "Instance=Accum|Qword" },
550 { "OPERAND_TYPE_DISP16_32",
551 "Disp16|Disp32" },
552 { "OPERAND_TYPE_ANYDISP",
553 "Disp8|Disp16|Disp32|Disp64" },
554 { "OPERAND_TYPE_IMM16_32",
555 "Imm16|Imm32" },
556 { "OPERAND_TYPE_IMM16_32S",
557 "Imm16|Imm32S" },
558 { "OPERAND_TYPE_IMM16_32_32S",
559 "Imm16|Imm32|Imm32S" },
560 { "OPERAND_TYPE_IMM32_64",
561 "Imm32|Imm64" },
562 { "OPERAND_TYPE_IMM32_32S_DISP32",
563 "Imm32|Imm32S|Disp32" },
564 { "OPERAND_TYPE_IMM64_DISP64",
565 "Imm64|Disp64" },
566 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
567 "Imm32|Imm32S|Imm64|Disp32" },
568 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
569 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
572 typedef struct bitfield
574 int position;
575 int value;
576 const char *name;
577 } bitfield;
579 #define BITFIELD(n) { n, 0, #n }
581 static bitfield cpu_flags[] =
583 BITFIELD (Cpu186),
584 BITFIELD (Cpu286),
585 BITFIELD (Cpu386),
586 BITFIELD (Cpu486),
587 BITFIELD (Cpu586),
588 BITFIELD (Cpu686),
589 BITFIELD (CpuCMOV),
590 BITFIELD (CpuFXSR),
591 BITFIELD (CpuClflush),
592 BITFIELD (CpuNop),
593 BITFIELD (CpuSYSCALL),
594 BITFIELD (Cpu8087),
595 BITFIELD (Cpu287),
596 BITFIELD (Cpu387),
597 BITFIELD (Cpu687),
598 BITFIELD (CpuFISTTP),
599 BITFIELD (CpuMMX),
600 BITFIELD (CpuSSE),
601 BITFIELD (CpuSSE2),
602 BITFIELD (CpuSSE3),
603 BITFIELD (CpuSSSE3),
604 BITFIELD (CpuSSE4_1),
605 BITFIELD (CpuSSE4_2),
606 BITFIELD (CpuAVX),
607 BITFIELD (CpuAVX2),
608 BITFIELD (CpuAVX512F),
609 BITFIELD (CpuAVX512CD),
610 BITFIELD (CpuAVX512ER),
611 BITFIELD (CpuAVX512PF),
612 BITFIELD (CpuAVX512VL),
613 BITFIELD (CpuAVX512DQ),
614 BITFIELD (CpuAVX512BW),
615 BITFIELD (CpuIAMCU),
616 BITFIELD (CpuSSE4a),
617 BITFIELD (Cpu3dnow),
618 BITFIELD (Cpu3dnowA),
619 BITFIELD (CpuPadLock),
620 BITFIELD (CpuSVME),
621 BITFIELD (CpuVMX),
622 BITFIELD (CpuSMX),
623 BITFIELD (CpuXsave),
624 BITFIELD (CpuXsaveopt),
625 BITFIELD (CpuAES),
626 BITFIELD (CpuPCLMUL),
627 BITFIELD (CpuFMA),
628 BITFIELD (CpuFMA4),
629 BITFIELD (CpuXOP),
630 BITFIELD (CpuLWP),
631 BITFIELD (CpuBMI),
632 BITFIELD (CpuTBM),
633 BITFIELD (CpuLM),
634 BITFIELD (CpuMovbe),
635 BITFIELD (CpuCX16),
636 BITFIELD (CpuEPT),
637 BITFIELD (CpuRdtscp),
638 BITFIELD (CpuFSGSBase),
639 BITFIELD (CpuRdRnd),
640 BITFIELD (CpuF16C),
641 BITFIELD (CpuBMI2),
642 BITFIELD (CpuLZCNT),
643 BITFIELD (CpuPOPCNT),
644 BITFIELD (CpuHLE),
645 BITFIELD (CpuRTM),
646 BITFIELD (CpuINVPCID),
647 BITFIELD (CpuVMFUNC),
648 BITFIELD (CpuRDSEED),
649 BITFIELD (CpuADX),
650 BITFIELD (CpuPRFCHW),
651 BITFIELD (CpuSMAP),
652 BITFIELD (CpuSHA),
653 BITFIELD (CpuClflushOpt),
654 BITFIELD (CpuXSAVES),
655 BITFIELD (CpuXSAVEC),
656 BITFIELD (CpuPREFETCHWT1),
657 BITFIELD (CpuSE1),
658 BITFIELD (CpuCLWB),
659 BITFIELD (CpuMPX),
660 BITFIELD (CpuAVX512IFMA),
661 BITFIELD (CpuAVX512VBMI),
662 BITFIELD (CpuAVX512_4FMAPS),
663 BITFIELD (CpuAVX512_4VNNIW),
664 BITFIELD (CpuAVX512_VPOPCNTDQ),
665 BITFIELD (CpuAVX512_VBMI2),
666 BITFIELD (CpuAVX512_VNNI),
667 BITFIELD (CpuAVX512_BITALG),
668 BITFIELD (CpuAVX512_BF16),
669 BITFIELD (CpuAVX512_VP2INTERSECT),
670 BITFIELD (CpuTDX),
671 BITFIELD (CpuAVX_VNNI),
672 BITFIELD (CpuAVX512_FP16),
673 BITFIELD (CpuPREFETCHI),
674 BITFIELD (CpuAVX_IFMA),
675 BITFIELD (CpuAVX_VNNI_INT8),
676 BITFIELD (CpuCMPCCXADD),
677 BITFIELD (CpuWRMSRNS),
678 BITFIELD (CpuMSRLIST),
679 BITFIELD (CpuAVX_NE_CONVERT),
680 BITFIELD (CpuRAO_INT),
681 BITFIELD (CpuMWAITX),
682 BITFIELD (CpuCLZERO),
683 BITFIELD (CpuOSPKE),
684 BITFIELD (CpuRDPID),
685 BITFIELD (CpuPTWRITE),
686 BITFIELD (CpuIBT),
687 BITFIELD (CpuSHSTK),
688 BITFIELD (CpuGFNI),
689 BITFIELD (CpuVAES),
690 BITFIELD (CpuVPCLMULQDQ),
691 BITFIELD (CpuWBNOINVD),
692 BITFIELD (CpuPCONFIG),
693 BITFIELD (CpuWAITPKG),
694 BITFIELD (CpuUINTR),
695 BITFIELD (CpuCLDEMOTE),
696 BITFIELD (CpuAMX_INT8),
697 BITFIELD (CpuAMX_BF16),
698 BITFIELD (CpuAMX_FP16),
699 BITFIELD (CpuAMX_TILE),
700 BITFIELD (CpuMOVDIRI),
701 BITFIELD (CpuMOVDIR64B),
702 BITFIELD (CpuENQCMD),
703 BITFIELD (CpuSERIALIZE),
704 BITFIELD (CpuRDPRU),
705 BITFIELD (CpuMCOMMIT),
706 BITFIELD (CpuSEV_ES),
707 BITFIELD (CpuTSXLDTRK),
708 BITFIELD (CpuKL),
709 BITFIELD (CpuWideKL),
710 BITFIELD (CpuHRESET),
711 BITFIELD (CpuINVLPGB),
712 BITFIELD (CpuTLBSYNC),
713 BITFIELD (CpuSNP),
714 BITFIELD (Cpu64),
715 BITFIELD (CpuNo64),
716 #ifdef CpuUnused
717 BITFIELD (CpuUnused),
718 #endif
721 static bitfield opcode_modifiers[] =
723 BITFIELD (D),
724 BITFIELD (W),
725 BITFIELD (Load),
726 BITFIELD (Modrm),
727 BITFIELD (Jump),
728 BITFIELD (FloatMF),
729 BITFIELD (FloatR),
730 BITFIELD (Size),
731 BITFIELD (CheckRegSize),
732 BITFIELD (OperandConstraint),
733 BITFIELD (MnemonicSize),
734 BITFIELD (No_bSuf),
735 BITFIELD (No_wSuf),
736 BITFIELD (No_lSuf),
737 BITFIELD (No_sSuf),
738 BITFIELD (No_qSuf),
739 BITFIELD (No_ldSuf),
740 BITFIELD (FWait),
741 BITFIELD (IsString),
742 BITFIELD (RegMem),
743 BITFIELD (BNDPrefixOk),
744 BITFIELD (PrefixOk),
745 BITFIELD (IsPrefix),
746 BITFIELD (ImmExt),
747 BITFIELD (NoRex64),
748 BITFIELD (Vex),
749 BITFIELD (VexVVVV),
750 BITFIELD (VexW),
751 BITFIELD (OpcodeSpace),
752 BITFIELD (OpcodePrefix),
753 BITFIELD (VexSources),
754 BITFIELD (SIB),
755 BITFIELD (SSE2AVX),
756 BITFIELD (EVex),
757 BITFIELD (Masking),
758 BITFIELD (Broadcast),
759 BITFIELD (StaticRounding),
760 BITFIELD (SAE),
761 BITFIELD (Disp8MemShift),
762 BITFIELD (Optimize),
763 BITFIELD (ATTMnemonic),
764 BITFIELD (ATTSyntax),
765 BITFIELD (IntelSyntax),
766 BITFIELD (ISA64),
769 #define CLASS(n) #n, n
771 static const struct {
772 const char *name;
773 enum operand_class value;
774 } operand_classes[] = {
775 CLASS (Reg),
776 CLASS (SReg),
777 CLASS (RegCR),
778 CLASS (RegDR),
779 CLASS (RegTR),
780 CLASS (RegMMX),
781 CLASS (RegSIMD),
782 CLASS (RegMask),
783 CLASS (RegBND),
786 #undef CLASS
788 #define INSTANCE(n) #n, n
790 static const struct {
791 const char *name;
792 enum operand_instance value;
793 } operand_instances[] = {
794 INSTANCE (Accum),
795 INSTANCE (RegC),
796 INSTANCE (RegD),
797 INSTANCE (RegB),
800 #undef INSTANCE
802 static bitfield operand_types[] =
804 BITFIELD (Imm1),
805 BITFIELD (Imm8),
806 BITFIELD (Imm8S),
807 BITFIELD (Imm16),
808 BITFIELD (Imm32),
809 BITFIELD (Imm32S),
810 BITFIELD (Imm64),
811 BITFIELD (BaseIndex),
812 BITFIELD (Disp8),
813 BITFIELD (Disp16),
814 BITFIELD (Disp32),
815 BITFIELD (Disp64),
816 BITFIELD (Byte),
817 BITFIELD (Word),
818 BITFIELD (Dword),
819 BITFIELD (Fword),
820 BITFIELD (Qword),
821 BITFIELD (Tbyte),
822 BITFIELD (Xmmword),
823 BITFIELD (Ymmword),
824 BITFIELD (Zmmword),
825 BITFIELD (Tmmword),
826 BITFIELD (Unspecified),
827 #ifdef OTUnused
828 BITFIELD (OTUnused),
829 #endif
832 static const char *filename;
833 static i386_cpu_flags active_cpu_flags;
834 static int active_isstring;
836 struct template_arg {
837 const struct template_arg *next;
838 const char *val;
841 struct template_instance {
842 const struct template_instance *next;
843 const char *name;
844 const struct template_arg *args;
847 struct template_param {
848 const struct template_param *next;
849 const char *name;
852 struct template {
853 struct template *next;
854 const char *name;
855 const struct template_instance *instances;
856 const struct template_param *params;
859 static struct template *templates;
861 static int
862 compare (const void *x, const void *y)
864 const bitfield *xp = (const bitfield *) x;
865 const bitfield *yp = (const bitfield *) y;
866 return xp->position - yp->position;
869 static void
870 fail (const char *message, ...)
872 va_list args;
874 va_start (args, message);
875 fprintf (stderr, _("%s: error: "), program_name);
876 vfprintf (stderr, message, args);
877 va_end (args);
878 xexit (1);
881 static void
882 process_copyright (FILE *fp)
884 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
885 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
887 This file is part of the GNU opcodes library.\n\
889 This library is free software; you can redistribute it and/or modify\n\
890 it under the terms of the GNU General Public License as published by\n\
891 the Free Software Foundation; either version 3, or (at your option)\n\
892 any later version.\n\
894 It is distributed in the hope that it will be useful, but WITHOUT\n\
895 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
896 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
897 License for more details.\n\
899 You should have received a copy of the GNU General Public License\n\
900 along with this program; if not, write to the Free Software\n\
901 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
902 MA 02110-1301, USA. */\n");
905 /* Remove leading white spaces. */
907 static char *
908 remove_leading_whitespaces (char *str)
910 while (ISSPACE (*str))
911 str++;
912 return str;
915 /* Remove trailing white spaces. */
917 static void
918 remove_trailing_whitespaces (char *str)
920 size_t last = strlen (str);
922 if (last == 0)
923 return;
927 last--;
928 if (ISSPACE (str [last]))
929 str[last] = '\0';
930 else
931 break;
933 while (last != 0);
936 /* Find next field separated by SEP and terminate it. Return a
937 pointer to the one after it. */
939 static char *
940 next_field (char *str, char sep, char **next, char *last)
942 char *p;
944 p = remove_leading_whitespaces (str);
945 for (str = p; *str != sep && *str != '\0'; str++);
947 *str = '\0';
948 remove_trailing_whitespaces (p);
950 *next = str + 1;
952 if (p >= last)
953 abort ();
955 return p;
958 static void set_bitfield (char *, bitfield *, int, unsigned int, int);
960 static int
961 set_bitfield_from_cpu_flag_init (char *f, bitfield *array, unsigned int size,
962 int lineno)
964 char *str, *next, *last;
965 unsigned int i;
967 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
968 if (strcmp (cpu_flag_init[i].name, f) == 0)
970 /* Turn on selective bits. */
971 char *init = xstrdup (cpu_flag_init[i].init);
972 last = init + strlen (init);
973 for (next = init; next && next < last; )
975 str = next_field (next, '|', &next, last);
976 if (str)
977 set_bitfield (str, array, 1, size, lineno);
979 free (init);
980 return 0;
983 return -1;
986 static void
987 set_bitfield (char *f, bitfield *array, int value,
988 unsigned int size, int lineno)
990 unsigned int i;
992 /* Ignore empty fields; they may result from template expansions. */
993 if (*f == '\0')
994 return;
996 for (i = 0; i < size; i++)
997 if (strcasecmp (array[i].name, f) == 0)
999 array[i].value = value;
1000 return;
1003 if (value)
1005 const char *v = strchr (f, '=');
1007 if (v)
1009 size_t n = v - f;
1010 char *end;
1012 for (i = 0; i < size; i++)
1013 if (strncasecmp (array[i].name, f, n) == 0)
1015 value = strtol (v + 1, &end, 0);
1016 if (*end == '\0')
1018 array[i].value = value;
1019 return;
1021 break;
1026 /* Handle CPU_XXX_FLAGS. */
1027 if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
1028 return;
1030 if (lineno != -1)
1031 fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
1032 else
1033 fail (_("unknown bitfield: %s\n"), f);
1036 static void
1037 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
1038 int macro, const char *comma, const char *indent)
1040 unsigned int i;
1042 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
1044 fprintf (table, "%s{ { ", indent);
1046 for (i = 0; i < size - 1; i++)
1048 if (((i + 1) % 20) != 0)
1049 fprintf (table, "%d, ", flags[i].value);
1050 else
1051 fprintf (table, "%d,", flags[i].value);
1052 if (((i + 1) % 20) == 0)
1054 /* We need \\ for macro. */
1055 if (macro)
1056 fprintf (table, " \\\n %s", indent);
1057 else
1058 fprintf (table, "\n %s", indent);
1060 if (flags[i].value)
1061 active_cpu_flags.array[i / 32] |= 1U << (i % 32);
1064 fprintf (table, "%d } }%s\n", flags[i].value, comma);
1067 static void
1068 process_i386_cpu_flag (FILE *table, char *flag, int macro,
1069 const char *comma, const char *indent,
1070 int lineno)
1072 char *str, *next = flag, *last;
1073 unsigned int i;
1074 int value = 1;
1075 bitfield flags [ARRAY_SIZE (cpu_flags)];
1077 /* Copy the default cpu flags. */
1078 memcpy (flags, cpu_flags, sizeof (cpu_flags));
1080 if (flag[0] == '~')
1082 last = flag + strlen (flag);
1084 if (flag[1] == '(')
1086 last -= 1;
1087 next = flag + 2;
1088 if (*last != ')')
1089 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
1090 lineno, flag);
1091 *last = '\0';
1093 else
1094 next = flag + 1;
1096 /* First we turn on everything except for cpu64, cpuno64, and - if
1097 present - the padding field. */
1098 for (i = 0; i < ARRAY_SIZE (flags); i++)
1099 if (flags[i].position < Cpu64)
1100 flags[i].value = 1;
1102 /* Turn off selective bits. */
1103 value = 0;
1106 if (strcmp (flag, "0"))
1108 /* Turn on/off selective bits. */
1109 last = flag + strlen (flag);
1110 for (; next && next < last; )
1112 str = next_field (next, '|', &next, last);
1113 if (str)
1114 set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
1118 output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
1119 comma, indent);
1122 static void
1123 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
1125 unsigned int i;
1127 fprintf (table, " { ");
1129 for (i = 0; i < size - 1; i++)
1131 if (((i + 1) % 20) != 0)
1132 fprintf (table, "%d, ", modifier[i].value);
1133 else
1134 fprintf (table, "%d,", modifier[i].value);
1135 if (((i + 1) % 20) == 0)
1136 fprintf (table, "\n ");
1139 fprintf (table, "%d },\n", modifier[i].value);
1142 /* Returns LOG2 of element size. */
1143 static int
1144 get_element_size (char **opnd, int lineno)
1146 char *str, *next, *last, *op;
1147 const char *full = opnd[0];
1148 int elem_size = INT_MAX;
1150 /* Find the memory operand. */
1151 while (full != NULL && strstr(full, "BaseIndex") == NULL)
1152 full = *++opnd;
1153 if (full == NULL)
1154 fail (_("%s: %d: no memory operand\n"), filename, lineno);
1156 op = xstrdup (full);
1157 last = op + strlen (op);
1158 for (next = op; next && next < last; )
1160 str = next_field (next, '|', &next, last);
1161 if (str)
1163 if (strcasecmp(str, "Byte") == 0)
1165 /* The smallest element size, no need to check
1166 further. */
1167 elem_size = 0;
1168 break;
1170 else if (strcasecmp(str, "Word") == 0)
1172 if (elem_size > 1)
1173 elem_size = 1;
1175 else if (strcasecmp(str, "Dword") == 0)
1177 if (elem_size > 2)
1178 elem_size = 2;
1180 else if (strcasecmp(str, "Qword") == 0)
1182 if (elem_size > 3)
1183 elem_size = 3;
1187 free (op);
1189 if (elem_size == INT_MAX)
1190 fail (_("%s: %d: unknown element size: %s\n"), filename, lineno, full);
1192 return elem_size;
1195 static void
1196 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
1197 unsigned int prefix, char **opnd, int lineno)
1199 char *str, *next, *last;
1200 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
1202 active_isstring = 0;
1204 /* Copy the default opcode modifier. */
1205 memcpy (modifiers, opcode_modifiers, sizeof (modifiers));
1207 if (strcmp (mod, "0"))
1209 unsigned int have_w = 0, bwlq_suf = 0xf;
1211 last = mod + strlen (mod);
1212 for (next = mod; next && next < last; )
1214 str = next_field (next, '|', &next, last);
1215 if (str)
1217 int val = 1;
1218 if (strcasecmp(str, "Broadcast") == 0)
1219 val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
1220 else if (strcasecmp(str, "Disp8MemShift") == 0)
1221 val = get_element_size (opnd, lineno);
1223 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
1224 lineno);
1225 if (strcasecmp(str, "IsString") == 0)
1226 active_isstring = 1;
1228 if (strcasecmp(str, "W") == 0)
1229 have_w = 1;
1231 if (strcasecmp(str, "No_bSuf") == 0)
1232 bwlq_suf &= ~1;
1233 if (strcasecmp(str, "No_wSuf") == 0)
1234 bwlq_suf &= ~2;
1235 if (strcasecmp(str, "No_lSuf") == 0)
1236 bwlq_suf &= ~4;
1237 if (strcasecmp(str, "No_qSuf") == 0)
1238 bwlq_suf &= ~8;
1242 if (space)
1244 if (!modifiers[OpcodeSpace].value)
1245 modifiers[OpcodeSpace].value = space;
1246 else if (modifiers[OpcodeSpace].value != space)
1247 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1248 filename, lineno);
1249 else
1250 fprintf (stderr,
1251 _("%s:%d: Warning: redundant opcode space specification\n"),
1252 filename, lineno);
1255 if (prefix)
1257 if (!modifiers[OpcodePrefix].value)
1258 modifiers[OpcodePrefix].value = prefix;
1259 else if (modifiers[OpcodePrefix].value != prefix)
1260 fail (_("%s:%d: Conflicting prefix specifications\n"),
1261 filename, lineno);
1262 else
1263 fprintf (stderr,
1264 _("%s:%d: Warning: redundant prefix specification\n"),
1265 filename, lineno);
1268 if (have_w && !bwlq_suf)
1269 fail ("%s: %d: stray W modifier\n", filename, lineno);
1270 if (have_w && !(bwlq_suf & 1))
1271 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
1272 filename, lineno);
1273 if (have_w && !(bwlq_suf & ~1))
1274 fprintf (stderr,
1275 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1276 filename, lineno);
1278 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
1281 enum stage {
1282 stage_macros,
1283 stage_opcodes,
1284 stage_registers,
1287 static void
1288 output_operand_type (FILE *table, enum operand_class class,
1289 enum operand_instance instance,
1290 const bitfield *types, unsigned int size,
1291 enum stage stage, const char *indent)
1293 unsigned int i;
1295 fprintf (table, "{ { %d, %d, ", class, instance);
1297 for (i = 0; i < size - 1; i++)
1299 if (((i + 3) % 20) != 0)
1300 fprintf (table, "%d, ", types[i].value);
1301 else
1302 fprintf (table, "%d,", types[i].value);
1303 if (((i + 3) % 20) == 0)
1305 /* We need \\ for macro. */
1306 if (stage == stage_macros)
1307 fprintf (table, " \\\n%s", indent);
1308 else
1309 fprintf (table, "\n%s", indent);
1313 fprintf (table, "%d } }", types[i].value);
1316 static void
1317 process_i386_operand_type (FILE *table, char *op, enum stage stage,
1318 const char *indent, int lineno)
1320 char *str, *next, *last;
1321 enum operand_class class = ClassNone;
1322 enum operand_instance instance = InstanceNone;
1323 bitfield types [ARRAY_SIZE (operand_types)];
1325 /* Copy the default operand type. */
1326 memcpy (types, operand_types, sizeof (types));
1328 if (strcmp (op, "0"))
1330 int baseindex = 0;
1332 last = op + strlen (op);
1333 for (next = op; next && next < last; )
1335 str = next_field (next, '|', &next, last);
1336 if (str)
1338 unsigned int i;
1340 if (!strncmp(str, "Class=", 6))
1342 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
1343 if (!strcmp(str + 6, operand_classes[i].name))
1345 class = operand_classes[i].value;
1346 str = NULL;
1347 break;
1351 if (str && !strncmp(str, "Instance=", 9))
1353 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
1354 if (!strcmp(str + 9, operand_instances[i].name))
1356 instance = operand_instances[i].value;
1357 str = NULL;
1358 break;
1362 if (str)
1364 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
1365 if (strcasecmp(str, "BaseIndex") == 0)
1366 baseindex = 1;
1370 if (stage == stage_opcodes && baseindex && !active_isstring)
1372 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno);
1373 if (!active_cpu_flags.bitfield.cpu64
1374 && !active_cpu_flags.bitfield.cpumpx)
1375 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
1376 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
1379 output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
1380 stage, indent);
1383 static void
1384 output_i386_opcode (FILE *table, const char *name, char *str,
1385 char *last, int lineno)
1387 unsigned int i, length, prefix = 0, space = 0;
1388 char *base_opcode, *extension_opcode, *end;
1389 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
1390 unsigned long long opcode;
1392 /* Find base_opcode. */
1393 base_opcode = next_field (str, ',', &str, last);
1395 /* Find extension_opcode. */
1396 extension_opcode = next_field (str, ',', &str, last);
1398 /* Find cpu_flags. */
1399 cpu_flags = next_field (str, ',', &str, last);
1401 /* Find opcode_modifier. */
1402 opcode_modifier = next_field (str, ',', &str, last);
1404 /* Remove the first {. */
1405 str = remove_leading_whitespaces (str);
1406 if (*str != '{')
1407 abort ();
1408 str = remove_leading_whitespaces (str + 1);
1409 remove_trailing_whitespaces (str);
1411 /* Remove } and trailing white space. */
1412 i = strlen (str);
1413 if (!i || str[i - 1] != '}')
1414 abort ();
1415 str[--i] = '\0';
1416 remove_trailing_whitespaces (str);
1418 if (!*str)
1419 operand_types [i = 0] = NULL;
1420 else
1422 last = str + strlen (str);
1424 /* Find operand_types. */
1425 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1427 if (str >= last)
1429 operand_types [i] = NULL;
1430 break;
1433 operand_types [i] = next_field (str, ',', &str, last);
1437 opcode = strtoull (base_opcode, &end, 0);
1439 /* Determine opcode length. */
1440 for (length = 1; length < 8; ++length)
1441 if (!(opcode >> (8 * length)))
1442 break;
1444 /* Transform prefixes encoded in the opcode into opcode modifier
1445 representation. */
1446 if (length > 1)
1448 switch (opcode >> (8 * length - 8))
1450 case 0x66: prefix = PREFIX_0X66; break;
1451 case 0xF3: prefix = PREFIX_0XF3; break;
1452 case 0xF2: prefix = PREFIX_0XF2; break;
1455 if (prefix)
1456 opcode &= (1ULL << (8 * --length)) - 1;
1459 /* Transform opcode space encoded in the opcode into opcode modifier
1460 representation. */
1461 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
1463 switch ((opcode >> (8 * length - 16)) & 0xff)
1465 default: space = SPACE_0F; break;
1466 case 0x38: space = SPACE_0F38; break;
1467 case 0x3A: space = SPACE_0F3A; break;
1470 if (space != SPACE_0F && --length == 1)
1471 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1472 filename, lineno, name);
1473 opcode &= (1ULL << (8 * --length)) - 1;
1476 if (length > 2)
1477 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1478 filename, lineno, name, 2 * length, opcode);
1480 fprintf (table, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1481 name, 2 * (int)length, opcode, end, i, extension_opcode);
1483 process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
1484 operand_types, lineno);
1486 process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
1488 fprintf (table, " { ");
1490 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
1492 if (!operand_types[i])
1494 if (i == 0)
1495 process_i386_operand_type (table, "0", stage_opcodes, "\t ",
1496 lineno);
1497 break;
1500 if (i != 0)
1501 fprintf (table, ",\n ");
1503 process_i386_operand_type (table, operand_types[i], stage_opcodes,
1504 "\t ", lineno);
1506 fprintf (table, " } },\n");
1509 struct opcode_hash_entry
1511 struct opcode_hash_entry *next;
1512 char *name;
1513 char *opcode;
1514 int lineno;
1517 /* Calculate the hash value of an opcode hash entry P. */
1519 static hashval_t
1520 opcode_hash_hash (const void *p)
1522 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1523 return htab_hash_string (entry->name);
1526 /* Compare a string Q against an opcode hash entry P. */
1528 static int
1529 opcode_hash_eq (const void *p, const void *q)
1531 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
1532 const char *name = (const char *) q;
1533 return strcmp (name, entry->name) == 0;
1536 static void
1537 parse_template (char *buf, int lineno)
1539 char sep, *end, *name;
1540 struct template *tmpl;
1541 struct template_instance *last_inst = NULL;
1543 buf = remove_leading_whitespaces (buf + 1);
1544 end = strchr (buf, ':');
1545 if (end == NULL)
1547 struct template *prev = NULL;
1549 end = strchr (buf, '>');
1550 if (end == NULL)
1551 fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
1552 if (*remove_leading_whitespaces (end + 1))
1553 fail ("%s: %d: malformed template purge\n", filename, lineno);
1554 *end = '\0';
1555 remove_trailing_whitespaces (buf);
1556 /* Don't bother freeing the various structures. */
1557 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
1558 if (!strcmp (buf, tmpl->name))
1559 break;
1560 if (tmpl == NULL)
1561 fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
1562 if (prev)
1563 prev->next = tmpl->next;
1564 else
1565 templates = tmpl->next;
1566 return;
1568 *end++ = '\0';
1569 remove_trailing_whitespaces (buf);
1571 if (*buf == '\0')
1572 fail ("%s: %d: missing template identifier\n", filename, lineno);
1573 tmpl = xmalloc (sizeof (*tmpl));
1574 tmpl->name = xstrdup (buf);
1576 tmpl->params = NULL;
1577 do {
1578 struct template_param *param;
1580 buf = remove_leading_whitespaces (end);
1581 end = strpbrk (buf, ":,");
1582 if (end == NULL)
1583 fail ("%s: %d: missing ':' or ','\n", filename, lineno);
1585 sep = *end;
1586 *end++ = '\0';
1587 remove_trailing_whitespaces (buf);
1589 param = xmalloc (sizeof (*param));
1590 param->name = xstrdup (buf);
1591 param->next = tmpl->params;
1592 tmpl->params = param;
1593 } while (sep == ':');
1595 tmpl->instances = NULL;
1596 do {
1597 struct template_instance *inst;
1598 char *cur, *next;
1599 const struct template_param *param;
1601 buf = remove_leading_whitespaces (end);
1602 end = strpbrk (buf, ",>");
1603 if (end == NULL)
1604 fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
1606 sep = *end;
1607 *end++ = '\0';
1609 inst = xmalloc (sizeof (*inst));
1610 inst->next = NULL;
1611 inst->args = NULL;
1613 cur = next_field (buf, ':', &next, end);
1614 inst->name = *cur != '$' ? xstrdup (cur) : "";
1616 for (param = tmpl->params; param; param = param->next)
1618 struct template_arg *arg = xmalloc (sizeof (*arg));
1620 cur = next_field (next, ':', &next, end);
1621 if (next > end)
1622 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
1623 arg->val = xstrdup (cur);
1624 arg->next = inst->args;
1625 inst->args = arg;
1628 if (tmpl->instances)
1629 last_inst->next = inst;
1630 else
1631 tmpl->instances = inst;
1632 last_inst = inst;
1633 } while (sep == ',');
1635 buf = remove_leading_whitespaces (end);
1636 if (*buf)
1637 fprintf(stderr, "%s: %d: excess characters '%s'\n",
1638 filename, lineno, buf);
1640 tmpl->next = templates;
1641 templates = tmpl;
1644 static unsigned int
1645 expand_templates (char *name, const char *str, htab_t opcode_hash_table,
1646 struct opcode_hash_entry ***opcode_array_p, int lineno)
1648 static unsigned int idx, opcode_array_size;
1649 struct opcode_hash_entry **opcode_array = *opcode_array_p;
1650 struct opcode_hash_entry **hash_slot, **entry;
1651 char *ptr1 = strchr(name, '<'), *ptr2;
1653 if (ptr1 == NULL)
1655 /* Get the slot in hash table. */
1656 hash_slot = (struct opcode_hash_entry **)
1657 htab_find_slot_with_hash (opcode_hash_table, name,
1658 htab_hash_string (name),
1659 INSERT);
1661 if (*hash_slot == NULL)
1663 /* It is the new one. Put it on opcode array. */
1664 if (idx >= opcode_array_size)
1666 /* Grow the opcode array when needed. */
1667 opcode_array_size += 1024;
1668 opcode_array = (struct opcode_hash_entry **)
1669 xrealloc (opcode_array,
1670 sizeof (*opcode_array) * opcode_array_size);
1671 *opcode_array_p = opcode_array;
1674 opcode_array[idx] = (struct opcode_hash_entry *)
1675 xmalloc (sizeof (struct opcode_hash_entry));
1676 opcode_array[idx]->next = NULL;
1677 opcode_array[idx]->name = xstrdup (name);
1678 opcode_array[idx]->opcode = xstrdup (str);
1679 opcode_array[idx]->lineno = lineno;
1680 *hash_slot = opcode_array[idx];
1681 idx++;
1683 else
1685 /* Append it to the existing one. */
1686 entry = hash_slot;
1687 while ((*entry) != NULL)
1688 entry = &(*entry)->next;
1689 *entry = (struct opcode_hash_entry *)
1690 xmalloc (sizeof (struct opcode_hash_entry));
1691 (*entry)->next = NULL;
1692 (*entry)->name = (*hash_slot)->name;
1693 (*entry)->opcode = xstrdup (str);
1694 (*entry)->lineno = lineno;
1697 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
1698 fail ("%s: %d: missing '>'\n", filename, lineno);
1699 else
1701 const struct template *tmpl;
1702 const struct template_instance *inst;
1704 *ptr1 = '\0';
1705 ptr1 = remove_leading_whitespaces (ptr1 + 1);
1706 remove_trailing_whitespaces (ptr1);
1708 *ptr2++ = '\0';
1710 for ( tmpl = templates; tmpl; tmpl = tmpl->next )
1711 if (!strcmp(ptr1, tmpl->name))
1712 break;
1713 if (!tmpl)
1714 fail ("reference to unknown template '%s'\n", ptr1);
1716 for (inst = tmpl->instances; inst; inst = inst->next)
1718 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
1719 char *str2 = xmalloc(2 * strlen(str));
1720 const char *src;
1722 strcpy (name2, name);
1723 strcat (name2, inst->name);
1724 strcat (name2, ptr2);
1726 for (ptr1 = str2, src = str; *src; )
1728 const char *ident = tmpl->name, *end;
1729 const struct template_param *param;
1730 const struct template_arg *arg;
1732 if ((*ptr1 = *src++) != '<')
1734 ++ptr1;
1735 continue;
1737 while (ISSPACE(*src))
1738 ++src;
1739 while (*ident && *src == *ident)
1740 ++src, ++ident;
1741 while (ISSPACE(*src))
1742 ++src;
1743 if (*src != ':' || *ident != '\0')
1745 memcpy (++ptr1, tmpl->name, ident - tmpl->name);
1746 ptr1 += ident - tmpl->name;
1747 continue;
1749 while (ISSPACE(*++src))
1752 end = src;
1753 while (*end != '\0' && !ISSPACE(*end) && *end != '>')
1754 ++end;
1756 for (param = tmpl->params, arg = inst->args; param;
1757 param = param->next, arg = arg->next)
1759 if (end - src == strlen (param->name)
1760 && !memcmp (src, param->name, end - src))
1762 src = end;
1763 break;
1767 if (param == NULL)
1768 fail ("template '%s' has no parameter '%.*s'\n",
1769 tmpl->name, (int)(end - src), src);
1771 while (ISSPACE(*src))
1772 ++src;
1773 if (*src != '>')
1774 fail ("%s: %d: missing '>'\n", filename, lineno);
1776 memcpy(ptr1, arg->val, strlen(arg->val));
1777 ptr1 += strlen(arg->val);
1778 ++src;
1781 *ptr1 = '\0';
1783 expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
1784 lineno);
1786 free (str2);
1787 free (name2);
1791 return idx;
1794 static void
1795 process_i386_opcodes (FILE *table)
1797 FILE *fp;
1798 char buf[2048];
1799 unsigned int i, j;
1800 char *str, *p, *last, *name;
1801 htab_t opcode_hash_table;
1802 struct opcode_hash_entry **opcode_array = NULL;
1803 int lineno = 0, marker = 0;
1805 filename = "i386-opc.tbl";
1806 fp = stdin;
1808 i = 0;
1809 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
1810 opcode_hash_eq, NULL,
1811 xcalloc, free);
1813 fprintf (table, "\n/* i386 opcode table. */\n\n");
1814 fprintf (table, "const insn_template i386_optab[] =\n{\n");
1816 /* Put everything on opcode array. */
1817 while (!feof (fp))
1819 if (fgets (buf, sizeof (buf), fp) == NULL)
1820 break;
1822 p = remove_leading_whitespaces (buf);
1824 for ( ; ; )
1826 lineno++;
1828 /* Skip comments. */
1829 str = strstr (p, "//");
1830 if (str != NULL)
1832 str[0] = '\0';
1833 remove_trailing_whitespaces (p);
1834 break;
1837 /* Look for line continuation character. */
1838 remove_trailing_whitespaces (p);
1839 j = strlen (buf);
1840 if (!j || buf[j - 1] != '+')
1841 break;
1842 if (j >= sizeof (buf) - 1)
1843 fail (_("%s: %d: (continued) line too long\n"), filename, lineno);
1845 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
1847 fprintf (stderr, "%s: Line continuation on last line?\n",
1848 filename);
1849 break;
1853 switch (p[0])
1855 case '#':
1856 if (!strcmp("### MARKER ###", buf))
1857 marker = 1;
1858 else
1860 /* Since we ignore all included files (we only care about their
1861 #define-s here), we don't need to monitor filenames. The final
1862 line number directive is going to refer to the main source file
1863 again. */
1864 char *end;
1865 unsigned long ln;
1867 p = remove_leading_whitespaces (p + 1);
1868 if (!strncmp(p, "line", 4))
1869 p += 4;
1870 ln = strtoul (p, &end, 10);
1871 if (ln > 1 && ln < INT_MAX
1872 && *remove_leading_whitespaces (end) == '"')
1873 lineno = ln - 1;
1875 /* Ignore comments. */
1876 case '\0':
1877 continue;
1878 break;
1879 case '<':
1880 parse_template (p, lineno);
1881 continue;
1882 default:
1883 if (!marker)
1884 continue;
1885 break;
1888 last = p + strlen (p);
1890 /* Find name. */
1891 name = next_field (p, ',', &str, last);
1893 i = expand_templates (name, str, opcode_hash_table, &opcode_array,
1894 lineno);
1897 /* Process opcode array. */
1898 for (j = 0; j < i; j++)
1900 struct opcode_hash_entry *next;
1902 for (next = opcode_array[j]; next; next = next->next)
1904 name = next->name;
1905 str = next->opcode;
1906 lineno = next->lineno;
1907 last = str + strlen (str);
1908 output_i386_opcode (table, name, str, last, lineno);
1912 fclose (fp);
1914 fprintf (table, " { NULL, 0, 0, 0,\n");
1916 process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
1918 process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
1920 fprintf (table, " { ");
1921 process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);
1922 fprintf (table, " } }\n");
1924 fprintf (table, "};\n");
1927 static void
1928 process_i386_registers (FILE *table)
1930 FILE *fp;
1931 char buf[2048];
1932 char *str, *p, *last;
1933 char *reg_name, *reg_type, *reg_flags, *reg_num;
1934 char *dw2_32_num, *dw2_64_num;
1935 int lineno = 0;
1937 filename = "i386-reg.tbl";
1938 fp = fopen (filename, "r");
1939 if (fp == NULL)
1940 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1941 xstrerror (errno));
1943 fprintf (table, "\n/* i386 register table. */\n\n");
1944 fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
1946 while (!feof (fp))
1948 if (fgets (buf, sizeof (buf), fp) == NULL)
1949 break;
1951 lineno++;
1953 p = remove_leading_whitespaces (buf);
1955 /* Skip comments. */
1956 str = strstr (p, "//");
1957 if (str != NULL)
1958 str[0] = '\0';
1960 /* Remove trailing white spaces. */
1961 remove_trailing_whitespaces (p);
1963 switch (p[0])
1965 case '#':
1966 fprintf (table, "%s\n", p);
1967 case '\0':
1968 continue;
1969 break;
1970 default:
1971 break;
1974 last = p + strlen (p);
1976 /* Find reg_name. */
1977 reg_name = next_field (p, ',', &str, last);
1979 /* Find reg_type. */
1980 reg_type = next_field (str, ',', &str, last);
1982 /* Find reg_flags. */
1983 reg_flags = next_field (str, ',', &str, last);
1985 /* Find reg_num. */
1986 reg_num = next_field (str, ',', &str, last);
1988 fprintf (table, " { \"%s\",\n ", reg_name);
1990 process_i386_operand_type (table, reg_type, stage_registers, "\t",
1991 lineno);
1993 /* Find 32-bit Dwarf2 register number. */
1994 dw2_32_num = next_field (str, ',', &str, last);
1996 /* Find 64-bit Dwarf2 register number. */
1997 dw2_64_num = next_field (str, ',', &str, last);
1999 fprintf (table, ",\n %s, %s, { %s, %s } },\n",
2000 reg_flags, reg_num, dw2_32_num, dw2_64_num);
2003 fclose (fp);
2005 fprintf (table, "};\n");
2007 fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2010 static void
2011 process_i386_initializers (void)
2013 unsigned int i;
2014 FILE *fp = fopen ("i386-init.h", "w");
2015 char *init;
2017 if (fp == NULL)
2018 fail (_("can't create i386-init.h, errno = %s\n"),
2019 xstrerror (errno));
2021 process_copyright (fp);
2023 for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
2025 fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
2026 init = xstrdup (cpu_flag_init[i].init);
2027 process_i386_cpu_flag (fp, init, 1, "", " ", -1);
2028 free (init);
2031 for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
2033 fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
2034 init = xstrdup (operand_type_init[i].init);
2035 process_i386_operand_type (fp, init, stage_macros, " ", -1);
2036 free (init);
2038 fprintf (fp, "\n");
2040 fclose (fp);
2043 /* Program options. */
2044 #define OPTION_SRCDIR 200
2046 struct option long_options[] =
2048 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
2049 {"debug", no_argument, NULL, 'd'},
2050 {"version", no_argument, NULL, 'V'},
2051 {"help", no_argument, NULL, 'h'},
2052 {0, no_argument, NULL, 0}
2055 static void
2056 print_version (void)
2058 printf ("%s: version 1.0\n", program_name);
2059 xexit (0);
2062 static void
2063 usage (FILE * stream, int status)
2065 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2066 program_name);
2067 xexit (status);
2071 main (int argc, char **argv)
2073 extern int chdir (char *);
2074 char *srcdir = NULL;
2075 int c;
2076 unsigned int i, cpumax;
2077 FILE *table;
2079 program_name = *argv;
2080 xmalloc_set_program_name (program_name);
2082 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
2083 switch (c)
2085 case OPTION_SRCDIR:
2086 srcdir = optarg;
2087 break;
2088 case 'V':
2089 case 'v':
2090 print_version ();
2091 break;
2092 case 'd':
2093 debug = 1;
2094 break;
2095 case 'h':
2096 case '?':
2097 usage (stderr, 0);
2098 default:
2099 case 0:
2100 break;
2103 if (optind != argc)
2104 usage (stdout, 1);
2106 if (srcdir != NULL)
2107 if (chdir (srcdir) != 0)
2108 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2109 srcdir, xstrerror (errno));
2111 /* cpu_flags isn't sorted by position. */
2112 cpumax = 0;
2113 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++)
2114 if (cpu_flags[i].position > cpumax)
2115 cpumax = cpu_flags[i].position;
2117 /* Check the unused bitfield in i386_cpu_flags. */
2118 #ifdef CpuUnused
2119 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
2121 if ((cpumax - 1) != CpuMax)
2122 fail (_("CpuMax != %d!\n"), cpumax);
2123 #else
2124 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
2126 if (cpumax != CpuMax)
2127 fail (_("CpuMax != %d!\n"), cpumax);
2129 c = CpuNumOfBits - CpuMax - 1;
2130 if (c)
2131 fail (_("%d unused bits in i386_cpu_flags.\n"), c);
2132 #endif
2134 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
2136 /* Check the unused bitfield in i386_operand_type. */
2137 #ifdef OTUnused
2138 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2139 == OTNum + 1);
2140 #else
2141 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
2142 == OTNum);
2144 c = OTNumOfBits - OTNum;
2145 if (c)
2146 fail (_("%d unused bits in i386_operand_type.\n"), c);
2147 #endif
2149 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
2150 compare);
2152 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers),
2153 sizeof (opcode_modifiers [0]), compare);
2155 qsort (operand_types, ARRAY_SIZE (operand_types),
2156 sizeof (operand_types [0]), compare);
2158 table = fopen ("i386-tbl.h", "w");
2159 if (table == NULL)
2160 fail (_("can't create i386-tbl.h, errno = %s\n"),
2161 xstrerror (errno));
2163 process_copyright (table);
2165 process_i386_opcodes (table);
2166 process_i386_registers (table);
2167 process_i386_initializers ();
2169 fclose (table);
2171 exit (0);