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