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)
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. */
24 #include "libiberty.h"
26 #include "safe-ctype.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
;
40 typedef struct initializer
46 static initializer cpu_flag_init
[] =
48 { "CPU_UNKNOWN_FLAGS",
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" },
59 "CPU_I186_FLAGS|Cpu286" },
61 "CPU_I286_FLAGS|Cpu386" },
63 "CPU_I386_FLAGS|Cpu486" },
65 "CPU_I486_FLAGS|Cpu387|Cpu586" },
67 "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
68 { "CPU_PENTIUMPRO_FLAGS",
69 "CPU_I686_FLAGS|CpuNop" },
71 "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
73 "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
75 "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
77 "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
79 "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
81 "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
83 "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
85 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
87 "CPU_K6_FLAGS|Cpu3dnow" },
89 "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
91 "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
92 { "CPU_AMDFAM10_FLAGS",
93 "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
95 "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
97 "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
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" },
119 "CPU_387_FLAGS|Cpu687" },
124 { "CPU_CLFLUSH_FLAGS",
128 { "CPU_SYSCALL_FLAGS",
135 "CPU_SSE_FLAGS|CpuSSE2" },
137 "CPU_SSE2_FLAGS|CpuSSE3" },
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" },
150 { "CPU_XSAVEOPT_FLAGS",
151 "CPU_XSAVE_FLAGS|CpuXsaveopt" },
153 "CPU_SSE2_FLAGS|CpuAES" },
154 { "CPU_PCLMUL_FLAGS",
155 "CPU_SSE2_FLAGS|CpuPCLMUL" },
157 "CPU_AVX_FLAGS|CpuFMA" },
159 "CPU_AVX_FLAGS|CpuFMA4" },
161 "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
163 "CPU_XSAVE_FLAGS|CpuLWP" },
172 { "CPU_RDTSCP_FLAGS",
176 { "CPU_FSGSBASE_FLAGS",
181 "CPU_AVX_FLAGS|CpuF16C" },
186 { "CPU_POPCNT_FLAGS",
192 { "CPU_INVPCID_FLAGS",
194 { "CPU_VMFUNC_FLAGS",
197 "CPU_MMX_FLAGS|Cpu3dnow" },
198 { "CPU_3DNOWA_FLAGS",
199 "CPU_3DNOW_FLAGS|Cpu3dnowA" },
200 { "CPU_PADLOCK_FLAGS",
205 "CPU_SSE3_FLAGS|CpuSSE4a" },
207 "CpuLZCNT|CpuPOPCNT" },
209 "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
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",
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",
256 { "CPU_WRMSRNS_FLAGS",
258 { "CPU_MSRLIST_FLAGS",
260 { "CPU_AVX_NE_CONVERT_FLAGS",
261 "CPU_AVX2_FLAGS|CpuAVX_NE_CONVERT" },
262 { "CPU_RAO_INT_FLAGS",
265 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
268 { "CPU_RDSEED_FLAGS",
270 { "CPU_PRFCHW_FLAGS",
275 "CPU_XSAVE_FLAGS|CpuMPX" },
277 "CPU_SSE2_FLAGS|CpuSHA" },
278 { "CPU_CLFLUSHOPT_FLAGS",
280 { "CPU_XSAVES_FLAGS",
281 "CPU_XSAVE_FLAGS|CpuXSAVES" },
282 { "CPU_XSAVEC_FLAGS",
283 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
284 { "CPU_PREFETCHWT1_FLAGS",
290 { "CPU_CLZERO_FLAGS",
292 { "CPU_MWAITX_FLAGS",
295 "CPU_XSAVE_FLAGS|CpuOSPKE" },
298 { "CPU_PTWRITE_FLAGS",
308 { "CPU_VPCLMULQDQ_FLAGS",
310 { "CPU_WBNOINVD_FLAGS",
312 { "CPU_PCONFIG_FLAGS",
314 { "CPU_WAITPKG_FLAGS",
318 { "CPU_CLDEMOTE_FLAGS",
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",
328 { "CPU_MOVDIRI_FLAGS",
330 { "CPU_MOVDIR64B_FLAGS",
332 { "CPU_ENQCMD_FLAGS",
334 { "CPU_SERIALIZE_FLAGS",
336 { "CPU_AVX512_VP2INTERSECT_FLAGS",
337 "CpuAVX512_VP2INTERSECT" },
342 { "CPU_MCOMMIT_FLAGS",
344 { "CPU_SEV_ES_FLAGS",
346 { "CPU_TSXLDTRK_FLAGS",
350 { "CPU_WIDEKL_FLAGS",
352 { "CPU_HRESET_FLAGS",
354 { "CPU_INVLPGB_FLAGS",
356 { "CPU_TLBSYNC_FLAGS",
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",
370 { "CPU_ANY_FXSR_FLAGS",
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",
386 { "CPU_ANY_SSE4A_FLAGS",
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",
396 { "CPU_ANY_AVX512ER_FLAGS",
398 { "CPU_ANY_AVX512PF_FLAGS",
400 { "CPU_ANY_AVX512DQ_FLAGS",
402 { "CPU_ANY_AVX512BW_FLAGS",
403 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
404 { "CPU_ANY_AVX512VL_FLAGS",
406 { "CPU_ANY_AVX512IFMA_FLAGS",
408 { "CPU_ANY_AVX512VBMI_FLAGS",
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",
418 { "CPU_ANY_SHSTK_FLAGS",
420 { "CPU_ANY_AVX512_VBMI2_FLAGS",
422 { "CPU_ANY_AVX512_VNNI_FLAGS",
424 { "CPU_ANY_AVX512_BITALG_FLAGS",
425 "CpuAVX512_BITALG" },
426 { "CPU_ANY_AVX512_BF16_FLAGS",
428 { "CPU_ANY_AMX_INT8_FLAGS",
430 { "CPU_ANY_AMX_BF16_FLAGS",
432 { "CPU_ANY_AMX_TILE_FLAGS",
433 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16|CpuAMX_FP16" },
434 { "CPU_ANY_AVX_VNNI_FLAGS",
436 { "CPU_ANY_MOVDIRI_FLAGS",
438 { "CPU_ANY_UINTR_FLAGS",
440 { "CPU_ANY_MOVDIR64B_FLAGS",
442 { "CPU_ANY_ENQCMD_FLAGS",
444 { "CPU_ANY_SERIALIZE_FLAGS",
446 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
447 "CpuAVX512_VP2INTERSECT" },
448 { "CPU_ANY_TDX_FLAGS",
450 { "CPU_ANY_TSXLDTRK_FLAGS",
452 { "CPU_ANY_KL_FLAGS",
454 { "CPU_ANY_WIDEKL_FLAGS",
456 { "CPU_ANY_HRESET_FLAGS",
458 { "CPU_ANY_AVX512_FP16_FLAGS",
460 { "CPU_ANY_AVX_IFMA_FLAGS",
462 { "CPU_ANY_AVX_VNNI_INT8_FLAGS",
463 "CpuAVX_VNNI_INT8" },
464 { "CPU_ANY_CMPCCXADD_FLAGS",
466 { "CPU_ANY_WRMSRNS_FLAGS",
468 { "CPU_ANY_MSRLIST_FLAGS",
470 { "CPU_ANY_AVX_NE_CONVERT_FLAGS",
471 "CpuAVX_NE_CONVERT" },
472 { "CPU_ANY_RAO_INT_FLAGS",
476 static initializer operand_type_init
[] =
478 { "OPERAND_TYPE_NONE",
480 { "OPERAND_TYPE_REG8",
482 { "OPERAND_TYPE_REG16",
484 { "OPERAND_TYPE_REG32",
486 { "OPERAND_TYPE_REG64",
488 { "OPERAND_TYPE_IMM1",
490 { "OPERAND_TYPE_IMM8",
492 { "OPERAND_TYPE_IMM8S",
494 { "OPERAND_TYPE_IMM16",
496 { "OPERAND_TYPE_IMM32",
498 { "OPERAND_TYPE_IMM32S",
500 { "OPERAND_TYPE_IMM64",
502 { "OPERAND_TYPE_BASEINDEX",
504 { "OPERAND_TYPE_DISP8",
506 { "OPERAND_TYPE_DISP16",
508 { "OPERAND_TYPE_DISP32",
510 { "OPERAND_TYPE_DISP64",
512 { "OPERAND_TYPE_INOUTPORTREG",
513 "Instance=RegD|Word" },
514 { "OPERAND_TYPE_SHIFTCOUNT",
515 "Instance=RegC|Byte" },
516 { "OPERAND_TYPE_CONTROL",
518 { "OPERAND_TYPE_TEST",
520 { "OPERAND_TYPE_DEBUG",
522 { "OPERAND_TYPE_FLOATREG",
524 { "OPERAND_TYPE_FLOATACC",
525 "Instance=Accum|Tbyte" },
526 { "OPERAND_TYPE_SREG",
528 { "OPERAND_TYPE_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",
540 { "OPERAND_TYPE_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",
552 { "OPERAND_TYPE_ANYDISP",
553 "Disp8|Disp16|Disp32|Disp64" },
554 { "OPERAND_TYPE_IMM16_32",
556 { "OPERAND_TYPE_IMM16_32S",
558 { "OPERAND_TYPE_IMM16_32_32S",
559 "Imm16|Imm32|Imm32S" },
560 { "OPERAND_TYPE_IMM32_64",
562 { "OPERAND_TYPE_IMM32_32S_DISP32",
563 "Imm32|Imm32S|Disp32" },
564 { "OPERAND_TYPE_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
579 #define BITFIELD(n) { n, 0, #n }
581 static bitfield cpu_flags
[] =
591 BITFIELD (CpuClflush
),
593 BITFIELD (CpuSYSCALL
),
598 BITFIELD (CpuFISTTP
),
604 BITFIELD (CpuSSE4_1
),
605 BITFIELD (CpuSSE4_2
),
608 BITFIELD (CpuAVX512F
),
609 BITFIELD (CpuAVX512CD
),
610 BITFIELD (CpuAVX512ER
),
611 BITFIELD (CpuAVX512PF
),
612 BITFIELD (CpuAVX512VL
),
613 BITFIELD (CpuAVX512DQ
),
614 BITFIELD (CpuAVX512BW
),
618 BITFIELD (Cpu3dnowA
),
619 BITFIELD (CpuPadLock
),
624 BITFIELD (CpuXsaveopt
),
626 BITFIELD (CpuPCLMUL
),
637 BITFIELD (CpuRdtscp
),
638 BITFIELD (CpuFSGSBase
),
643 BITFIELD (CpuPOPCNT
),
646 BITFIELD (CpuINVPCID
),
647 BITFIELD (CpuVMFUNC
),
648 BITFIELD (CpuRDSEED
),
650 BITFIELD (CpuPRFCHW
),
653 BITFIELD (CpuClflushOpt
),
654 BITFIELD (CpuXSAVES
),
655 BITFIELD (CpuXSAVEC
),
656 BITFIELD (CpuPREFETCHWT1
),
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
),
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
),
685 BITFIELD (CpuPTWRITE
),
690 BITFIELD (CpuVPCLMULQDQ
),
691 BITFIELD (CpuWBNOINVD
),
692 BITFIELD (CpuPCONFIG
),
693 BITFIELD (CpuWAITPKG
),
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
),
705 BITFIELD (CpuMCOMMIT
),
706 BITFIELD (CpuSEV_ES
),
707 BITFIELD (CpuTSXLDTRK
),
709 BITFIELD (CpuWideKL
),
710 BITFIELD (CpuHRESET
),
711 BITFIELD (CpuINVLPGB
),
712 BITFIELD (CpuTLBSYNC
),
717 BITFIELD (CpuUnused
),
721 static bitfield opcode_modifiers
[] =
731 BITFIELD (CheckRegSize
),
732 BITFIELD (OperandConstraint
),
733 BITFIELD (MnemonicSize
),
743 BITFIELD (BNDPrefixOk
),
751 BITFIELD (OpcodeSpace
),
752 BITFIELD (OpcodePrefix
),
753 BITFIELD (VexSources
),
758 BITFIELD (Broadcast
),
759 BITFIELD (StaticRounding
),
761 BITFIELD (Disp8MemShift
),
763 BITFIELD (ATTMnemonic
),
764 BITFIELD (ATTSyntax
),
765 BITFIELD (IntelSyntax
),
769 #define CLASS(n) #n, n
771 static const struct {
773 enum operand_class value
;
774 } operand_classes
[] = {
788 #define INSTANCE(n) #n, n
790 static const struct {
792 enum operand_instance value
;
793 } operand_instances
[] = {
802 static bitfield operand_types
[] =
811 BITFIELD (BaseIndex
),
826 BITFIELD (Unspecified
),
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
;
841 struct template_instance
{
842 const struct template_instance
*next
;
844 const struct template_arg
*args
;
847 struct template_param
{
848 const struct template_param
*next
;
853 struct template *next
;
855 const struct template_instance
*instances
;
856 const struct template_param
*params
;
859 static struct template *templates
;
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
;
870 fail (const char *message
, ...)
874 va_start (args
, message
);
875 fprintf (stderr
, _("%s: error: "), program_name
);
876 vfprintf (stderr
, message
, args
);
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. */
908 remove_leading_whitespaces (char *str
)
910 while (ISSPACE (*str
))
915 /* Remove trailing white spaces. */
918 remove_trailing_whitespaces (char *str
)
920 size_t last
= strlen (str
);
928 if (ISSPACE (str
[last
]))
936 /* Find next field separated by SEP and terminate it. Return a
937 pointer to the one after it. */
940 next_field (char *str
, char sep
, char **next
, char *last
)
944 p
= remove_leading_whitespaces (str
);
945 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
948 remove_trailing_whitespaces (p
);
958 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
961 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
964 char *str
, *next
, *last
;
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
);
977 set_bitfield (str
, array
, 1, size
, lineno
);
987 set_bitfield (char *f
, bitfield
*array
, int value
,
988 unsigned int size
, int lineno
)
992 /* Ignore empty fields; they may result from template expansions. */
996 for (i
= 0; i
< size
; i
++)
997 if (strcasecmp (array
[i
].name
, f
) == 0)
999 array
[i
].value
= value
;
1005 const char *v
= strchr (f
, '=');
1012 for (i
= 0; i
< size
; i
++)
1013 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
1015 value
= strtol (v
+ 1, &end
, 0);
1018 array
[i
].value
= value
;
1026 /* Handle CPU_XXX_FLAGS. */
1027 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1031 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1033 fail (_("unknown bitfield: %s\n"), f
);
1037 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1038 int macro
, const char *comma
, const char *indent
)
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
);
1051 fprintf (table
, "%d,", flags
[i
].value
);
1052 if (((i
+ 1) % 20) == 0)
1054 /* We need \\ for macro. */
1056 fprintf (table
, " \\\n %s", indent
);
1058 fprintf (table
, "\n %s", indent
);
1061 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1064 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1068 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1069 const char *comma
, const char *indent
,
1072 char *str
, *next
= flag
, *last
;
1075 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1077 /* Copy the default cpu flags. */
1078 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1082 last
= flag
+ strlen (flag
);
1089 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
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
)
1102 /* Turn off selective bits. */
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
);
1114 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1118 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1123 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1127 fprintf (table
, " { ");
1129 for (i
= 0; i
< size
- 1; i
++)
1131 if (((i
+ 1) % 20) != 0)
1132 fprintf (table
, "%d, ", modifier
[i
].value
);
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. */
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
)
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
);
1163 if (strcasecmp(str
, "Byte") == 0)
1165 /* The smallest element size, no need to check
1170 else if (strcasecmp(str
, "Word") == 0)
1175 else if (strcasecmp(str
, "Dword") == 0)
1180 else if (strcasecmp(str
, "Qword") == 0)
1189 if (elem_size
== INT_MAX
)
1190 fail (_("%s: %d: unknown element size: %s\n"), filename
, lineno
, full
);
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
);
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
),
1225 if (strcasecmp(str
, "IsString") == 0)
1226 active_isstring
= 1;
1228 if (strcasecmp(str
, "W") == 0)
1231 if (strcasecmp(str
, "No_bSuf") == 0)
1233 if (strcasecmp(str
, "No_wSuf") == 0)
1235 if (strcasecmp(str
, "No_lSuf") == 0)
1237 if (strcasecmp(str
, "No_qSuf") == 0)
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"),
1251 _("%s:%d: Warning: redundant opcode space specification\n"),
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"),
1264 _("%s:%d: Warning: redundant prefix specification\n"),
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",
1273 if (have_w
&& !(bwlq_suf
& ~1))
1275 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1278 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
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
)
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
);
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
);
1309 fprintf (table
, "\n%s", indent
);
1313 fprintf (table
, "%d } }", types
[i
].value
);
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"))
1332 last
= op
+ strlen (op
);
1333 for (next
= op
; next
&& next
< last
; )
1335 str
= next_field (next
, '|', &next
, last
);
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
;
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
;
1364 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1365 if (strcasecmp(str
, "BaseIndex") == 0)
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
),
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
);
1408 str
= remove_leading_whitespaces (str
+ 1);
1409 remove_trailing_whitespaces (str
);
1411 /* Remove } and trailing white space. */
1413 if (!i
|| str
[i
- 1] != '}')
1416 remove_trailing_whitespaces (str
);
1419 operand_types
[i
= 0] = NULL
;
1422 last
= str
+ strlen (str
);
1424 /* Find operand_types. */
1425 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1429 operand_types
[i
] = NULL
;
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
)))
1444 /* Transform prefixes encoded in the opcode into opcode modifier
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;
1456 opcode
&= (1ULL << (8 * --length
)) - 1;
1459 /* Transform opcode space encoded in the opcode into opcode modifier
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;
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
])
1495 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1501 fprintf (table
, ",\n ");
1503 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1506 fprintf (table
, " } },\n");
1509 struct opcode_hash_entry
1511 struct opcode_hash_entry
*next
;
1517 /* Calculate the hash value of an opcode hash entry P. */
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. */
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;
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
, ':');
1547 struct template *prev
= NULL
;
1549 end
= strchr (buf
, '>');
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
);
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
))
1561 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1563 prev
->next
= tmpl
->next
;
1565 templates
= tmpl
->next
;
1569 remove_trailing_whitespaces (buf
);
1572 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1573 tmpl
= xmalloc (sizeof (*tmpl
));
1574 tmpl
->name
= xstrdup (buf
);
1576 tmpl
->params
= NULL
;
1578 struct template_param
*param
;
1580 buf
= remove_leading_whitespaces (end
);
1581 end
= strpbrk (buf
, ":,");
1583 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
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
;
1597 struct template_instance
*inst
;
1599 const struct template_param
*param
;
1601 buf
= remove_leading_whitespaces (end
);
1602 end
= strpbrk (buf
, ",>");
1604 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1609 inst
= xmalloc (sizeof (*inst
));
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
);
1622 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1623 arg
->val
= xstrdup (cur
);
1624 arg
->next
= inst
->args
;
1628 if (tmpl
->instances
)
1629 last_inst
->next
= inst
;
1631 tmpl
->instances
= inst
;
1633 } while (sep
== ',');
1635 buf
= remove_leading_whitespaces (end
);
1637 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1638 filename
, lineno
, buf
);
1640 tmpl
->next
= templates
;
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
;
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
),
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
];
1685 /* Append it to the existing one. */
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
);
1701 const struct template *tmpl
;
1702 const struct template_instance
*inst
;
1705 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1706 remove_trailing_whitespaces (ptr1
);
1710 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1711 if (!strcmp(ptr1
, tmpl
->name
))
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
));
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
++) != '<')
1737 while (ISSPACE(*src
))
1739 while (*ident
&& *src
== *ident
)
1741 while (ISSPACE(*src
))
1743 if (*src
!= ':' || *ident
!= '\0')
1745 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1746 ptr1
+= ident
- tmpl
->name
;
1749 while (ISSPACE(*++src
))
1753 while (*end
!= '\0' && !ISSPACE(*end
) && *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
))
1768 fail ("template '%s' has no parameter '%.*s'\n",
1769 tmpl
->name
, (int)(end
- src
), src
);
1771 while (ISSPACE(*src
))
1774 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1776 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1777 ptr1
+= strlen(arg
->val
);
1783 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1795 process_i386_opcodes (FILE *table
)
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";
1809 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1810 opcode_hash_eq
, NULL
,
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. */
1819 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1822 p
= remove_leading_whitespaces (buf
);
1828 /* Skip comments. */
1829 str
= strstr (p
, "//");
1833 remove_trailing_whitespaces (p
);
1837 /* Look for line continuation character. */
1838 remove_trailing_whitespaces (p
);
1840 if (!j
|| buf
[j
- 1] != '+')
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",
1856 if (!strcmp("### MARKER ###", buf
))
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
1867 p
= remove_leading_whitespaces (p
+ 1);
1868 if (!strncmp(p
, "line", 4))
1870 ln
= strtoul (p
, &end
, 10);
1871 if (ln
> 1 && ln
< INT_MAX
1872 && *remove_leading_whitespaces (end
) == '"')
1875 /* Ignore comments. */
1880 parse_template (p
, lineno
);
1888 last
= p
+ strlen (p
);
1891 name
= next_field (p
, ',', &str
, last
);
1893 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
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
)
1906 lineno
= next
->lineno
;
1907 last
= str
+ strlen (str
);
1908 output_i386_opcode (table
, name
, str
, last
, lineno
);
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");
1928 process_i386_registers (FILE *table
)
1932 char *str
, *p
, *last
;
1933 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1934 char *dw2_32_num
, *dw2_64_num
;
1937 filename
= "i386-reg.tbl";
1938 fp
= fopen (filename
, "r");
1940 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1943 fprintf (table
, "\n/* i386 register table. */\n\n");
1944 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1948 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1953 p
= remove_leading_whitespaces (buf
);
1955 /* Skip comments. */
1956 str
= strstr (p
, "//");
1960 /* Remove trailing white spaces. */
1961 remove_trailing_whitespaces (p
);
1966 fprintf (table
, "%s\n", p
);
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
);
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",
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
);
2005 fprintf (table
, "};\n");
2007 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2011 process_i386_initializers (void)
2014 FILE *fp
= fopen ("i386-init.h", "w");
2018 fail (_("can't create i386-init.h, errno = %s\n"),
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);
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);
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}
2056 print_version (void)
2058 printf ("%s: version 1.0\n", program_name
);
2063 usage (FILE * stream
, int status
)
2065 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2071 main (int argc
, char **argv
)
2073 extern int chdir (char *);
2074 char *srcdir
= NULL
;
2076 unsigned int i
, cpumax
;
2079 program_name
= *argv
;
2080 xmalloc_set_program_name (program_name
);
2082 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
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. */
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. */
2119 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2121 if ((cpumax
- 1) != CpuMax
)
2122 fail (_("CpuMax != %d!\n"), cpumax
);
2124 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2126 if (cpumax
!= CpuMax
)
2127 fail (_("CpuMax != %d!\n"), cpumax
);
2129 c
= CpuNumOfBits
- CpuMax
- 1;
2131 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2134 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2136 /* Check the unused bitfield in i386_operand_type. */
2138 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2141 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2144 c
= OTNumOfBits
- OTNum
;
2146 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2149 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
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");
2160 fail (_("can't create i386-tbl.h, errno = %s\n"),
2163 process_copyright (table
);
2165 process_i386_opcodes (table
);
2166 process_i386_registers (table
);
2167 process_i386_initializers ();