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",
261 "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
264 { "CPU_RDSEED_FLAGS",
266 { "CPU_PRFCHW_FLAGS",
271 "CPU_XSAVE_FLAGS|CpuMPX" },
273 "CPU_SSE2_FLAGS|CpuSHA" },
274 { "CPU_CLFLUSHOPT_FLAGS",
276 { "CPU_XSAVES_FLAGS",
277 "CPU_XSAVE_FLAGS|CpuXSAVES" },
278 { "CPU_XSAVEC_FLAGS",
279 "CPU_XSAVE_FLAGS|CpuXSAVEC" },
280 { "CPU_PREFETCHWT1_FLAGS",
286 { "CPU_CLZERO_FLAGS",
288 { "CPU_MWAITX_FLAGS",
291 "CPU_XSAVE_FLAGS|CpuOSPKE" },
294 { "CPU_PTWRITE_FLAGS",
304 { "CPU_VPCLMULQDQ_FLAGS",
306 { "CPU_WBNOINVD_FLAGS",
308 { "CPU_PCONFIG_FLAGS",
310 { "CPU_WAITPKG_FLAGS",
314 { "CPU_CLDEMOTE_FLAGS",
316 { "CPU_AMX_INT8_FLAGS",
317 "CPU_AMX_TILE_FLAGS|CpuAMX_INT8" },
318 { "CPU_AMX_BF16_FLAGS",
319 "CPU_AMX_TILE_FLAGS|CpuAMX_BF16" },
320 { "CPU_AMX_FP16_FLAGS",
321 "CPU_AMX_TILE_FLAGS|CpuAMX_FP16" },
322 { "CPU_AMX_TILE_FLAGS",
324 { "CPU_MOVDIRI_FLAGS",
326 { "CPU_MOVDIR64B_FLAGS",
328 { "CPU_ENQCMD_FLAGS",
330 { "CPU_SERIALIZE_FLAGS",
332 { "CPU_AVX512_VP2INTERSECT_FLAGS",
333 "CpuAVX512_VP2INTERSECT" },
338 { "CPU_MCOMMIT_FLAGS",
340 { "CPU_SEV_ES_FLAGS",
342 { "CPU_TSXLDTRK_FLAGS",
346 { "CPU_WIDEKL_FLAGS",
348 { "CPU_HRESET_FLAGS",
350 { "CPU_INVLPGB_FLAGS",
352 { "CPU_TLBSYNC_FLAGS",
356 { "CPU_ANY_X87_FLAGS",
357 "CPU_ANY_287_FLAGS|Cpu8087" },
358 { "CPU_ANY_287_FLAGS",
359 "CPU_ANY_387_FLAGS|Cpu287" },
360 { "CPU_ANY_387_FLAGS",
361 "CPU_ANY_687_FLAGS|Cpu387" },
362 { "CPU_ANY_687_FLAGS",
363 "Cpu687|CpuFISTTP" },
364 { "CPU_ANY_CMOV_FLAGS",
366 { "CPU_ANY_FXSR_FLAGS",
368 { "CPU_ANY_MMX_FLAGS",
369 "CPU_3DNOWA_FLAGS" },
370 { "CPU_ANY_SSE_FLAGS",
371 "CPU_ANY_SSE2_FLAGS|CpuSSE" },
372 { "CPU_ANY_SSE2_FLAGS",
373 "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
374 { "CPU_ANY_SSE3_FLAGS",
375 "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
376 { "CPU_ANY_SSSE3_FLAGS",
377 "CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
378 { "CPU_ANY_SSE4_1_FLAGS",
379 "CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
380 { "CPU_ANY_SSE4_2_FLAGS",
382 { "CPU_ANY_SSE4A_FLAGS",
384 { "CPU_ANY_AVX_FLAGS",
385 "CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
386 { "CPU_ANY_AVX2_FLAGS",
387 "CPU_ANY_AVX512F_FLAGS|CpuAVX2|CpuAVX_VNNI|CpuAVX_IFMA|CpuAVX_VNNI_INT8" },
388 { "CPU_ANY_AVX512F_FLAGS",
389 "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" },
390 { "CPU_ANY_AVX512CD_FLAGS",
392 { "CPU_ANY_AVX512ER_FLAGS",
394 { "CPU_ANY_AVX512PF_FLAGS",
396 { "CPU_ANY_AVX512DQ_FLAGS",
398 { "CPU_ANY_AVX512BW_FLAGS",
399 "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
400 { "CPU_ANY_AVX512VL_FLAGS",
402 { "CPU_ANY_AVX512IFMA_FLAGS",
404 { "CPU_ANY_AVX512VBMI_FLAGS",
406 { "CPU_ANY_AVX512_4FMAPS_FLAGS",
407 "CpuAVX512_4FMAPS" },
408 { "CPU_ANY_AVX512_4VNNIW_FLAGS",
409 "CpuAVX512_4VNNIW" },
410 { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
411 "CpuAVX512_VPOPCNTDQ" },
412 { "CPU_ANY_IBT_FLAGS",
414 { "CPU_ANY_SHSTK_FLAGS",
416 { "CPU_ANY_AVX512_VBMI2_FLAGS",
418 { "CPU_ANY_AVX512_VNNI_FLAGS",
420 { "CPU_ANY_AVX512_BITALG_FLAGS",
421 "CpuAVX512_BITALG" },
422 { "CPU_ANY_AVX512_BF16_FLAGS",
424 { "CPU_ANY_AMX_INT8_FLAGS",
426 { "CPU_ANY_AMX_BF16_FLAGS",
428 { "CPU_ANY_AMX_TILE_FLAGS",
429 "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16|CpuAMX_FP16" },
430 { "CPU_ANY_AVX_VNNI_FLAGS",
432 { "CPU_ANY_MOVDIRI_FLAGS",
434 { "CPU_ANY_UINTR_FLAGS",
436 { "CPU_ANY_MOVDIR64B_FLAGS",
438 { "CPU_ANY_ENQCMD_FLAGS",
440 { "CPU_ANY_SERIALIZE_FLAGS",
442 { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
443 "CpuAVX512_VP2INTERSECT" },
444 { "CPU_ANY_TDX_FLAGS",
446 { "CPU_ANY_TSXLDTRK_FLAGS",
448 { "CPU_ANY_KL_FLAGS",
450 { "CPU_ANY_WIDEKL_FLAGS",
452 { "CPU_ANY_HRESET_FLAGS",
454 { "CPU_ANY_AVX512_FP16_FLAGS",
456 { "CPU_ANY_AVX_IFMA_FLAGS",
458 { "CPU_ANY_AVX_VNNI_INT8_FLAGS",
459 "CpuAVX_VNNI_INT8" },
460 { "CPU_ANY_CMPCCXADD_FLAGS",
462 { "CPU_ANY_WRMSRNS_FLAGS",
464 { "CPU_ANY_MSRLIST_FLAGS",
468 static initializer operand_type_init
[] =
470 { "OPERAND_TYPE_NONE",
472 { "OPERAND_TYPE_REG8",
474 { "OPERAND_TYPE_REG16",
476 { "OPERAND_TYPE_REG32",
478 { "OPERAND_TYPE_REG64",
480 { "OPERAND_TYPE_IMM1",
482 { "OPERAND_TYPE_IMM8",
484 { "OPERAND_TYPE_IMM8S",
486 { "OPERAND_TYPE_IMM16",
488 { "OPERAND_TYPE_IMM32",
490 { "OPERAND_TYPE_IMM32S",
492 { "OPERAND_TYPE_IMM64",
494 { "OPERAND_TYPE_BASEINDEX",
496 { "OPERAND_TYPE_DISP8",
498 { "OPERAND_TYPE_DISP16",
500 { "OPERAND_TYPE_DISP32",
502 { "OPERAND_TYPE_DISP64",
504 { "OPERAND_TYPE_INOUTPORTREG",
505 "Instance=RegD|Word" },
506 { "OPERAND_TYPE_SHIFTCOUNT",
507 "Instance=RegC|Byte" },
508 { "OPERAND_TYPE_CONTROL",
510 { "OPERAND_TYPE_TEST",
512 { "OPERAND_TYPE_DEBUG",
514 { "OPERAND_TYPE_FLOATREG",
516 { "OPERAND_TYPE_FLOATACC",
517 "Instance=Accum|Tbyte" },
518 { "OPERAND_TYPE_SREG",
520 { "OPERAND_TYPE_REGMMX",
522 { "OPERAND_TYPE_REGXMM",
523 "Class=RegSIMD|Xmmword" },
524 { "OPERAND_TYPE_REGYMM",
525 "Class=RegSIMD|Ymmword" },
526 { "OPERAND_TYPE_REGZMM",
527 "Class=RegSIMD|Zmmword" },
528 { "OPERAND_TYPE_REGTMM",
529 "Class=RegSIMD|Tmmword" },
530 { "OPERAND_TYPE_REGMASK",
532 { "OPERAND_TYPE_REGBND",
534 { "OPERAND_TYPE_ACC8",
535 "Instance=Accum|Byte" },
536 { "OPERAND_TYPE_ACC16",
537 "Instance=Accum|Word" },
538 { "OPERAND_TYPE_ACC32",
539 "Instance=Accum|Dword" },
540 { "OPERAND_TYPE_ACC64",
541 "Instance=Accum|Qword" },
542 { "OPERAND_TYPE_DISP16_32",
544 { "OPERAND_TYPE_ANYDISP",
545 "Disp8|Disp16|Disp32|Disp64" },
546 { "OPERAND_TYPE_IMM16_32",
548 { "OPERAND_TYPE_IMM16_32S",
550 { "OPERAND_TYPE_IMM16_32_32S",
551 "Imm16|Imm32|Imm32S" },
552 { "OPERAND_TYPE_IMM32_64",
554 { "OPERAND_TYPE_IMM32_32S_DISP32",
555 "Imm32|Imm32S|Disp32" },
556 { "OPERAND_TYPE_IMM64_DISP64",
558 { "OPERAND_TYPE_IMM32_32S_64_DISP32",
559 "Imm32|Imm32S|Imm64|Disp32" },
560 { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
561 "Imm32|Imm32S|Imm64|Disp32|Disp64" },
564 typedef struct bitfield
571 #define BITFIELD(n) { n, 0, #n }
573 static bitfield cpu_flags
[] =
583 BITFIELD (CpuClflush
),
585 BITFIELD (CpuSYSCALL
),
590 BITFIELD (CpuFISTTP
),
596 BITFIELD (CpuSSE4_1
),
597 BITFIELD (CpuSSE4_2
),
600 BITFIELD (CpuAVX512F
),
601 BITFIELD (CpuAVX512CD
),
602 BITFIELD (CpuAVX512ER
),
603 BITFIELD (CpuAVX512PF
),
604 BITFIELD (CpuAVX512VL
),
605 BITFIELD (CpuAVX512DQ
),
606 BITFIELD (CpuAVX512BW
),
610 BITFIELD (Cpu3dnowA
),
611 BITFIELD (CpuPadLock
),
616 BITFIELD (CpuXsaveopt
),
618 BITFIELD (CpuPCLMUL
),
629 BITFIELD (CpuRdtscp
),
630 BITFIELD (CpuFSGSBase
),
635 BITFIELD (CpuPOPCNT
),
638 BITFIELD (CpuINVPCID
),
639 BITFIELD (CpuVMFUNC
),
640 BITFIELD (CpuRDSEED
),
642 BITFIELD (CpuPRFCHW
),
645 BITFIELD (CpuClflushOpt
),
646 BITFIELD (CpuXSAVES
),
647 BITFIELD (CpuXSAVEC
),
648 BITFIELD (CpuPREFETCHWT1
),
652 BITFIELD (CpuAVX512IFMA
),
653 BITFIELD (CpuAVX512VBMI
),
654 BITFIELD (CpuAVX512_4FMAPS
),
655 BITFIELD (CpuAVX512_4VNNIW
),
656 BITFIELD (CpuAVX512_VPOPCNTDQ
),
657 BITFIELD (CpuAVX512_VBMI2
),
658 BITFIELD (CpuAVX512_VNNI
),
659 BITFIELD (CpuAVX512_BITALG
),
660 BITFIELD (CpuAVX512_BF16
),
661 BITFIELD (CpuAVX512_VP2INTERSECT
),
663 BITFIELD (CpuAVX_VNNI
),
664 BITFIELD (CpuAVX512_FP16
),
665 BITFIELD (CpuPREFETCHI
),
666 BITFIELD (CpuAVX_IFMA
),
667 BITFIELD (CpuAVX_VNNI_INT8
),
668 BITFIELD (CpuCMPCCXADD
),
669 BITFIELD (CpuWRMSRNS
),
670 BITFIELD (CpuMSRLIST
),
671 BITFIELD (CpuMWAITX
),
672 BITFIELD (CpuCLZERO
),
675 BITFIELD (CpuPTWRITE
),
680 BITFIELD (CpuVPCLMULQDQ
),
681 BITFIELD (CpuWBNOINVD
),
682 BITFIELD (CpuPCONFIG
),
683 BITFIELD (CpuWAITPKG
),
685 BITFIELD (CpuCLDEMOTE
),
686 BITFIELD (CpuAMX_INT8
),
687 BITFIELD (CpuAMX_BF16
),
688 BITFIELD (CpuAMX_FP16
),
689 BITFIELD (CpuAMX_TILE
),
690 BITFIELD (CpuMOVDIRI
),
691 BITFIELD (CpuMOVDIR64B
),
692 BITFIELD (CpuENQCMD
),
693 BITFIELD (CpuSERIALIZE
),
695 BITFIELD (CpuMCOMMIT
),
696 BITFIELD (CpuSEV_ES
),
697 BITFIELD (CpuTSXLDTRK
),
699 BITFIELD (CpuWideKL
),
700 BITFIELD (CpuHRESET
),
701 BITFIELD (CpuINVLPGB
),
702 BITFIELD (CpuTLBSYNC
),
707 BITFIELD (CpuUnused
),
711 static bitfield opcode_modifiers
[] =
721 BITFIELD (CheckRegSize
),
722 BITFIELD (DistinctDest
),
723 BITFIELD (MnemonicSize
),
734 BITFIELD (BNDPrefixOk
),
735 BITFIELD (RegKludge
),
736 BITFIELD (Implicit1stXmm0
),
738 BITFIELD (AddrPrefixOpReg
),
746 BITFIELD (OpcodeSpace
),
747 BITFIELD (OpcodePrefix
),
748 BITFIELD (VexSources
),
753 BITFIELD (Broadcast
),
754 BITFIELD (StaticRounding
),
756 BITFIELD (Disp8MemShift
),
757 BITFIELD (NoDefMask
),
758 BITFIELD (ImplicitQuadGroup
),
759 BITFIELD (SwapSources
),
761 BITFIELD (ATTMnemonic
),
762 BITFIELD (ATTSyntax
),
763 BITFIELD (IntelSyntax
),
767 #define CLASS(n) #n, n
769 static const struct {
771 enum operand_class value
;
772 } operand_classes
[] = {
786 #define INSTANCE(n) #n, n
788 static const struct {
790 enum operand_instance value
;
791 } operand_instances
[] = {
800 static bitfield operand_types
[] =
809 BITFIELD (BaseIndex
),
824 BITFIELD (Unspecified
),
830 static const char *filename
;
831 static i386_cpu_flags active_cpu_flags
;
832 static int active_isstring
;
834 struct template_arg
{
835 const struct template_arg
*next
;
839 struct template_instance
{
840 const struct template_instance
*next
;
842 const struct template_arg
*args
;
845 struct template_param
{
846 const struct template_param
*next
;
851 struct template *next
;
853 const struct template_instance
*instances
;
854 const struct template_param
*params
;
857 static struct template *templates
;
860 compare (const void *x
, const void *y
)
862 const bitfield
*xp
= (const bitfield
*) x
;
863 const bitfield
*yp
= (const bitfield
*) y
;
864 return xp
->position
- yp
->position
;
868 fail (const char *message
, ...)
872 va_start (args
, message
);
873 fprintf (stderr
, _("%s: error: "), program_name
);
874 vfprintf (stderr
, message
, args
);
880 process_copyright (FILE *fp
)
882 fprintf (fp
, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
883 /* Copyright (C) 2007-2022 Free Software Foundation, Inc.\n\
885 This file is part of the GNU opcodes library.\n\
887 This library is free software; you can redistribute it and/or modify\n\
888 it under the terms of the GNU General Public License as published by\n\
889 the Free Software Foundation; either version 3, or (at your option)\n\
890 any later version.\n\
892 It is distributed in the hope that it will be useful, but WITHOUT\n\
893 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
894 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
895 License for more details.\n\
897 You should have received a copy of the GNU General Public License\n\
898 along with this program; if not, write to the Free Software\n\
899 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
900 MA 02110-1301, USA. */\n");
903 /* Remove leading white spaces. */
906 remove_leading_whitespaces (char *str
)
908 while (ISSPACE (*str
))
913 /* Remove trailing white spaces. */
916 remove_trailing_whitespaces (char *str
)
918 size_t last
= strlen (str
);
926 if (ISSPACE (str
[last
]))
934 /* Find next field separated by SEP and terminate it. Return a
935 pointer to the one after it. */
938 next_field (char *str
, char sep
, char **next
, char *last
)
942 p
= remove_leading_whitespaces (str
);
943 for (str
= p
; *str
!= sep
&& *str
!= '\0'; str
++);
946 remove_trailing_whitespaces (p
);
956 static void set_bitfield (char *, bitfield
*, int, unsigned int, int);
959 set_bitfield_from_cpu_flag_init (char *f
, bitfield
*array
, unsigned int size
,
962 char *str
, *next
, *last
;
965 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
966 if (strcmp (cpu_flag_init
[i
].name
, f
) == 0)
968 /* Turn on selective bits. */
969 char *init
= xstrdup (cpu_flag_init
[i
].init
);
970 last
= init
+ strlen (init
);
971 for (next
= init
; next
&& next
< last
; )
973 str
= next_field (next
, '|', &next
, last
);
975 set_bitfield (str
, array
, 1, size
, lineno
);
985 set_bitfield (char *f
, bitfield
*array
, int value
,
986 unsigned int size
, int lineno
)
990 /* Ignore empty fields; they may result from template expansions. */
994 for (i
= 0; i
< size
; i
++)
995 if (strcasecmp (array
[i
].name
, f
) == 0)
997 array
[i
].value
= value
;
1003 const char *v
= strchr (f
, '=');
1010 for (i
= 0; i
< size
; i
++)
1011 if (strncasecmp (array
[i
].name
, f
, n
) == 0)
1013 value
= strtol (v
+ 1, &end
, 0);
1016 array
[i
].value
= value
;
1024 /* Handle CPU_XXX_FLAGS. */
1025 if (value
== 1 && !set_bitfield_from_cpu_flag_init (f
, array
, size
, lineno
))
1029 fail (_("%s: %d: unknown bitfield: %s\n"), filename
, lineno
, f
);
1031 fail (_("unknown bitfield: %s\n"), f
);
1035 output_cpu_flags (FILE *table
, bitfield
*flags
, unsigned int size
,
1036 int macro
, const char *comma
, const char *indent
)
1040 memset (&active_cpu_flags
, 0, sizeof(active_cpu_flags
));
1042 fprintf (table
, "%s{ { ", indent
);
1044 for (i
= 0; i
< size
- 1; i
++)
1046 if (((i
+ 1) % 20) != 0)
1047 fprintf (table
, "%d, ", flags
[i
].value
);
1049 fprintf (table
, "%d,", flags
[i
].value
);
1050 if (((i
+ 1) % 20) == 0)
1052 /* We need \\ for macro. */
1054 fprintf (table
, " \\\n %s", indent
);
1056 fprintf (table
, "\n %s", indent
);
1059 active_cpu_flags
.array
[i
/ 32] |= 1U << (i
% 32);
1062 fprintf (table
, "%d } }%s\n", flags
[i
].value
, comma
);
1066 process_i386_cpu_flag (FILE *table
, char *flag
, int macro
,
1067 const char *comma
, const char *indent
,
1070 char *str
, *next
= flag
, *last
;
1073 bitfield flags
[ARRAY_SIZE (cpu_flags
)];
1075 /* Copy the default cpu flags. */
1076 memcpy (flags
, cpu_flags
, sizeof (cpu_flags
));
1080 last
= flag
+ strlen (flag
);
1087 fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename
,
1094 /* First we turn on everything except for cpu64, cpuno64, and - if
1095 present - the padding field. */
1096 for (i
= 0; i
< ARRAY_SIZE (flags
); i
++)
1097 if (flags
[i
].position
< Cpu64
)
1100 /* Turn off selective bits. */
1104 if (strcmp (flag
, "0"))
1106 /* Turn on/off selective bits. */
1107 last
= flag
+ strlen (flag
);
1108 for (; next
&& next
< last
; )
1110 str
= next_field (next
, '|', &next
, last
);
1112 set_bitfield (str
, flags
, value
, ARRAY_SIZE (flags
), lineno
);
1116 output_cpu_flags (table
, flags
, ARRAY_SIZE (flags
), macro
,
1121 output_opcode_modifier (FILE *table
, bitfield
*modifier
, unsigned int size
)
1125 fprintf (table
, " { ");
1127 for (i
= 0; i
< size
- 1; i
++)
1129 if (((i
+ 1) % 20) != 0)
1130 fprintf (table
, "%d, ", modifier
[i
].value
);
1132 fprintf (table
, "%d,", modifier
[i
].value
);
1133 if (((i
+ 1) % 20) == 0)
1134 fprintf (table
, "\n ");
1137 fprintf (table
, "%d },\n", modifier
[i
].value
);
1140 /* Returns LOG2 of element size. */
1142 get_element_size (char **opnd
, int lineno
)
1144 char *str
, *next
, *last
, *op
;
1145 const char *full
= opnd
[0];
1146 int elem_size
= INT_MAX
;
1148 /* Find the memory operand. */
1149 while (full
!= NULL
&& strstr(full
, "BaseIndex") == NULL
)
1152 fail (_("%s: %d: no memory operand\n"), filename
, lineno
);
1154 op
= xstrdup (full
);
1155 last
= op
+ strlen (op
);
1156 for (next
= op
; next
&& next
< last
; )
1158 str
= next_field (next
, '|', &next
, last
);
1161 if (strcasecmp(str
, "Byte") == 0)
1163 /* The smallest element size, no need to check
1168 else if (strcasecmp(str
, "Word") == 0)
1173 else if (strcasecmp(str
, "Dword") == 0)
1178 else if (strcasecmp(str
, "Qword") == 0)
1187 if (elem_size
== INT_MAX
)
1188 fail (_("%s: %d: unknown element size: %s\n"), filename
, lineno
, full
);
1194 process_i386_opcode_modifier (FILE *table
, char *mod
, unsigned int space
,
1195 unsigned int prefix
, char **opnd
, int lineno
)
1197 char *str
, *next
, *last
;
1198 bitfield modifiers
[ARRAY_SIZE (opcode_modifiers
)];
1200 active_isstring
= 0;
1202 /* Copy the default opcode modifier. */
1203 memcpy (modifiers
, opcode_modifiers
, sizeof (modifiers
));
1205 if (strcmp (mod
, "0"))
1207 unsigned int have_w
= 0, bwlq_suf
= 0xf;
1209 last
= mod
+ strlen (mod
);
1210 for (next
= mod
; next
&& next
< last
; )
1212 str
= next_field (next
, '|', &next
, last
);
1216 if (strcasecmp(str
, "Broadcast") == 0)
1217 val
= get_element_size (opnd
, lineno
) + BYTE_BROADCAST
;
1218 else if (strcasecmp(str
, "Disp8MemShift") == 0)
1219 val
= get_element_size (opnd
, lineno
);
1221 set_bitfield (str
, modifiers
, val
, ARRAY_SIZE (modifiers
),
1223 if (strcasecmp(str
, "IsString") == 0)
1224 active_isstring
= 1;
1226 if (strcasecmp(str
, "W") == 0)
1229 if (strcasecmp(str
, "No_bSuf") == 0)
1231 if (strcasecmp(str
, "No_wSuf") == 0)
1233 if (strcasecmp(str
, "No_lSuf") == 0)
1235 if (strcasecmp(str
, "No_qSuf") == 0)
1242 if (!modifiers
[OpcodeSpace
].value
)
1243 modifiers
[OpcodeSpace
].value
= space
;
1244 else if (modifiers
[OpcodeSpace
].value
!= space
)
1245 fail (_("%s:%d: Conflicting opcode space specifications\n"),
1249 _("%s:%d: Warning: redundant opcode space specification\n"),
1255 if (!modifiers
[OpcodePrefix
].value
)
1256 modifiers
[OpcodePrefix
].value
= prefix
;
1257 else if (modifiers
[OpcodePrefix
].value
!= prefix
)
1258 fail (_("%s:%d: Conflicting prefix specifications\n"),
1262 _("%s:%d: Warning: redundant prefix specification\n"),
1266 if (have_w
&& !bwlq_suf
)
1267 fail ("%s: %d: stray W modifier\n", filename
, lineno
);
1268 if (have_w
&& !(bwlq_suf
& 1))
1269 fprintf (stderr
, "%s: %d: W modifier without Byte operand(s)\n",
1271 if (have_w
&& !(bwlq_suf
& ~1))
1273 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
1276 output_opcode_modifier (table
, modifiers
, ARRAY_SIZE (modifiers
));
1286 output_operand_type (FILE *table
, enum operand_class
class,
1287 enum operand_instance instance
,
1288 const bitfield
*types
, unsigned int size
,
1289 enum stage stage
, const char *indent
)
1293 fprintf (table
, "{ { %d, %d, ", class, instance
);
1295 for (i
= 0; i
< size
- 1; i
++)
1297 if (((i
+ 3) % 20) != 0)
1298 fprintf (table
, "%d, ", types
[i
].value
);
1300 fprintf (table
, "%d,", types
[i
].value
);
1301 if (((i
+ 3) % 20) == 0)
1303 /* We need \\ for macro. */
1304 if (stage
== stage_macros
)
1305 fprintf (table
, " \\\n%s", indent
);
1307 fprintf (table
, "\n%s", indent
);
1311 fprintf (table
, "%d } }", types
[i
].value
);
1315 process_i386_operand_type (FILE *table
, char *op
, enum stage stage
,
1316 const char *indent
, int lineno
)
1318 char *str
, *next
, *last
;
1319 enum operand_class
class = ClassNone
;
1320 enum operand_instance instance
= InstanceNone
;
1321 bitfield types
[ARRAY_SIZE (operand_types
)];
1323 /* Copy the default operand type. */
1324 memcpy (types
, operand_types
, sizeof (types
));
1326 if (strcmp (op
, "0"))
1330 last
= op
+ strlen (op
);
1331 for (next
= op
; next
&& next
< last
; )
1333 str
= next_field (next
, '|', &next
, last
);
1338 if (!strncmp(str
, "Class=", 6))
1340 for (i
= 0; i
< ARRAY_SIZE(operand_classes
); ++i
)
1341 if (!strcmp(str
+ 6, operand_classes
[i
].name
))
1343 class = operand_classes
[i
].value
;
1349 if (str
&& !strncmp(str
, "Instance=", 9))
1351 for (i
= 0; i
< ARRAY_SIZE(operand_instances
); ++i
)
1352 if (!strcmp(str
+ 9, operand_instances
[i
].name
))
1354 instance
= operand_instances
[i
].value
;
1362 set_bitfield (str
, types
, 1, ARRAY_SIZE (types
), lineno
);
1363 if (strcasecmp(str
, "BaseIndex") == 0)
1368 if (stage
== stage_opcodes
&& baseindex
&& !active_isstring
)
1370 set_bitfield("Disp8", types
, 1, ARRAY_SIZE (types
), lineno
);
1371 if (!active_cpu_flags
.bitfield
.cpu64
1372 && !active_cpu_flags
.bitfield
.cpumpx
)
1373 set_bitfield("Disp16", types
, 1, ARRAY_SIZE (types
), lineno
);
1374 set_bitfield("Disp32", types
, 1, ARRAY_SIZE (types
), lineno
);
1377 output_operand_type (table
, class, instance
, types
, ARRAY_SIZE (types
),
1382 output_i386_opcode (FILE *table
, const char *name
, char *str
,
1383 char *last
, int lineno
)
1385 unsigned int i
, length
, prefix
= 0, space
= 0;
1386 char *base_opcode
, *extension_opcode
, *end
;
1387 char *cpu_flags
, *opcode_modifier
, *operand_types
[MAX_OPERANDS
];
1388 unsigned long long opcode
;
1390 /* Find base_opcode. */
1391 base_opcode
= next_field (str
, ',', &str
, last
);
1393 /* Find extension_opcode. */
1394 extension_opcode
= next_field (str
, ',', &str
, last
);
1396 /* Find cpu_flags. */
1397 cpu_flags
= next_field (str
, ',', &str
, last
);
1399 /* Find opcode_modifier. */
1400 opcode_modifier
= next_field (str
, ',', &str
, last
);
1402 /* Remove the first {. */
1403 str
= remove_leading_whitespaces (str
);
1406 str
= remove_leading_whitespaces (str
+ 1);
1407 remove_trailing_whitespaces (str
);
1409 /* Remove } and trailing white space. */
1411 if (!i
|| str
[i
- 1] != '}')
1414 remove_trailing_whitespaces (str
);
1417 operand_types
[i
= 0] = NULL
;
1420 last
= str
+ strlen (str
);
1422 /* Find operand_types. */
1423 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1427 operand_types
[i
] = NULL
;
1431 operand_types
[i
] = next_field (str
, ',', &str
, last
);
1435 opcode
= strtoull (base_opcode
, &end
, 0);
1437 /* Determine opcode length. */
1438 for (length
= 1; length
< 8; ++length
)
1439 if (!(opcode
>> (8 * length
)))
1442 /* Transform prefixes encoded in the opcode into opcode modifier
1446 switch (opcode
>> (8 * length
- 8))
1448 case 0x66: prefix
= PREFIX_0X66
; break;
1449 case 0xF3: prefix
= PREFIX_0XF3
; break;
1450 case 0xF2: prefix
= PREFIX_0XF2
; break;
1454 opcode
&= (1ULL << (8 * --length
)) - 1;
1457 /* Transform opcode space encoded in the opcode into opcode modifier
1459 if (length
> 1 && (opcode
>> (8 * length
- 8)) == 0xf)
1461 switch ((opcode
>> (8 * length
- 16)) & 0xff)
1463 default: space
= SPACE_0F
; break;
1464 case 0x38: space
= SPACE_0F38
; break;
1465 case 0x3A: space
= SPACE_0F3A
; break;
1468 if (space
!= SPACE_0F
&& --length
== 1)
1469 fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
1470 filename
, lineno
, name
);
1471 opcode
&= (1ULL << (8 * --length
)) - 1;
1475 fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
1476 filename
, lineno
, name
, 2 * length
, opcode
);
1478 fprintf (table
, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
1479 name
, 2 * (int)length
, opcode
, end
, i
, extension_opcode
);
1481 process_i386_opcode_modifier (table
, opcode_modifier
, space
, prefix
,
1482 operand_types
, lineno
);
1484 process_i386_cpu_flag (table
, cpu_flags
, 0, ",", " ", lineno
);
1486 fprintf (table
, " { ");
1488 for (i
= 0; i
< ARRAY_SIZE (operand_types
); i
++)
1490 if (!operand_types
[i
])
1493 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ",
1499 fprintf (table
, ",\n ");
1501 process_i386_operand_type (table
, operand_types
[i
], stage_opcodes
,
1504 fprintf (table
, " } },\n");
1507 struct opcode_hash_entry
1509 struct opcode_hash_entry
*next
;
1515 /* Calculate the hash value of an opcode hash entry P. */
1518 opcode_hash_hash (const void *p
)
1520 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1521 return htab_hash_string (entry
->name
);
1524 /* Compare a string Q against an opcode hash entry P. */
1527 opcode_hash_eq (const void *p
, const void *q
)
1529 struct opcode_hash_entry
*entry
= (struct opcode_hash_entry
*) p
;
1530 const char *name
= (const char *) q
;
1531 return strcmp (name
, entry
->name
) == 0;
1535 parse_template (char *buf
, int lineno
)
1537 char sep
, *end
, *name
;
1538 struct template *tmpl
;
1539 struct template_instance
*last_inst
= NULL
;
1541 buf
= remove_leading_whitespaces (buf
+ 1);
1542 end
= strchr (buf
, ':');
1545 struct template *prev
= NULL
;
1547 end
= strchr (buf
, '>');
1549 fail ("%s: %d: missing ':' or '>'\n", filename
, lineno
);
1550 if (*remove_leading_whitespaces (end
+ 1))
1551 fail ("%s: %d: malformed template purge\n", filename
, lineno
);
1553 remove_trailing_whitespaces (buf
);
1554 /* Don't bother freeing the various structures. */
1555 for (tmpl
= templates
; tmpl
!= NULL
; tmpl
= (prev
= tmpl
)->next
)
1556 if (!strcmp (buf
, tmpl
->name
))
1559 fail ("%s: %d: no template '%s'\n", filename
, lineno
, buf
);
1561 prev
->next
= tmpl
->next
;
1563 templates
= tmpl
->next
;
1567 remove_trailing_whitespaces (buf
);
1570 fail ("%s: %d: missing template identifier\n", filename
, lineno
);
1571 tmpl
= xmalloc (sizeof (*tmpl
));
1572 tmpl
->name
= xstrdup (buf
);
1574 tmpl
->params
= NULL
;
1576 struct template_param
*param
;
1578 buf
= remove_leading_whitespaces (end
);
1579 end
= strpbrk (buf
, ":,");
1581 fail ("%s: %d: missing ':' or ','\n", filename
, lineno
);
1585 remove_trailing_whitespaces (buf
);
1587 param
= xmalloc (sizeof (*param
));
1588 param
->name
= xstrdup (buf
);
1589 param
->next
= tmpl
->params
;
1590 tmpl
->params
= param
;
1591 } while (sep
== ':');
1593 tmpl
->instances
= NULL
;
1595 struct template_instance
*inst
;
1597 const struct template_param
*param
;
1599 buf
= remove_leading_whitespaces (end
);
1600 end
= strpbrk (buf
, ",>");
1602 fail ("%s: %d: missing ',' or '>'\n", filename
, lineno
);
1607 inst
= xmalloc (sizeof (*inst
));
1611 cur
= next_field (buf
, ':', &next
, end
);
1612 inst
->name
= *cur
!= '$' ? xstrdup (cur
) : "";
1614 for (param
= tmpl
->params
; param
; param
= param
->next
)
1616 struct template_arg
*arg
= xmalloc (sizeof (*arg
));
1618 cur
= next_field (next
, ':', &next
, end
);
1620 fail ("%s: %d: missing argument for '%s'\n", filename
, lineno
, param
->name
);
1621 arg
->val
= xstrdup (cur
);
1622 arg
->next
= inst
->args
;
1626 if (tmpl
->instances
)
1627 last_inst
->next
= inst
;
1629 tmpl
->instances
= inst
;
1631 } while (sep
== ',');
1633 buf
= remove_leading_whitespaces (end
);
1635 fprintf(stderr
, "%s: %d: excess characters '%s'\n",
1636 filename
, lineno
, buf
);
1638 tmpl
->next
= templates
;
1643 expand_templates (char *name
, const char *str
, htab_t opcode_hash_table
,
1644 struct opcode_hash_entry
***opcode_array_p
, int lineno
)
1646 static unsigned int idx
, opcode_array_size
;
1647 struct opcode_hash_entry
**opcode_array
= *opcode_array_p
;
1648 struct opcode_hash_entry
**hash_slot
, **entry
;
1649 char *ptr1
= strchr(name
, '<'), *ptr2
;
1653 /* Get the slot in hash table. */
1654 hash_slot
= (struct opcode_hash_entry
**)
1655 htab_find_slot_with_hash (opcode_hash_table
, name
,
1656 htab_hash_string (name
),
1659 if (*hash_slot
== NULL
)
1661 /* It is the new one. Put it on opcode array. */
1662 if (idx
>= opcode_array_size
)
1664 /* Grow the opcode array when needed. */
1665 opcode_array_size
+= 1024;
1666 opcode_array
= (struct opcode_hash_entry
**)
1667 xrealloc (opcode_array
,
1668 sizeof (*opcode_array
) * opcode_array_size
);
1669 *opcode_array_p
= opcode_array
;
1672 opcode_array
[idx
] = (struct opcode_hash_entry
*)
1673 xmalloc (sizeof (struct opcode_hash_entry
));
1674 opcode_array
[idx
]->next
= NULL
;
1675 opcode_array
[idx
]->name
= xstrdup (name
);
1676 opcode_array
[idx
]->opcode
= xstrdup (str
);
1677 opcode_array
[idx
]->lineno
= lineno
;
1678 *hash_slot
= opcode_array
[idx
];
1683 /* Append it to the existing one. */
1685 while ((*entry
) != NULL
)
1686 entry
= &(*entry
)->next
;
1687 *entry
= (struct opcode_hash_entry
*)
1688 xmalloc (sizeof (struct opcode_hash_entry
));
1689 (*entry
)->next
= NULL
;
1690 (*entry
)->name
= (*hash_slot
)->name
;
1691 (*entry
)->opcode
= xstrdup (str
);
1692 (*entry
)->lineno
= lineno
;
1695 else if ((ptr2
= strchr(ptr1
+ 1, '>')) == NULL
)
1696 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1699 const struct template *tmpl
;
1700 const struct template_instance
*inst
;
1703 ptr1
= remove_leading_whitespaces (ptr1
+ 1);
1704 remove_trailing_whitespaces (ptr1
);
1708 for ( tmpl
= templates
; tmpl
; tmpl
= tmpl
->next
)
1709 if (!strcmp(ptr1
, tmpl
->name
))
1712 fail ("reference to unknown template '%s'\n", ptr1
);
1714 for (inst
= tmpl
->instances
; inst
; inst
= inst
->next
)
1716 char *name2
= xmalloc(strlen(name
) + strlen(inst
->name
) + strlen(ptr2
) + 1);
1717 char *str2
= xmalloc(2 * strlen(str
));
1720 strcpy (name2
, name
);
1721 strcat (name2
, inst
->name
);
1722 strcat (name2
, ptr2
);
1724 for (ptr1
= str2
, src
= str
; *src
; )
1726 const char *ident
= tmpl
->name
, *end
;
1727 const struct template_param
*param
;
1728 const struct template_arg
*arg
;
1730 if ((*ptr1
= *src
++) != '<')
1735 while (ISSPACE(*src
))
1737 while (*ident
&& *src
== *ident
)
1739 while (ISSPACE(*src
))
1741 if (*src
!= ':' || *ident
!= '\0')
1743 memcpy (++ptr1
, tmpl
->name
, ident
- tmpl
->name
);
1744 ptr1
+= ident
- tmpl
->name
;
1747 while (ISSPACE(*++src
))
1751 while (*end
!= '\0' && !ISSPACE(*end
) && *end
!= '>')
1754 for (param
= tmpl
->params
, arg
= inst
->args
; param
;
1755 param
= param
->next
, arg
= arg
->next
)
1757 if (end
- src
== strlen (param
->name
)
1758 && !memcmp (src
, param
->name
, end
- src
))
1766 fail ("template '%s' has no parameter '%.*s'\n",
1767 tmpl
->name
, (int)(end
- src
), src
);
1769 while (ISSPACE(*src
))
1772 fail ("%s: %d: missing '>'\n", filename
, lineno
);
1774 memcpy(ptr1
, arg
->val
, strlen(arg
->val
));
1775 ptr1
+= strlen(arg
->val
);
1781 expand_templates (name2
, str2
, opcode_hash_table
, opcode_array_p
,
1793 process_i386_opcodes (FILE *table
)
1798 char *str
, *p
, *last
, *name
;
1799 htab_t opcode_hash_table
;
1800 struct opcode_hash_entry
**opcode_array
= NULL
;
1801 int lineno
= 0, marker
= 0;
1803 filename
= "i386-opc.tbl";
1807 opcode_hash_table
= htab_create_alloc (16, opcode_hash_hash
,
1808 opcode_hash_eq
, NULL
,
1811 fprintf (table
, "\n/* i386 opcode table. */\n\n");
1812 fprintf (table
, "const insn_template i386_optab[] =\n{\n");
1814 /* Put everything on opcode array. */
1817 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1820 p
= remove_leading_whitespaces (buf
);
1826 /* Skip comments. */
1827 str
= strstr (p
, "//");
1831 remove_trailing_whitespaces (p
);
1835 /* Look for line continuation character. */
1836 remove_trailing_whitespaces (p
);
1838 if (!j
|| buf
[j
- 1] != '+')
1840 if (j
>= sizeof (buf
) - 1)
1841 fail (_("%s: %d: (continued) line too long\n"), filename
, lineno
);
1843 if (fgets (buf
+ j
- 1, sizeof (buf
) - j
+ 1, fp
) == NULL
)
1845 fprintf (stderr
, "%s: Line continuation on last line?\n",
1854 if (!strcmp("### MARKER ###", buf
))
1858 /* Since we ignore all included files (we only care about their
1859 #define-s here), we don't need to monitor filenames. The final
1860 line number directive is going to refer to the main source file
1865 p
= remove_leading_whitespaces (p
+ 1);
1866 if (!strncmp(p
, "line", 4))
1868 ln
= strtoul (p
, &end
, 10);
1869 if (ln
> 1 && ln
< INT_MAX
1870 && *remove_leading_whitespaces (end
) == '"')
1873 /* Ignore comments. */
1878 parse_template (p
, lineno
);
1886 last
= p
+ strlen (p
);
1889 name
= next_field (p
, ',', &str
, last
);
1891 i
= expand_templates (name
, str
, opcode_hash_table
, &opcode_array
,
1895 /* Process opcode array. */
1896 for (j
= 0; j
< i
; j
++)
1898 struct opcode_hash_entry
*next
;
1900 for (next
= opcode_array
[j
]; next
; next
= next
->next
)
1904 lineno
= next
->lineno
;
1905 last
= str
+ strlen (str
);
1906 output_i386_opcode (table
, name
, str
, last
, lineno
);
1912 fprintf (table
, " { NULL, 0, 0, 0,\n");
1914 process_i386_opcode_modifier (table
, "0", 0, 0, NULL
, -1);
1916 process_i386_cpu_flag (table
, "0", 0, ",", " ", -1);
1918 fprintf (table
, " { ");
1919 process_i386_operand_type (table
, "0", stage_opcodes
, "\t ", -1);
1920 fprintf (table
, " } }\n");
1922 fprintf (table
, "};\n");
1926 process_i386_registers (FILE *table
)
1930 char *str
, *p
, *last
;
1931 char *reg_name
, *reg_type
, *reg_flags
, *reg_num
;
1932 char *dw2_32_num
, *dw2_64_num
;
1935 filename
= "i386-reg.tbl";
1936 fp
= fopen (filename
, "r");
1938 fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
1941 fprintf (table
, "\n/* i386 register table. */\n\n");
1942 fprintf (table
, "const reg_entry i386_regtab[] =\n{\n");
1946 if (fgets (buf
, sizeof (buf
), fp
) == NULL
)
1951 p
= remove_leading_whitespaces (buf
);
1953 /* Skip comments. */
1954 str
= strstr (p
, "//");
1958 /* Remove trailing white spaces. */
1959 remove_trailing_whitespaces (p
);
1964 fprintf (table
, "%s\n", p
);
1972 last
= p
+ strlen (p
);
1974 /* Find reg_name. */
1975 reg_name
= next_field (p
, ',', &str
, last
);
1977 /* Find reg_type. */
1978 reg_type
= next_field (str
, ',', &str
, last
);
1980 /* Find reg_flags. */
1981 reg_flags
= next_field (str
, ',', &str
, last
);
1984 reg_num
= next_field (str
, ',', &str
, last
);
1986 fprintf (table
, " { \"%s\",\n ", reg_name
);
1988 process_i386_operand_type (table
, reg_type
, stage_registers
, "\t",
1991 /* Find 32-bit Dwarf2 register number. */
1992 dw2_32_num
= next_field (str
, ',', &str
, last
);
1994 /* Find 64-bit Dwarf2 register number. */
1995 dw2_64_num
= next_field (str
, ',', &str
, last
);
1997 fprintf (table
, ",\n %s, %s, { %s, %s } },\n",
1998 reg_flags
, reg_num
, dw2_32_num
, dw2_64_num
);
2003 fprintf (table
, "};\n");
2005 fprintf (table
, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
2009 process_i386_initializers (void)
2012 FILE *fp
= fopen ("i386-init.h", "w");
2016 fail (_("can't create i386-init.h, errno = %s\n"),
2019 process_copyright (fp
);
2021 for (i
= 0; i
< ARRAY_SIZE (cpu_flag_init
); i
++)
2023 fprintf (fp
, "\n#define %s \\\n", cpu_flag_init
[i
].name
);
2024 init
= xstrdup (cpu_flag_init
[i
].init
);
2025 process_i386_cpu_flag (fp
, init
, 1, "", " ", -1);
2029 for (i
= 0; i
< ARRAY_SIZE (operand_type_init
); i
++)
2031 fprintf (fp
, "\n\n#define %s \\\n ", operand_type_init
[i
].name
);
2032 init
= xstrdup (operand_type_init
[i
].init
);
2033 process_i386_operand_type (fp
, init
, stage_macros
, " ", -1);
2041 /* Program options. */
2042 #define OPTION_SRCDIR 200
2044 struct option long_options
[] =
2046 {"srcdir", required_argument
, NULL
, OPTION_SRCDIR
},
2047 {"debug", no_argument
, NULL
, 'd'},
2048 {"version", no_argument
, NULL
, 'V'},
2049 {"help", no_argument
, NULL
, 'h'},
2050 {0, no_argument
, NULL
, 0}
2054 print_version (void)
2056 printf ("%s: version 1.0\n", program_name
);
2061 usage (FILE * stream
, int status
)
2063 fprintf (stream
, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
2069 main (int argc
, char **argv
)
2071 extern int chdir (char *);
2072 char *srcdir
= NULL
;
2074 unsigned int i
, cpumax
;
2077 program_name
= *argv
;
2078 xmalloc_set_program_name (program_name
);
2080 while ((c
= getopt_long (argc
, argv
, "vVdh", long_options
, 0)) != EOF
)
2105 if (chdir (srcdir
) != 0)
2106 fail (_("unable to change directory to \"%s\", errno = %s\n"),
2107 srcdir
, xstrerror (errno
));
2109 /* cpu_flags isn't sorted by position. */
2111 for (i
= 0; i
< ARRAY_SIZE (cpu_flags
); i
++)
2112 if (cpu_flags
[i
].position
> cpumax
)
2113 cpumax
= cpu_flags
[i
].position
;
2115 /* Check the unused bitfield in i386_cpu_flags. */
2117 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 2);
2119 if ((cpumax
- 1) != CpuMax
)
2120 fail (_("CpuMax != %d!\n"), cpumax
);
2122 static_assert (ARRAY_SIZE (cpu_flags
) == CpuMax
+ 1);
2124 if (cpumax
!= CpuMax
)
2125 fail (_("CpuMax != %d!\n"), cpumax
);
2127 c
= CpuNumOfBits
- CpuMax
- 1;
2129 fail (_("%d unused bits in i386_cpu_flags.\n"), c
);
2132 static_assert (ARRAY_SIZE (opcode_modifiers
) == Opcode_Modifier_Num
);
2134 /* Check the unused bitfield in i386_operand_type. */
2136 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2139 static_assert (ARRAY_SIZE (operand_types
) + CLASS_WIDTH
+ INSTANCE_WIDTH
2142 c
= OTNumOfBits
- OTNum
;
2144 fail (_("%d unused bits in i386_operand_type.\n"), c
);
2147 qsort (cpu_flags
, ARRAY_SIZE (cpu_flags
), sizeof (cpu_flags
[0]),
2150 qsort (opcode_modifiers
, ARRAY_SIZE (opcode_modifiers
),
2151 sizeof (opcode_modifiers
[0]), compare
);
2153 qsort (operand_types
, ARRAY_SIZE (operand_types
),
2154 sizeof (operand_types
[0]), compare
);
2156 table
= fopen ("i386-tbl.h", "w");
2158 fail (_("can't create i386-tbl.h, errno = %s\n"),
2161 process_copyright (table
);
2163 process_i386_opcodes (table
);
2164 process_i386_registers (table
);
2165 process_i386_initializers ();