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