1 1.10 christos /* Copyright (C) 2007-2025 Free Software Foundation, Inc. 2 1.1 christos 3 1.1 christos This file is part of the GNU opcodes library. 4 1.1 christos 5 1.1 christos This library is free software; you can redistribute it and/or modify 6 1.1 christos it under the terms of the GNU General Public License as published by 7 1.1 christos the Free Software Foundation; either version 3, or (at your option) 8 1.1 christos any later version. 9 1.1 christos 10 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 11 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 13 1.1 christos License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License 16 1.1 christos along with this program; if not, write to the Free Software 17 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 18 1.1 christos MA 02110-1301, USA. */ 19 1.1 christos 20 1.1 christos #include "sysdep.h" 21 1.9 christos #include <stdbool.h> 22 1.1 christos #include <stdio.h> 23 1.1 christos #include <errno.h> 24 1.1 christos #include "getopt.h" 25 1.1 christos #include "libiberty.h" 26 1.1 christos #include "hashtab.h" 27 1.1 christos #include "safe-ctype.h" 28 1.1 christos 29 1.1 christos #include "i386-opc.h" 30 1.1 christos 31 1.7 christos /* Build-time checks are preferrable over runtime ones. Use this construct 32 1.7 christos in preference where possible. */ 33 1.10 christos #ifndef static_assert 34 1.7 christos #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); })) 35 1.10 christos #endif 36 1.7 christos 37 1.1 christos static const char *program_name = NULL; 38 1.1 christos static int debug = 0; 39 1.1 christos 40 1.9 christos typedef struct dependency 41 1.1 christos { 42 1.1 christos const char *name; 43 1.9 christos /* Note: Only direct dependencies should be enumerated. */ 44 1.9 christos const char *deps; 45 1.9 christos } dependency; 46 1.9 christos 47 1.9 christos static const dependency isa_dependencies[] = 48 1.9 christos { 49 1.9 christos { "UNKNOWN", 50 1.10 christos "~(IAMCU|MPX)" }, 51 1.9 christos { "GENERIC32", 52 1.9 christos "386" }, 53 1.9 christos { "GENERIC64", 54 1.9 christos "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" }, 55 1.9 christos { "NONE", 56 1.9 christos "0" }, 57 1.9 christos { "PENTIUMPRO", 58 1.9 christos "686|Nop" }, 59 1.9 christos { "P2", 60 1.9 christos "PENTIUMPRO|MMX" }, 61 1.9 christos { "P3", 62 1.9 christos "P2|SSE" }, 63 1.9 christos { "P4", 64 1.9 christos "P3|Clflush|SSE2" }, 65 1.9 christos { "NOCONA", 66 1.9 christos "GENERIC64|FISTTP|SSE3|MONITOR|CX16" }, 67 1.9 christos { "CORE", 68 1.9 christos "P4|FISTTP|SSE3|MONITOR" }, 69 1.9 christos { "CORE2", 70 1.9 christos "NOCONA|SSSE3" }, 71 1.9 christos { "COREI7", 72 1.9 christos "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" }, 73 1.9 christos { "K6", 74 1.9 christos "186|286|386|486|586|SYSCALL|387|MMX" }, 75 1.9 christos { "K6_2", 76 1.9 christos "K6|3dnow" }, 77 1.9 christos { "ATHLON", 78 1.9 christos "K6_2|686:min|687|Nop|3dnowA" }, 79 1.9 christos { "K8", 80 1.9 christos "ATHLON|Rdtscp|SSE2|LM" }, 81 1.9 christos { "AMDFAM10", 82 1.9 christos "K8|FISTTP|SSE4A|ABM|MONITOR" }, 83 1.9 christos { "BDVER1", 84 1.9 christos "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMULQDQ|PRFCHW" }, 85 1.9 christos { "BDVER2", 86 1.9 christos "BDVER1|FMA|BMI|TBM|F16C" }, 87 1.9 christos { "BDVER3", 88 1.9 christos "BDVER2|Xsaveopt|FSGSBase" }, 89 1.9 christos { "BDVER4", 90 1.9 christos "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" }, 91 1.9 christos { "ZNVER1", 92 1.9 christos "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|AVX2|SSE4A|ABM|SVME|AES|PCLMULQDQ|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" }, 93 1.9 christos { "ZNVER2", 94 1.9 christos "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" }, 95 1.9 christos { "ZNVER3", 96 1.9 christos "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" }, 97 1.9 christos { "ZNVER4", 98 1.9 christos "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" }, 99 1.9 christos { "ZNVER5", 100 1.9 christos "ZNVER4|AVX_VNNI|MOVDIRI|MOVDIR64B|AVX512_VP2INTERSECT|PREFETCHI" }, 101 1.9 christos { "BTVER1", 102 1.9 christos "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" }, 103 1.9 christos { "BTVER2", 104 1.9 christos "BTVER1|AVX|BMI|F16C|AES|PCLMULQDQ|Movbe|Xsaveopt|PRFCHW" }, 105 1.9 christos { "286", 106 1.9 christos "186" }, 107 1.9 christos { "386", 108 1.9 christos "286" }, 109 1.9 christos { "486", 110 1.9 christos "386" }, 111 1.9 christos { "586", 112 1.9 christos "486|387" }, 113 1.9 christos { "586:nofpu", 114 1.9 christos "486" }, 115 1.9 christos { "686", 116 1.9 christos "586|687|CMOV|FXSR" }, 117 1.9 christos { "686:min", 118 1.9 christos "586|687" }, 119 1.9 christos { "687", 120 1.9 christos "387" }, 121 1.9 christos { "FISTTP", 122 1.9 christos "687" }, 123 1.9 christos { "SSE", 124 1.9 christos "FXSR" }, 125 1.9 christos { "SSE2", 126 1.9 christos "SSE" }, 127 1.9 christos { "SSE3", 128 1.9 christos "SSE2" }, 129 1.9 christos { "SSSE3", 130 1.9 christos "SSE3" }, 131 1.9 christos { "SSE4_1", 132 1.9 christos "SSSE3" }, 133 1.9 christos { "SSE4_2", 134 1.9 christos "SSE4_1|POPCNT" }, 135 1.9 christos { "Xsaveopt", 136 1.9 christos "XSAVE" }, 137 1.9 christos { "AES", 138 1.9 christos "SSE2" }, 139 1.9 christos { "PCLMULQDQ", 140 1.9 christos "SSE2" }, 141 1.9 christos { "FMA", 142 1.9 christos "AVX" }, 143 1.9 christos { "FMA4", 144 1.9 christos "AVX" }, 145 1.9 christos { "XOP", 146 1.9 christos "SSE4A|FMA4" }, 147 1.9 christos { "LWP", 148 1.9 christos "XSAVE" }, 149 1.9 christos { "F16C", 150 1.9 christos "AVX" }, 151 1.9 christos { "3dnow", 152 1.9 christos "MMX" }, 153 1.9 christos { "3dnowA", 154 1.9 christos "3dnow" }, 155 1.9 christos { "SSE4a", 156 1.9 christos "SSE3" }, 157 1.9 christos { "ABM", 158 1.9 christos "LZCNT|POPCNT" }, 159 1.9 christos { "AVX", 160 1.9 christos "SSE4_2|XSAVE" }, 161 1.9 christos { "AVX2", 162 1.9 christos "AVX" }, 163 1.9 christos { "AVX_VNNI", 164 1.9 christos "AVX2" }, 165 1.9 christos { "AVX_IFMA", 166 1.9 christos "AVX2" }, 167 1.9 christos { "AVX_VNNI_INT8", 168 1.9 christos "AVX2" }, 169 1.9 christos { "AVX_VNNI_INT16", 170 1.9 christos "AVX2" }, 171 1.9 christos { "AVX_NE_CONVERT", 172 1.9 christos "AVX2" }, 173 1.9 christos { "CX16", 174 1.9 christos "64" }, 175 1.9 christos { "LKGS", 176 1.9 christos "64" }, 177 1.9 christos { "FRED", 178 1.9 christos "LKGS" }, 179 1.9 christos { "AVX512F", 180 1.9 christos "AVX2" }, 181 1.9 christos { "AVX512CD", 182 1.9 christos "AVX512F" }, 183 1.9 christos { "AVX512ER", 184 1.9 christos "AVX512F" }, 185 1.9 christos { "AVX512PF", 186 1.9 christos "AVX512F" }, 187 1.9 christos { "AVX512DQ", 188 1.9 christos "AVX512F" }, 189 1.9 christos { "AVX512BW", 190 1.9 christos "AVX512F" }, 191 1.9 christos { "AVX512VL", 192 1.9 christos "AVX512F" }, 193 1.9 christos { "AVX512IFMA", 194 1.9 christos "AVX512F" }, 195 1.9 christos { "AVX512VBMI", 196 1.9 christos "AVX512BW" }, 197 1.9 christos { "AVX512_4FMAPS", 198 1.9 christos "AVX512F" }, 199 1.9 christos { "AVX512_4VNNIW", 200 1.9 christos "AVX512F" }, 201 1.9 christos { "AVX512_VPOPCNTDQ", 202 1.9 christos "AVX512F" }, 203 1.9 christos { "AVX512_VBMI2", 204 1.9 christos "AVX512BW" }, 205 1.9 christos { "AVX512_VNNI", 206 1.9 christos "AVX512F" }, 207 1.9 christos { "AVX512_BITALG", 208 1.9 christos "AVX512BW" }, 209 1.9 christos { "AVX512_VP2INTERSECT", 210 1.9 christos "AVX512F" }, 211 1.9 christos { "AVX512_BF16", 212 1.9 christos "AVX512BW" }, 213 1.9 christos { "AVX512_FP16", 214 1.9 christos "AVX512BW" }, 215 1.9 christos { "IAMCU", 216 1.9 christos "586:nofpu" }, 217 1.9 christos { "EPT", 218 1.9 christos "VMX" }, 219 1.9 christos { "VMFUNC", 220 1.9 christos "VMX" }, 221 1.9 christos { "MPX", 222 1.9 christos "XSAVE" }, 223 1.9 christos { "SHA", 224 1.9 christos "SSE2" }, 225 1.9 christos { "SHA512", 226 1.9 christos "AVX2" }, 227 1.9 christos { "SM3", 228 1.9 christos "AVX" }, 229 1.9 christos { "SM4", 230 1.9 christos "AVX2" }, 231 1.9 christos { "XSAVES", 232 1.9 christos "XSAVEC" }, 233 1.9 christos { "XSAVEC", 234 1.9 christos "XSAVE" }, 235 1.9 christos { "OSPKE", 236 1.9 christos "XSAVE" }, 237 1.9 christos { "GFNI", 238 1.9 christos "SSE2" }, 239 1.9 christos { "VAES", 240 1.9 christos "AVX2|AES" }, 241 1.9 christos { "VPCLMULQDQ", 242 1.9 christos "AVX2|PCLMULQDQ" }, 243 1.9 christos { "AVX10_1", 244 1.9 christos "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA" 245 1.9 christos "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" }, 246 1.10 christos { "AVX10_2", 247 1.10 christos "AVX10_1" }, 248 1.9 christos { "SEV_ES", 249 1.9 christos "SVME" }, 250 1.9 christos { "SNP", 251 1.9 christos "SEV_ES" }, 252 1.9 christos { "RMPQUERY", 253 1.9 christos "SNP|64" }, 254 1.10 christos { "RMPREAD", 255 1.10 christos "SNP|64" }, 256 1.9 christos { "TSX", 257 1.9 christos "RTM|HLE" }, 258 1.9 christos { "TSXLDTRK", 259 1.9 christos "RTM" }, 260 1.9 christos { "AMX_TILE", 261 1.9 christos "XSAVE|64" }, 262 1.9 christos { "AMX_INT8", 263 1.9 christos "AMX_TILE" }, 264 1.9 christos { "AMX_BF16", 265 1.9 christos "AMX_TILE" }, 266 1.9 christos { "AMX_FP16", 267 1.9 christos "AMX_TILE" }, 268 1.9 christos { "AMX_COMPLEX", 269 1.9 christos "AMX_TILE" }, 270 1.10 christos { "AMX_TRANSPOSE", 271 1.10 christos "AMX_TILE" }, 272 1.10 christos { "AMX_TF32", 273 1.10 christos "AMX_TILE" }, 274 1.10 christos { "AMX_FP8", 275 1.10 christos "AMX_TILE" }, 276 1.10 christos { "AMX_MOVRS", 277 1.10 christos "AMX_TILE" }, 278 1.10 christos { "AMX_AVX512", 279 1.10 christos "AMX_TILE|AVX10_2" }, 280 1.9 christos { "KL", 281 1.9 christos "SSE2" }, 282 1.9 christos { "WIDEKL", 283 1.9 christos "KL" }, 284 1.9 christos { "PBNDKB", 285 1.9 christos "64" }, 286 1.9 christos { "UINTR", 287 1.9 christos "64" }, 288 1.9 christos { "PREFETCHI", 289 1.9 christos "64" }, 290 1.9 christos { "CMPCCXADD", 291 1.9 christos "64" }, 292 1.9 christos { "MSRLIST", 293 1.9 christos "64" }, 294 1.9 christos { "USER_MSR", 295 1.9 christos "64" }, 296 1.10 christos { "MSR_IMM", 297 1.10 christos "64" }, 298 1.9 christos { "APX_F", 299 1.9 christos "XSAVE|64" }, 300 1.10 christos { "PadLockRNG2", 301 1.10 christos "PadLock" }, 302 1.10 christos { "PadLockPHE2", 303 1.10 christos "PadLock" }, 304 1.10 christos { "PadLockXMODX", 305 1.10 christos "PadLock" }, 306 1.1 christos }; 307 1.1 christos 308 1.9 christos /* This array is populated as process_i386_initializers() walks cpu_flags[]. */ 309 1.9 christos static unsigned char isa_reverse_deps[CpuMax][CpuMax]; 310 1.1 christos 311 1.1 christos typedef struct bitfield 312 1.1 christos { 313 1.1 christos int position; 314 1.1 christos int value; 315 1.1 christos const char *name; 316 1.1 christos } bitfield; 317 1.1 christos 318 1.9 christos #define BITFIELD(n) { Cpu##n, 0, #n } 319 1.1 christos 320 1.1 christos static bitfield cpu_flags[] = 321 1.1 christos { 322 1.9 christos BITFIELD (186), 323 1.9 christos BITFIELD (286), 324 1.9 christos BITFIELD (386), 325 1.9 christos BITFIELD (486), 326 1.9 christos BITFIELD (586), 327 1.9 christos BITFIELD (686), 328 1.9 christos BITFIELD (CMOV), 329 1.9 christos BITFIELD (FXSR), 330 1.9 christos BITFIELD (Clflush), 331 1.9 christos BITFIELD (Nop), 332 1.9 christos BITFIELD (SYSCALL), 333 1.9 christos BITFIELD (8087), 334 1.9 christos BITFIELD (287), 335 1.9 christos BITFIELD (387), 336 1.9 christos BITFIELD (687), 337 1.9 christos BITFIELD (FISTTP), 338 1.9 christos BITFIELD (MMX), 339 1.9 christos BITFIELD (SSE), 340 1.9 christos BITFIELD (SSE2), 341 1.9 christos BITFIELD (SSE3), 342 1.9 christos BITFIELD (SSSE3), 343 1.9 christos BITFIELD (SSE4_1), 344 1.9 christos BITFIELD (SSE4_2), 345 1.9 christos BITFIELD (AVX), 346 1.9 christos BITFIELD (AVX2), 347 1.9 christos BITFIELD (AVX512F), 348 1.9 christos BITFIELD (AVX512CD), 349 1.9 christos BITFIELD (AVX512ER), 350 1.9 christos BITFIELD (AVX512PF), 351 1.9 christos BITFIELD (AVX512VL), 352 1.9 christos BITFIELD (AVX512DQ), 353 1.9 christos BITFIELD (AVX512BW), 354 1.9 christos BITFIELD (IAMCU), 355 1.9 christos BITFIELD (SSE4a), 356 1.9 christos BITFIELD (3dnow), 357 1.9 christos BITFIELD (3dnowA), 358 1.9 christos BITFIELD (PadLock), 359 1.10 christos BITFIELD (PadLockRNG2), 360 1.10 christos BITFIELD (PadLockPHE2), 361 1.10 christos BITFIELD (PadLockXMODX), 362 1.10 christos BITFIELD (GMISM2), 363 1.10 christos BITFIELD (GMICCS), 364 1.9 christos BITFIELD (SVME), 365 1.9 christos BITFIELD (VMX), 366 1.9 christos BITFIELD (SMX), 367 1.9 christos BITFIELD (Xsave), 368 1.9 christos BITFIELD (Xsaveopt), 369 1.9 christos BITFIELD (AES), 370 1.9 christos BITFIELD (PCLMULQDQ), 371 1.9 christos BITFIELD (FMA), 372 1.9 christos BITFIELD (FMA4), 373 1.9 christos BITFIELD (XOP), 374 1.9 christos BITFIELD (LWP), 375 1.9 christos BITFIELD (BMI), 376 1.9 christos BITFIELD (TBM), 377 1.9 christos BITFIELD (Movbe), 378 1.9 christos BITFIELD (CX16), 379 1.9 christos BITFIELD (LAHF_SAHF), 380 1.9 christos BITFIELD (EPT), 381 1.9 christos BITFIELD (Rdtscp), 382 1.9 christos BITFIELD (FSGSBase), 383 1.9 christos BITFIELD (RdRnd), 384 1.9 christos BITFIELD (F16C), 385 1.9 christos BITFIELD (BMI2), 386 1.9 christos BITFIELD (LZCNT), 387 1.9 christos BITFIELD (POPCNT), 388 1.9 christos BITFIELD (MONITOR), 389 1.9 christos BITFIELD (HLE), 390 1.9 christos BITFIELD (RTM), 391 1.9 christos BITFIELD (INVPCID), 392 1.9 christos BITFIELD (VMFUNC), 393 1.9 christos BITFIELD (RDSEED), 394 1.9 christos BITFIELD (ADX), 395 1.9 christos BITFIELD (PRFCHW), 396 1.9 christos BITFIELD (SMAP), 397 1.9 christos BITFIELD (SHA), 398 1.9 christos BITFIELD (SHA512), 399 1.9 christos BITFIELD (SM3), 400 1.9 christos BITFIELD (SM4), 401 1.9 christos BITFIELD (ClflushOpt), 402 1.9 christos BITFIELD (XSAVES), 403 1.9 christos BITFIELD (XSAVEC), 404 1.9 christos BITFIELD (PREFETCHWT1), 405 1.9 christos BITFIELD (SE1), 406 1.9 christos BITFIELD (CLWB), 407 1.9 christos BITFIELD (MPX), 408 1.9 christos BITFIELD (AVX512IFMA), 409 1.9 christos BITFIELD (AVX512VBMI), 410 1.9 christos BITFIELD (AVX512_4FMAPS), 411 1.9 christos BITFIELD (AVX512_4VNNIW), 412 1.9 christos BITFIELD (AVX512_VPOPCNTDQ), 413 1.9 christos BITFIELD (AVX512_VBMI2), 414 1.9 christos BITFIELD (AVX512_VNNI), 415 1.9 christos BITFIELD (AVX512_BITALG), 416 1.9 christos BITFIELD (AVX512_BF16), 417 1.9 christos BITFIELD (AVX512_VP2INTERSECT), 418 1.9 christos BITFIELD (TDX), 419 1.9 christos BITFIELD (AVX_VNNI), 420 1.9 christos BITFIELD (AVX512_FP16), 421 1.9 christos BITFIELD (PREFETCHI), 422 1.9 christos BITFIELD (AVX_IFMA), 423 1.9 christos BITFIELD (AVX_VNNI_INT8), 424 1.9 christos BITFIELD (AVX_VNNI_INT16), 425 1.9 christos BITFIELD (CMPCCXADD), 426 1.9 christos BITFIELD (WRMSRNS), 427 1.9 christos BITFIELD (MSRLIST), 428 1.9 christos BITFIELD (AVX_NE_CONVERT), 429 1.9 christos BITFIELD (RAO_INT), 430 1.9 christos BITFIELD (FRED), 431 1.9 christos BITFIELD (LKGS), 432 1.9 christos BITFIELD (USER_MSR), 433 1.10 christos BITFIELD (MSR_IMM), 434 1.9 christos BITFIELD (APX_F), 435 1.10 christos BITFIELD (AVX10_2), 436 1.10 christos BITFIELD (MOVRS), 437 1.9 christos BITFIELD (MWAITX), 438 1.9 christos BITFIELD (CLZERO), 439 1.9 christos BITFIELD (OSPKE), 440 1.9 christos BITFIELD (RDPID), 441 1.9 christos BITFIELD (PTWRITE), 442 1.9 christos BITFIELD (IBT), 443 1.9 christos BITFIELD (SHSTK), 444 1.9 christos BITFIELD (GFNI), 445 1.9 christos BITFIELD (VAES), 446 1.9 christos BITFIELD (VPCLMULQDQ), 447 1.9 christos BITFIELD (WBNOINVD), 448 1.9 christos BITFIELD (PCONFIG), 449 1.9 christos BITFIELD (PBNDKB), 450 1.9 christos BITFIELD (WAITPKG), 451 1.9 christos BITFIELD (UINTR), 452 1.9 christos BITFIELD (CLDEMOTE), 453 1.9 christos BITFIELD (AMX_INT8), 454 1.9 christos BITFIELD (AMX_BF16), 455 1.9 christos BITFIELD (AMX_FP16), 456 1.9 christos BITFIELD (AMX_COMPLEX), 457 1.10 christos BITFIELD (AMX_TRANSPOSE), 458 1.10 christos BITFIELD (AMX_TF32), 459 1.10 christos BITFIELD (AMX_FP8), 460 1.10 christos BITFIELD (AMX_MOVRS), 461 1.10 christos BITFIELD (AMX_AVX512), 462 1.9 christos BITFIELD (AMX_TILE), 463 1.9 christos BITFIELD (MOVDIRI), 464 1.9 christos BITFIELD (MOVDIR64B), 465 1.9 christos BITFIELD (ENQCMD), 466 1.9 christos BITFIELD (SERIALIZE), 467 1.9 christos BITFIELD (RDPRU), 468 1.9 christos BITFIELD (MCOMMIT), 469 1.9 christos BITFIELD (SEV_ES), 470 1.9 christos BITFIELD (TSXLDTRK), 471 1.9 christos BITFIELD (KL), 472 1.9 christos BITFIELD (WideKL), 473 1.9 christos BITFIELD (HRESET), 474 1.9 christos BITFIELD (INVLPGB), 475 1.9 christos BITFIELD (TLBSYNC), 476 1.9 christos BITFIELD (SNP), 477 1.9 christos BITFIELD (RMPQUERY), 478 1.10 christos BITFIELD (RMPREAD), 479 1.9 christos BITFIELD (64), 480 1.9 christos BITFIELD (No64), 481 1.1 christos #ifdef CpuUnused 482 1.9 christos BITFIELD (Unused), 483 1.1 christos #endif 484 1.1 christos }; 485 1.1 christos 486 1.9 christos #undef BITFIELD 487 1.9 christos #define BITFIELD(n) { n, 0, #n } 488 1.9 christos 489 1.1 christos static bitfield opcode_modifiers[] = 490 1.1 christos { 491 1.1 christos BITFIELD (D), 492 1.1 christos BITFIELD (W), 493 1.6 christos BITFIELD (Load), 494 1.1 christos BITFIELD (Modrm), 495 1.1 christos BITFIELD (Jump), 496 1.1 christos BITFIELD (FloatMF), 497 1.7 christos BITFIELD (Size), 498 1.9 christos BITFIELD (CheckOperandSize), 499 1.9 christos BITFIELD (OperandConstraint), 500 1.8 christos BITFIELD (MnemonicSize), 501 1.1 christos BITFIELD (No_bSuf), 502 1.1 christos BITFIELD (No_wSuf), 503 1.1 christos BITFIELD (No_lSuf), 504 1.1 christos BITFIELD (No_sSuf), 505 1.1 christos BITFIELD (No_qSuf), 506 1.1 christos BITFIELD (FWait), 507 1.1 christos BITFIELD (IsString), 508 1.7 christos BITFIELD (RegMem), 509 1.3 christos BITFIELD (BNDPrefixOk), 510 1.8 christos BITFIELD (PrefixOk), 511 1.1 christos BITFIELD (IsPrefix), 512 1.1 christos BITFIELD (ImmExt), 513 1.1 christos BITFIELD (NoRex64), 514 1.1 christos BITFIELD (Vex), 515 1.1 christos BITFIELD (VexVVVV), 516 1.1 christos BITFIELD (VexW), 517 1.8 christos BITFIELD (OpcodePrefix), 518 1.8 christos BITFIELD (SIB), 519 1.1 christos BITFIELD (SSE2AVX), 520 1.3 christos BITFIELD (EVex), 521 1.3 christos BITFIELD (Masking), 522 1.3 christos BITFIELD (Broadcast), 523 1.3 christos BITFIELD (StaticRounding), 524 1.3 christos BITFIELD (SAE), 525 1.3 christos BITFIELD (Disp8MemShift), 526 1.6 christos BITFIELD (Optimize), 527 1.9 christos BITFIELD (Dialect), 528 1.10 christos BITFIELD (IntelSuffix), 529 1.8 christos BITFIELD (ISA64), 530 1.9 christos BITFIELD (NoEgpr), 531 1.9 christos BITFIELD (NF), 532 1.9 christos BITFIELD (Rex2), 533 1.1 christos }; 534 1.1 christos 535 1.7 christos #define CLASS(n) #n, n 536 1.7 christos 537 1.7 christos static const struct { 538 1.7 christos const char *name; 539 1.7 christos enum operand_class value; 540 1.7 christos } operand_classes[] = { 541 1.7 christos CLASS (Reg), 542 1.7 christos CLASS (SReg), 543 1.10 christos CLASS (RegFP), 544 1.7 christos CLASS (RegCR), 545 1.7 christos CLASS (RegDR), 546 1.7 christos CLASS (RegTR), 547 1.7 christos CLASS (RegMMX), 548 1.7 christos CLASS (RegSIMD), 549 1.7 christos CLASS (RegMask), 550 1.7 christos CLASS (RegBND), 551 1.7 christos }; 552 1.7 christos 553 1.7 christos #undef CLASS 554 1.7 christos 555 1.7 christos #define INSTANCE(n) #n, n 556 1.7 christos 557 1.7 christos static const struct { 558 1.7 christos const char *name; 559 1.7 christos enum operand_instance value; 560 1.7 christos } operand_instances[] = { 561 1.7 christos INSTANCE (Accum), 562 1.7 christos INSTANCE (RegC), 563 1.7 christos INSTANCE (RegD), 564 1.7 christos INSTANCE (RegB), 565 1.7 christos }; 566 1.7 christos 567 1.7 christos #undef INSTANCE 568 1.7 christos 569 1.1 christos static bitfield operand_types[] = 570 1.1 christos { 571 1.1 christos BITFIELD (Imm1), 572 1.1 christos BITFIELD (Imm8), 573 1.1 christos BITFIELD (Imm8S), 574 1.1 christos BITFIELD (Imm16), 575 1.1 christos BITFIELD (Imm32), 576 1.1 christos BITFIELD (Imm32S), 577 1.1 christos BITFIELD (Imm64), 578 1.1 christos BITFIELD (BaseIndex), 579 1.1 christos BITFIELD (Disp8), 580 1.1 christos BITFIELD (Disp16), 581 1.1 christos BITFIELD (Disp32), 582 1.1 christos BITFIELD (Disp64), 583 1.1 christos BITFIELD (Byte), 584 1.1 christos BITFIELD (Word), 585 1.1 christos BITFIELD (Dword), 586 1.1 christos BITFIELD (Fword), 587 1.1 christos BITFIELD (Qword), 588 1.1 christos BITFIELD (Tbyte), 589 1.1 christos BITFIELD (Xmmword), 590 1.1 christos BITFIELD (Ymmword), 591 1.3 christos BITFIELD (Zmmword), 592 1.8 christos BITFIELD (Tmmword), 593 1.1 christos BITFIELD (Unspecified), 594 1.1 christos #ifdef OTUnused 595 1.1 christos BITFIELD (OTUnused), 596 1.1 christos #endif 597 1.1 christos }; 598 1.1 christos 599 1.1 christos static const char *filename; 600 1.6 christos static i386_cpu_flags active_cpu_flags; 601 1.6 christos static int active_isstring; 602 1.1 christos 603 1.8 christos struct template_arg { 604 1.8 christos const struct template_arg *next; 605 1.8 christos const char *val; 606 1.8 christos }; 607 1.8 christos 608 1.8 christos struct template_instance { 609 1.8 christos const struct template_instance *next; 610 1.8 christos const char *name; 611 1.8 christos const struct template_arg *args; 612 1.8 christos }; 613 1.8 christos 614 1.8 christos struct template_param { 615 1.8 christos const struct template_param *next; 616 1.8 christos const char *name; 617 1.8 christos }; 618 1.8 christos 619 1.8 christos struct template { 620 1.9 christos struct template *next; 621 1.8 christos const char *name; 622 1.8 christos const struct template_instance *instances; 623 1.8 christos const struct template_param *params; 624 1.8 christos }; 625 1.8 christos 626 1.9 christos static struct template *templates; 627 1.8 christos 628 1.1 christos static int 629 1.1 christos compare (const void *x, const void *y) 630 1.1 christos { 631 1.1 christos const bitfield *xp = (const bitfield *) x; 632 1.1 christos const bitfield *yp = (const bitfield *) y; 633 1.1 christos return xp->position - yp->position; 634 1.1 christos } 635 1.1 christos 636 1.1 christos static void 637 1.1 christos fail (const char *message, ...) 638 1.1 christos { 639 1.1 christos va_list args; 640 1.1 christos 641 1.1 christos va_start (args, message); 642 1.9 christos fprintf (stderr, "%s: error: ", program_name); 643 1.1 christos vfprintf (stderr, message, args); 644 1.1 christos va_end (args); 645 1.1 christos xexit (1); 646 1.1 christos } 647 1.1 christos 648 1.1 christos static void 649 1.1 christos process_copyright (FILE *fp) 650 1.1 christos { 651 1.1 christos fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\ 652 1.10 christos /* Copyright (C) 2007-2025 Free Software Foundation, Inc.\n\ 653 1.1 christos \n\ 654 1.1 christos This file is part of the GNU opcodes library.\n\ 655 1.1 christos \n\ 656 1.1 christos This library is free software; you can redistribute it and/or modify\n\ 657 1.1 christos it under the terms of the GNU General Public License as published by\n\ 658 1.1 christos the Free Software Foundation; either version 3, or (at your option)\n\ 659 1.1 christos any later version.\n\ 660 1.1 christos \n\ 661 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT\n\ 662 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\ 663 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\ 664 1.1 christos License for more details.\n\ 665 1.1 christos \n\ 666 1.1 christos You should have received a copy of the GNU General Public License\n\ 667 1.1 christos along with this program; if not, write to the Free Software\n\ 668 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\ 669 1.1 christos MA 02110-1301, USA. */\n"); 670 1.1 christos } 671 1.1 christos 672 1.1 christos /* Remove leading white spaces. */ 673 1.1 christos 674 1.1 christos static char * 675 1.1 christos remove_leading_whitespaces (char *str) 676 1.1 christos { 677 1.1 christos while (ISSPACE (*str)) 678 1.1 christos str++; 679 1.1 christos return str; 680 1.1 christos } 681 1.1 christos 682 1.1 christos /* Remove trailing white spaces. */ 683 1.1 christos 684 1.1 christos static void 685 1.1 christos remove_trailing_whitespaces (char *str) 686 1.1 christos { 687 1.1 christos size_t last = strlen (str); 688 1.1 christos 689 1.1 christos if (last == 0) 690 1.1 christos return; 691 1.1 christos 692 1.1 christos do 693 1.1 christos { 694 1.1 christos last--; 695 1.1 christos if (ISSPACE (str [last])) 696 1.1 christos str[last] = '\0'; 697 1.1 christos else 698 1.1 christos break; 699 1.1 christos } 700 1.1 christos while (last != 0); 701 1.1 christos } 702 1.1 christos 703 1.1 christos /* Find next field separated by SEP and terminate it. Return a 704 1.1 christos pointer to the one after it. */ 705 1.1 christos 706 1.1 christos static char * 707 1.1 christos next_field (char *str, char sep, char **next, char *last) 708 1.1 christos { 709 1.1 christos char *p; 710 1.1 christos 711 1.1 christos p = remove_leading_whitespaces (str); 712 1.1 christos for (str = p; *str != sep && *str != '\0'; str++); 713 1.1 christos 714 1.1 christos *str = '\0'; 715 1.1 christos remove_trailing_whitespaces (p); 716 1.1 christos 717 1.1 christos *next = str + 1; 718 1.1 christos 719 1.1 christos if (p >= last) 720 1.1 christos abort (); 721 1.1 christos 722 1.1 christos return p; 723 1.1 christos } 724 1.1 christos 725 1.5 christos static void set_bitfield (char *, bitfield *, int, unsigned int, int); 726 1.5 christos 727 1.1 christos static void 728 1.5 christos set_bitfield (char *f, bitfield *array, int value, 729 1.1 christos unsigned int size, int lineno) 730 1.1 christos { 731 1.1 christos unsigned int i; 732 1.1 christos 733 1.8 christos /* Ignore empty fields; they may result from template expansions. */ 734 1.8 christos if (*f == '\0') 735 1.8 christos return; 736 1.1 christos 737 1.1 christos for (i = 0; i < size; i++) 738 1.1 christos if (strcasecmp (array[i].name, f) == 0) 739 1.1 christos { 740 1.1 christos array[i].value = value; 741 1.1 christos return; 742 1.1 christos } 743 1.1 christos 744 1.1 christos if (value) 745 1.1 christos { 746 1.1 christos const char *v = strchr (f, '='); 747 1.1 christos 748 1.1 christos if (v) 749 1.1 christos { 750 1.1 christos size_t n = v - f; 751 1.1 christos char *end; 752 1.1 christos 753 1.1 christos for (i = 0; i < size; i++) 754 1.1 christos if (strncasecmp (array[i].name, f, n) == 0) 755 1.1 christos { 756 1.1 christos value = strtol (v + 1, &end, 0); 757 1.1 christos if (*end == '\0') 758 1.1 christos { 759 1.1 christos array[i].value = value; 760 1.1 christos return; 761 1.1 christos } 762 1.1 christos break; 763 1.1 christos } 764 1.1 christos } 765 1.1 christos } 766 1.1 christos 767 1.1 christos if (lineno != -1) 768 1.9 christos fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f); 769 1.1 christos else 770 1.9 christos fail ("unknown bitfield: %s\n", f); 771 1.9 christos } 772 1.9 christos 773 1.9 christos static void 774 1.9 christos add_isa_dependencies (bitfield *flags, const char *f, int value, 775 1.9 christos unsigned int reverse) 776 1.9 christos { 777 1.9 christos unsigned int i; 778 1.9 christos char *str = NULL; 779 1.9 christos const char *isa = f; 780 1.9 christos static bool is_avx; 781 1.9 christos bool is_isa = false, orig_is_avx = is_avx; 782 1.9 christos 783 1.9 christos /* Need to find base entry for references to auxiliary ones. */ 784 1.9 christos if (strchr (f, ':')) 785 1.9 christos { 786 1.9 christos str = xstrdup (f); 787 1.9 christos *strchr (str, ':') = '\0'; 788 1.9 christos isa = str; 789 1.9 christos } 790 1.9 christos /* isa_dependencies[] prefers "LM" over "64". */ 791 1.9 christos else if (!strcmp (f, "LM")) 792 1.9 christos isa = "64"; 793 1.9 christos for (i = 0; i < CpuMax; ++i) 794 1.9 christos if (strcasecmp (flags[i].name, isa) == 0) 795 1.9 christos { 796 1.9 christos flags[i].value = value; 797 1.9 christos if (reverse < ARRAY_SIZE (isa_reverse_deps[0]) 798 1.9 christos /* Don't record the feature itself here. */ 799 1.9 christos && reverse != i 800 1.9 christos /* Don't record base architectures. */ 801 1.9 christos && reverse > Cpu686) 802 1.9 christos isa_reverse_deps[i][reverse] = 1; 803 1.9 christos is_isa = true; 804 1.9 christos if (i == CpuAVX || i == CpuXOP || i == CpuVAES || i == CpuVPCLMULQDQ) 805 1.9 christos is_avx = true; 806 1.9 christos break; 807 1.9 christos } 808 1.9 christos free (str); 809 1.9 christos 810 1.9 christos /* Do not turn off dependencies. */ 811 1.9 christos if (is_isa && !value) 812 1.9 christos { 813 1.9 christos is_avx = orig_is_avx; 814 1.9 christos return; 815 1.9 christos } 816 1.9 christos 817 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i) 818 1.9 christos if (strcasecmp (isa_dependencies[i].name, f) == 0) 819 1.9 christos { 820 1.9 christos char *deps = xstrdup (isa_dependencies[i].deps); 821 1.9 christos char *next = deps; 822 1.9 christos char *last = deps + strlen (deps); 823 1.9 christos 824 1.9 christos for (; next && next < last; ) 825 1.9 christos { 826 1.9 christos char *str = next_field (next, '|', &next, last); 827 1.9 christos 828 1.9 christos /* No AVX/XOP -> SSE reverse dependencies. */ 829 1.9 christos if (is_avx && strncmp (str, "SSE", 3) == 0) 830 1.9 christos add_isa_dependencies (flags, str, value, CpuMax); 831 1.9 christos else 832 1.9 christos add_isa_dependencies (flags, str, value, reverse); 833 1.9 christos } 834 1.9 christos free (deps); 835 1.9 christos 836 1.9 christos /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted, 837 1.9 christos unless the sole dependency is the "64-bit mode only" one. */ 838 1.9 christos if (reverse < ARRAY_SIZE (isa_reverse_deps[0]) 839 1.9 christos && strcmp (isa_dependencies[i].deps, "64")) 840 1.9 christos isa_reverse_deps[reverse][reverse] = 1; 841 1.9 christos 842 1.9 christos is_avx = orig_is_avx; 843 1.9 christos return; 844 1.9 christos } 845 1.9 christos 846 1.9 christos if (!is_isa) 847 1.9 christos fail ("unknown bitfield: %s\n", f); 848 1.9 christos 849 1.9 christos is_avx = orig_is_avx; 850 1.1 christos } 851 1.1 christos 852 1.1 christos static void 853 1.1 christos output_cpu_flags (FILE *table, bitfield *flags, unsigned int size, 854 1.9 christos int mode, const char *comma, const char *indent, int lineno) 855 1.1 christos { 856 1.9 christos unsigned int i = 0, j = 0; 857 1.1 christos 858 1.9 christos if (mode < 0) 859 1.9 christos memset (&active_cpu_flags, 0, sizeof(active_cpu_flags)); 860 1.6 christos 861 1.1 christos fprintf (table, "%s{ { ", indent); 862 1.1 christos 863 1.9 christos if (mode <= 0) 864 1.9 christos { 865 1.9 christos for (j = ~0u; i < CpuAttrEnums; i++) 866 1.9 christos { 867 1.9 christos if (!flags[i].value) 868 1.9 christos continue; 869 1.9 christos 870 1.9 christos if (j < ~0u) 871 1.9 christos fail ("%s: %d: invalid combination of CPU identifiers\n", 872 1.9 christos filename, lineno); 873 1.9 christos j = i; 874 1.9 christos if (mode) 875 1.9 christos active_cpu_flags.array[i / 32] |= 1U << (i % 32); 876 1.9 christos } 877 1.9 christos 878 1.9 christos /* Write 0 to indicate "no associated flag". */ 879 1.9 christos fprintf (table, "%u, ", j + 1); 880 1.9 christos 881 1.9 christos j = 1; 882 1.9 christos } 883 1.9 christos 884 1.9 christos for (; i < size - 1; i++, j++) 885 1.1 christos { 886 1.9 christos if (((j + 1) % 20) != 0) 887 1.3 christos fprintf (table, "%d, ", flags[i].value); 888 1.3 christos else 889 1.3 christos fprintf (table, "%d,", flags[i].value); 890 1.9 christos if (((j + 1) % 20) == 0) 891 1.1 christos { 892 1.1 christos /* We need \\ for macro. */ 893 1.9 christos if (mode > 0) 894 1.1 christos fprintf (table, " \\\n %s", indent); 895 1.1 christos else 896 1.1 christos fprintf (table, "\n %s", indent); 897 1.1 christos } 898 1.9 christos if (mode < 0 && flags[i].value) 899 1.6 christos active_cpu_flags.array[i / 32] |= 1U << (i % 32); 900 1.1 christos } 901 1.1 christos 902 1.9 christos #if defined(CpuAttrUnused) != defined(CpuUnused) 903 1.9 christos if (mode <= 0) 904 1.9 christos # ifdef CpuUnused 905 1.9 christos fprintf (table, " } }%s\n", comma); 906 1.9 christos # else 907 1.9 christos fprintf (table, "%d, 0 } }%s\n", flags[i].value, comma); 908 1.9 christos # endif 909 1.9 christos else 910 1.9 christos #endif 911 1.9 christos fprintf (table, "%d } }%s\n", flags[i].value, comma); 912 1.1 christos } 913 1.1 christos 914 1.1 christos static void 915 1.9 christos process_i386_cpu_flag (FILE *table, char *flag, 916 1.9 christos const char *name, 917 1.1 christos const char *comma, const char *indent, 918 1.9 christos int lineno, unsigned int reverse) 919 1.1 christos { 920 1.8 christos char *str, *next = flag, *last; 921 1.1 christos unsigned int i; 922 1.8 christos int value = 1; 923 1.9 christos bool is_isa = false; 924 1.9 christos bitfield all [ARRAY_SIZE (cpu_flags)]; 925 1.9 christos bitfield any [ARRAY_SIZE (cpu_flags)]; 926 1.1 christos 927 1.1 christos /* Copy the default cpu flags. */ 928 1.9 christos memcpy (all, cpu_flags, sizeof (cpu_flags)); 929 1.9 christos memcpy (any, cpu_flags, sizeof (cpu_flags)); 930 1.9 christos 931 1.9 christos if (flag == NULL) 932 1.9 christos { 933 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i) 934 1.9 christos any[i].value = isa_reverse_deps[reverse][i]; 935 1.9 christos goto output; 936 1.9 christos } 937 1.1 christos 938 1.8 christos if (flag[0] == '~') 939 1.1 christos { 940 1.1 christos last = flag + strlen (flag); 941 1.1 christos 942 1.1 christos if (flag[1] == '(') 943 1.1 christos { 944 1.1 christos last -= 1; 945 1.1 christos next = flag + 2; 946 1.1 christos if (*last != ')') 947 1.9 christos fail ("%s: %d: missing `)' in bitfield: %s\n", filename, 948 1.1 christos lineno, flag); 949 1.1 christos *last = '\0'; 950 1.1 christos } 951 1.1 christos else 952 1.1 christos next = flag + 1; 953 1.1 christos 954 1.9 christos /* First we turn on everything except for cpuno64 and - if 955 1.8 christos present - the padding field. */ 956 1.9 christos for (i = 0; i < ARRAY_SIZE (any); i++) 957 1.9 christos if (any[i].position < CpuNo64) 958 1.9 christos any[i].value = 1; 959 1.1 christos 960 1.1 christos /* Turn off selective bits. */ 961 1.8 christos value = 0; 962 1.1 christos } 963 1.8 christos 964 1.9 christos if (name != NULL && value != 0) 965 1.9 christos { 966 1.9 christos for (i = 0; i < ARRAY_SIZE (any); i++) 967 1.9 christos if (strcasecmp (any[i].name, name) == 0) 968 1.9 christos { 969 1.9 christos add_isa_dependencies (any, name, 1, reverse); 970 1.9 christos is_isa = true; 971 1.9 christos break; 972 1.9 christos } 973 1.9 christos } 974 1.9 christos 975 1.8 christos if (strcmp (flag, "0")) 976 1.1 christos { 977 1.9 christos bool combined = false; 978 1.9 christos 979 1.9 christos if (is_isa) 980 1.9 christos return; 981 1.9 christos 982 1.8 christos /* Turn on/off selective bits. */ 983 1.1 christos last = flag + strlen (flag); 984 1.9 christos if (name == NULL && strchr (flag, '&')) 985 1.9 christos { 986 1.9 christos for (; next < last && *next != '('; ) 987 1.9 christos { 988 1.9 christos str = next_field (next, '&', &next, last); 989 1.9 christos set_bitfield (str, all, value, ARRAY_SIZE (all), lineno); 990 1.9 christos } 991 1.9 christos if (*next == '(') 992 1.9 christos { 993 1.9 christos if (*--last != ')') 994 1.9 christos fail ("%s: %d: missing `)' in bitfield: %s\n", filename, 995 1.9 christos lineno, flag); 996 1.9 christos ++next; 997 1.9 christos *last = '\0'; 998 1.9 christos } 999 1.9 christos combined = true; 1000 1.9 christos } 1001 1.8 christos for (; next && next < last; ) 1002 1.1 christos { 1003 1.1 christos str = next_field (next, '|', &next, last); 1004 1.9 christos if (name) 1005 1.9 christos add_isa_dependencies (any, str, value, reverse); 1006 1.9 christos else if (combined || next < last) 1007 1.9 christos set_bitfield (str, any, value, ARRAY_SIZE (any), lineno); 1008 1.9 christos else /* Singular specifiers go into "all". */ 1009 1.9 christos set_bitfield (str, all, value, ARRAY_SIZE (all), lineno); 1010 1.9 christos combined = true; 1011 1.1 christos } 1012 1.1 christos } 1013 1.1 christos 1014 1.9 christos output: 1015 1.9 christos if (name != NULL) 1016 1.9 christos { 1017 1.9 christos size_t len = strlen (name); 1018 1.9 christos char *upper = xmalloc (len + 1); 1019 1.9 christos 1020 1.9 christos /* Cpu64 is special: It specifies a mode dependency, not an ISA one. Zap 1021 1.9 christos the flag from ISA initializer macros (and from CPU_ANY_64_FLAGS 1022 1.9 christos itself we only care about tracking its dependents. Also don't emit the 1023 1.9 christos (otherwise all zero) CPU_64_FLAGS. */ 1024 1.9 christos if (flag != NULL && reverse == Cpu64) 1025 1.9 christos return; 1026 1.9 christos if (is_isa || flag == NULL) 1027 1.9 christos any[Cpu64].value = 0; 1028 1.9 christos 1029 1.9 christos for (i = 0; i < len; ++i) 1030 1.9 christos { 1031 1.9 christos /* Don't emit #define-s for auxiliary entries. */ 1032 1.9 christos if (name[i] == ':') 1033 1.9 christos return; 1034 1.9 christos upper[i] = TOUPPER (name[i]); 1035 1.9 christos } 1036 1.9 christos upper[i] = '\0'; 1037 1.9 christos fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n", 1038 1.9 christos flag != NULL ? "": "ANY_", upper); 1039 1.9 christos free (upper); 1040 1.9 christos } 1041 1.9 christos else 1042 1.9 christos { 1043 1.9 christos /* Synthesize "64-bit mode only" dependencies from the dependencies we 1044 1.9 christos have accumulated. */ 1045 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i) 1046 1.9 christos if (all[i].value && isa_reverse_deps[Cpu64][i]) 1047 1.9 christos all[Cpu64].value = 1; 1048 1.9 christos 1049 1.9 christos output_cpu_flags(table, all, ARRAY_SIZE (all), -1, comma, indent, lineno); 1050 1.10 christos 1051 1.10 christos /* For APX_F extension of multiple cpuid enabled insns, we cannot use 1052 1.10 christos APX_F(cpuid_A&cpuid_B) in the opcode table, as the result would fail 1053 1.10 christos to be parsed. Furthermore, the result also wouldn't be quite valid. 1054 1.10 christos However, the assembler's cpu_flags_match() will simply propagate "any" 1055 1.10 christos to "all", zapping "any" afterwards altogether. IOW in this situation 1056 1.10 christos both masks have "&&" meaning. Set the missing flag here. */ 1057 1.10 christos if (all[CpuAMX_TRANSPOSE].value && all[CpuAMX_MOVRS].value) 1058 1.10 christos { 1059 1.10 christos if (!any[CpuAPX_F].value || !any[CpuAMX_MOVRS].value) 1060 1.10 christos fail ("%s: %d: internal error: APX_F=%d AMX_MOVRS=%d\n", 1061 1.10 christos filename, lineno, any[CpuAPX_F].value, any[CpuAMX_MOVRS].value); 1062 1.10 christos any[CpuAMX_TRANSPOSE].value = 1; 1063 1.10 christos } 1064 1.9 christos } 1065 1.9 christos 1066 1.9 christos output_cpu_flags (table, any, ARRAY_SIZE (any), name != NULL, 1067 1.9 christos comma, indent, lineno); 1068 1.1 christos } 1069 1.1 christos 1070 1.1 christos static void 1071 1.1 christos output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size) 1072 1.1 christos { 1073 1.1 christos unsigned int i; 1074 1.1 christos 1075 1.1 christos fprintf (table, " { "); 1076 1.1 christos 1077 1.1 christos for (i = 0; i < size - 1; i++) 1078 1.1 christos { 1079 1.3 christos if (((i + 1) % 20) != 0) 1080 1.3 christos fprintf (table, "%d, ", modifier[i].value); 1081 1.3 christos else 1082 1.3 christos fprintf (table, "%d,", modifier[i].value); 1083 1.1 christos if (((i + 1) % 20) == 0) 1084 1.1 christos fprintf (table, "\n "); 1085 1.1 christos } 1086 1.1 christos 1087 1.1 christos fprintf (table, "%d },\n", modifier[i].value); 1088 1.1 christos } 1089 1.1 christos 1090 1.9 christos /* Returns LOG2 of element size. */ 1091 1.7 christos static int 1092 1.9 christos get_element_size (char **opnd, int lineno) 1093 1.7 christos { 1094 1.7 christos char *str, *next, *last, *op; 1095 1.9 christos const char *full = opnd[0]; 1096 1.9 christos int elem_size = INT_MAX; 1097 1.7 christos 1098 1.9 christos /* Find the memory operand. */ 1099 1.9 christos while (full != NULL && strstr(full, "BaseIndex") == NULL) 1100 1.9 christos full = *++opnd; 1101 1.9 christos if (full == NULL) 1102 1.9 christos fail ("%s: %d: no memory operand\n", filename, lineno); 1103 1.7 christos 1104 1.9 christos op = xstrdup (full); 1105 1.7 christos last = op + strlen (op); 1106 1.7 christos for (next = op; next && next < last; ) 1107 1.7 christos { 1108 1.7 christos str = next_field (next, '|', &next, last); 1109 1.7 christos if (str) 1110 1.7 christos { 1111 1.7 christos if (strcasecmp(str, "Byte") == 0) 1112 1.7 christos { 1113 1.9 christos /* The smallest element size, no need to check 1114 1.7 christos further. */ 1115 1.9 christos elem_size = 0; 1116 1.7 christos break; 1117 1.7 christos } 1118 1.7 christos else if (strcasecmp(str, "Word") == 0) 1119 1.7 christos { 1120 1.9 christos if (elem_size > 1) 1121 1.9 christos elem_size = 1; 1122 1.7 christos } 1123 1.7 christos else if (strcasecmp(str, "Dword") == 0) 1124 1.7 christos { 1125 1.9 christos if (elem_size > 2) 1126 1.9 christos elem_size = 2; 1127 1.7 christos } 1128 1.7 christos else if (strcasecmp(str, "Qword") == 0) 1129 1.7 christos { 1130 1.9 christos if (elem_size > 3) 1131 1.9 christos elem_size = 3; 1132 1.7 christos } 1133 1.7 christos } 1134 1.7 christos } 1135 1.7 christos free (op); 1136 1.7 christos 1137 1.9 christos if (elem_size == INT_MAX) 1138 1.9 christos fail ("%s: %d: unknown element size: %s\n", filename, lineno, full); 1139 1.9 christos 1140 1.9 christos return elem_size; 1141 1.9 christos } 1142 1.9 christos 1143 1.9 christos static bool 1144 1.9 christos rex2_disallowed (const unsigned long long opcode, unsigned int length, 1145 1.9 christos unsigned int space, const char *cpu_flags) 1146 1.9 christos { 1147 1.9 christos /* Some opcodes encode a ModR/M-like byte directly in the opcode. */ 1148 1.9 christos unsigned int base_opcode = opcode >> (8 * length - 8); 1149 1.9 christos 1150 1.9 christos /* All opcodes listed map0 0x4*, 0x7*, 0xa*, 0xe* and map1 0x3*, 0x8* 1151 1.9 christos are reserved under REX2 and triggers #UD when prefixed with REX2 */ 1152 1.9 christos if (space == 0) 1153 1.9 christos switch (base_opcode >> 4) 1154 1.9 christos { 1155 1.9 christos case 0x4: 1156 1.9 christos case 0x7: 1157 1.9 christos case 0xA: 1158 1.9 christos case 0xE: 1159 1.9 christos return true; 1160 1.9 christos default: 1161 1.9 christos return false; 1162 1.9 christos } 1163 1.7 christos 1164 1.9 christos if (space == SPACE_0F) 1165 1.9 christos switch (base_opcode >> 4) 1166 1.9 christos { 1167 1.9 christos case 0x3: 1168 1.9 christos case 0x8: 1169 1.9 christos return true; 1170 1.9 christos default: 1171 1.9 christos return false; 1172 1.9 christos } 1173 1.9 christos 1174 1.9 christos return false; 1175 1.7 christos } 1176 1.7 christos 1177 1.1 christos static void 1178 1.8 christos process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space, 1179 1.9 christos unsigned int prefix, const char *extension_opcode, 1180 1.9 christos char **opnd, int lineno, bool rex2_disallowed) 1181 1.1 christos { 1182 1.1 christos char *str, *next, *last; 1183 1.10 christos bool disp8_shift_derived = false; 1184 1.1 christos bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; 1185 1.9 christos static const char *const spaces[] = { 1186 1.9 christos #define SPACE(n) [SPACE_##n] = #n 1187 1.9 christos SPACE(BASE), 1188 1.9 christos SPACE(0F), 1189 1.9 christos SPACE(0F38), 1190 1.9 christos SPACE(0F3A), 1191 1.10 christos SPACE(MAP4), 1192 1.10 christos SPACE(MAP5), 1193 1.10 christos SPACE(MAP6), 1194 1.10 christos SPACE(MAP7), 1195 1.9 christos SPACE(XOP08), 1196 1.9 christos SPACE(XOP09), 1197 1.9 christos SPACE(XOP0A), 1198 1.9 christos #undef SPACE 1199 1.9 christos }; 1200 1.1 christos 1201 1.6 christos active_isstring = 0; 1202 1.6 christos 1203 1.1 christos /* Copy the default opcode modifier. */ 1204 1.1 christos memcpy (modifiers, opcode_modifiers, sizeof (modifiers)); 1205 1.1 christos 1206 1.1 christos if (strcmp (mod, "0")) 1207 1.1 christos { 1208 1.7 christos unsigned int have_w = 0, bwlq_suf = 0xf; 1209 1.7 christos 1210 1.1 christos last = mod + strlen (mod); 1211 1.1 christos for (next = mod; next && next < last; ) 1212 1.1 christos { 1213 1.1 christos str = next_field (next, '|', &next, last); 1214 1.1 christos if (str) 1215 1.6 christos { 1216 1.7 christos int val = 1; 1217 1.9 christos 1218 1.9 christos if (strncmp(str, "OpcodeSpace", 11) == 0) 1219 1.9 christos { 1220 1.9 christos char *end; 1221 1.9 christos 1222 1.9 christos if (str[11] != '=') 1223 1.9 christos fail ("%s:%d: Missing value for `OpcodeSpace'\n", 1224 1.9 christos filename, lineno); 1225 1.9 christos 1226 1.9 christos val = strtol (str + 12, &end, 0); 1227 1.9 christos if (*end) 1228 1.9 christos fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n", 1229 1.9 christos filename, lineno, end); 1230 1.9 christos 1231 1.9 christos if (space) 1232 1.9 christos { 1233 1.9 christos if (val != space) 1234 1.9 christos fail ("%s:%d: Conflicting opcode space specifications\n", 1235 1.9 christos filename, lineno); 1236 1.9 christos fprintf (stderr, 1237 1.9 christos "%s:%d: Warning: redundant opcode space specification\n", 1238 1.9 christos filename, lineno); 1239 1.9 christos } 1240 1.9 christos 1241 1.9 christos space = val; 1242 1.9 christos continue; 1243 1.9 christos } 1244 1.9 christos 1245 1.7 christos if (strcasecmp(str, "Broadcast") == 0) 1246 1.9 christos val = get_element_size (opnd, lineno) + BYTE_BROADCAST; 1247 1.9 christos else if (strcasecmp(str, "Disp8MemShift") == 0) 1248 1.10 christos { 1249 1.10 christos val = get_element_size (opnd, lineno); 1250 1.10 christos disp8_shift_derived = true; 1251 1.10 christos } 1252 1.8 christos 1253 1.7 christos set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers), 1254 1.8 christos lineno); 1255 1.6 christos if (strcasecmp(str, "IsString") == 0) 1256 1.6 christos active_isstring = 1; 1257 1.7 christos 1258 1.7 christos if (strcasecmp(str, "W") == 0) 1259 1.7 christos have_w = 1; 1260 1.7 christos 1261 1.7 christos if (strcasecmp(str, "No_bSuf") == 0) 1262 1.7 christos bwlq_suf &= ~1; 1263 1.7 christos if (strcasecmp(str, "No_wSuf") == 0) 1264 1.7 christos bwlq_suf &= ~2; 1265 1.7 christos if (strcasecmp(str, "No_lSuf") == 0) 1266 1.7 christos bwlq_suf &= ~4; 1267 1.7 christos if (strcasecmp(str, "No_qSuf") == 0) 1268 1.7 christos bwlq_suf &= ~8; 1269 1.6 christos } 1270 1.1 christos } 1271 1.7 christos 1272 1.8 christos if (prefix) 1273 1.8 christos { 1274 1.8 christos if (!modifiers[OpcodePrefix].value) 1275 1.8 christos modifiers[OpcodePrefix].value = prefix; 1276 1.8 christos else if (modifiers[OpcodePrefix].value != prefix) 1277 1.9 christos fail ("%s:%d: Conflicting prefix specifications\n", 1278 1.8 christos filename, lineno); 1279 1.8 christos else 1280 1.8 christos fprintf (stderr, 1281 1.9 christos "%s:%d: Warning: redundant prefix specification\n", 1282 1.8 christos filename, lineno); 1283 1.8 christos } 1284 1.8 christos 1285 1.7 christos if (have_w && !bwlq_suf) 1286 1.7 christos fail ("%s: %d: stray W modifier\n", filename, lineno); 1287 1.7 christos if (have_w && !(bwlq_suf & 1)) 1288 1.7 christos fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n", 1289 1.7 christos filename, lineno); 1290 1.7 christos if (have_w && !(bwlq_suf & ~1)) 1291 1.7 christos fprintf (stderr, 1292 1.7 christos "%s: %d: W modifier without Word/Dword/Qword operand(s)\n", 1293 1.7 christos filename, lineno); 1294 1.1 christos } 1295 1.9 christos 1296 1.9 christos if (space >= ARRAY_SIZE (spaces) || !spaces[space]) 1297 1.9 christos fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space); 1298 1.9 christos 1299 1.9 christos fprintf (table, " SPACE_%s, %s,\n", 1300 1.9 christos spaces[space], extension_opcode ? extension_opcode : "None"); 1301 1.9 christos 1302 1.9 christos /* Rather than evaluating multiple conditions at runtime to determine 1303 1.9 christos whether an EVEX encoding is being dealt with, derive that information 1304 1.10 christos right here. A missing EVex attribute means "dynamic". There's one 1305 1.10 christos exception though: A value-less Disp8MemShift needs zapping rather than 1306 1.10 christos respecting if no other attribute indicates EVEX encoding. This is for 1307 1.10 christos certain SSE2AVX templatized templates to work reasonably. */ 1308 1.10 christos if (!modifiers[EVex].value) 1309 1.10 christos { 1310 1.10 christos if (modifiers[Broadcast].value 1311 1.9 christos || modifiers[Masking].value 1312 1.10 christos || modifiers[SAE].value) 1313 1.10 christos modifiers[EVex].value = EVEXDYN; 1314 1.10 christos else if (disp8_shift_derived) 1315 1.10 christos modifiers[Disp8MemShift].value = 0; 1316 1.10 christos else if (modifiers[Disp8MemShift].value) 1317 1.10 christos modifiers[EVex].value = EVEXDYN; 1318 1.10 christos } 1319 1.9 christos 1320 1.9 christos /* Vex, legacy map2 and map3 and rex2_disallowed do not support EGPR. 1321 1.9 christos For templates supporting both Vex and EVex allowing EGPR. */ 1322 1.9 christos if ((modifiers[Vex].value || space > SPACE_0F || rex2_disallowed) 1323 1.9 christos && !modifiers[EVex].value) 1324 1.9 christos modifiers[NoEgpr].value = 1; 1325 1.9 christos 1326 1.1 christos output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers)); 1327 1.1 christos } 1328 1.1 christos 1329 1.6 christos enum stage { 1330 1.6 christos stage_macros, 1331 1.6 christos stage_opcodes, 1332 1.6 christos stage_registers, 1333 1.6 christos }; 1334 1.6 christos 1335 1.1 christos static void 1336 1.7 christos output_operand_type (FILE *table, enum operand_class class, 1337 1.7 christos enum operand_instance instance, 1338 1.7 christos const bitfield *types, unsigned int size, 1339 1.6 christos enum stage stage, const char *indent) 1340 1.1 christos { 1341 1.1 christos unsigned int i; 1342 1.1 christos 1343 1.7 christos fprintf (table, "{ { %d, %d, ", class, instance); 1344 1.1 christos 1345 1.1 christos for (i = 0; i < size - 1; i++) 1346 1.1 christos { 1347 1.7 christos if (((i + 3) % 20) != 0) 1348 1.3 christos fprintf (table, "%d, ", types[i].value); 1349 1.3 christos else 1350 1.3 christos fprintf (table, "%d,", types[i].value); 1351 1.7 christos if (((i + 3) % 20) == 0) 1352 1.1 christos { 1353 1.1 christos /* We need \\ for macro. */ 1354 1.6 christos if (stage == stage_macros) 1355 1.3 christos fprintf (table, " \\\n%s", indent); 1356 1.1 christos else 1357 1.1 christos fprintf (table, "\n%s", indent); 1358 1.1 christos } 1359 1.1 christos } 1360 1.1 christos 1361 1.1 christos fprintf (table, "%d } }", types[i].value); 1362 1.1 christos } 1363 1.1 christos 1364 1.1 christos static void 1365 1.6 christos process_i386_operand_type (FILE *table, char *op, enum stage stage, 1366 1.1 christos const char *indent, int lineno) 1367 1.1 christos { 1368 1.1 christos char *str, *next, *last; 1369 1.7 christos enum operand_class class = ClassNone; 1370 1.7 christos enum operand_instance instance = InstanceNone; 1371 1.1 christos bitfield types [ARRAY_SIZE (operand_types)]; 1372 1.1 christos 1373 1.1 christos /* Copy the default operand type. */ 1374 1.1 christos memcpy (types, operand_types, sizeof (types)); 1375 1.1 christos 1376 1.1 christos if (strcmp (op, "0")) 1377 1.1 christos { 1378 1.6 christos int baseindex = 0; 1379 1.6 christos 1380 1.1 christos last = op + strlen (op); 1381 1.1 christos for (next = op; next && next < last; ) 1382 1.1 christos { 1383 1.1 christos str = next_field (next, '|', &next, last); 1384 1.1 christos if (str) 1385 1.6 christos { 1386 1.7 christos unsigned int i; 1387 1.7 christos 1388 1.7 christos if (!strncmp(str, "Class=", 6)) 1389 1.7 christos { 1390 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_classes); ++i) 1391 1.7 christos if (!strcmp(str + 6, operand_classes[i].name)) 1392 1.7 christos { 1393 1.7 christos class = operand_classes[i].value; 1394 1.7 christos str = NULL; 1395 1.7 christos break; 1396 1.7 christos } 1397 1.7 christos } 1398 1.7 christos 1399 1.7 christos if (str && !strncmp(str, "Instance=", 9)) 1400 1.7 christos { 1401 1.7 christos for (i = 0; i < ARRAY_SIZE(operand_instances); ++i) 1402 1.7 christos if (!strcmp(str + 9, operand_instances[i].name)) 1403 1.7 christos { 1404 1.7 christos instance = operand_instances[i].value; 1405 1.7 christos str = NULL; 1406 1.7 christos break; 1407 1.7 christos } 1408 1.7 christos } 1409 1.7 christos } 1410 1.7 christos if (str) 1411 1.7 christos { 1412 1.6 christos set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno); 1413 1.6 christos if (strcasecmp(str, "BaseIndex") == 0) 1414 1.6 christos baseindex = 1; 1415 1.6 christos } 1416 1.6 christos } 1417 1.6 christos 1418 1.6 christos if (stage == stage_opcodes && baseindex && !active_isstring) 1419 1.6 christos { 1420 1.6 christos set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno); 1421 1.6 christos if (!active_cpu_flags.bitfield.cpu64 1422 1.6 christos && !active_cpu_flags.bitfield.cpumpx) 1423 1.6 christos set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno); 1424 1.8 christos set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno); 1425 1.1 christos } 1426 1.1 christos } 1427 1.7 christos output_operand_type (table, class, instance, types, ARRAY_SIZE (types), 1428 1.7 christos stage, indent); 1429 1.1 christos } 1430 1.1 christos 1431 1.9 christos static char *mkident (const char *mnem) 1432 1.9 christos { 1433 1.9 christos char *ident = xstrdup (mnem), *p = ident; 1434 1.9 christos 1435 1.9 christos do 1436 1.9 christos { 1437 1.9 christos if (!ISALNUM (*p)) 1438 1.9 christos *p = '_'; 1439 1.9 christos } 1440 1.9 christos while (*++p); 1441 1.9 christos 1442 1.9 christos return ident; 1443 1.9 christos } 1444 1.9 christos 1445 1.1 christos static void 1446 1.1 christos output_i386_opcode (FILE *table, const char *name, char *str, 1447 1.1 christos char *last, int lineno) 1448 1.1 christos { 1449 1.8 christos unsigned int i, length, prefix = 0, space = 0; 1450 1.9 christos char *base_opcode, *extension_opcode, *end, *ident; 1451 1.1 christos char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS]; 1452 1.8 christos unsigned long long opcode; 1453 1.1 christos 1454 1.1 christos /* Find base_opcode. */ 1455 1.1 christos base_opcode = next_field (str, ',', &str, last); 1456 1.1 christos 1457 1.9 christos /* Find extension_opcode, if any. */ 1458 1.9 christos extension_opcode = strchr (base_opcode, '/'); 1459 1.9 christos if (extension_opcode) 1460 1.9 christos *extension_opcode++ = '\0'; 1461 1.1 christos 1462 1.1 christos /* Find cpu_flags. */ 1463 1.1 christos cpu_flags = next_field (str, ',', &str, last); 1464 1.1 christos 1465 1.1 christos /* Find opcode_modifier. */ 1466 1.1 christos opcode_modifier = next_field (str, ',', &str, last); 1467 1.1 christos 1468 1.1 christos /* Remove the first {. */ 1469 1.1 christos str = remove_leading_whitespaces (str); 1470 1.1 christos if (*str != '{') 1471 1.1 christos abort (); 1472 1.1 christos str = remove_leading_whitespaces (str + 1); 1473 1.8 christos remove_trailing_whitespaces (str); 1474 1.1 christos 1475 1.8 christos /* Remove } and trailing white space. */ 1476 1.1 christos i = strlen (str); 1477 1.8 christos if (!i || str[i - 1] != '}') 1478 1.1 christos abort (); 1479 1.8 christos str[--i] = '\0'; 1480 1.8 christos remove_trailing_whitespaces (str); 1481 1.1 christos 1482 1.8 christos if (!*str) 1483 1.8 christos operand_types [i = 0] = NULL; 1484 1.8 christos else 1485 1.1 christos { 1486 1.8 christos last = str + strlen (str); 1487 1.8 christos 1488 1.8 christos /* Find operand_types. */ 1489 1.8 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++) 1490 1.8 christos { 1491 1.8 christos if (str >= last) 1492 1.8 christos { 1493 1.8 christos operand_types [i] = NULL; 1494 1.8 christos break; 1495 1.8 christos } 1496 1.8 christos 1497 1.8 christos operand_types [i] = next_field (str, ',', &str, last); 1498 1.8 christos } 1499 1.1 christos } 1500 1.1 christos 1501 1.8 christos opcode = strtoull (base_opcode, &end, 0); 1502 1.1 christos 1503 1.8 christos /* Determine opcode length. */ 1504 1.8 christos for (length = 1; length < 8; ++length) 1505 1.8 christos if (!(opcode >> (8 * length))) 1506 1.8 christos break; 1507 1.8 christos 1508 1.8 christos /* Transform prefixes encoded in the opcode into opcode modifier 1509 1.8 christos representation. */ 1510 1.8 christos if (length > 1) 1511 1.1 christos { 1512 1.8 christos switch (opcode >> (8 * length - 8)) 1513 1.1 christos { 1514 1.8 christos case 0x66: prefix = PREFIX_0X66; break; 1515 1.8 christos case 0xF3: prefix = PREFIX_0XF3; break; 1516 1.8 christos case 0xF2: prefix = PREFIX_0XF2; break; 1517 1.1 christos } 1518 1.1 christos 1519 1.8 christos if (prefix) 1520 1.8 christos opcode &= (1ULL << (8 * --length)) - 1; 1521 1.8 christos } 1522 1.8 christos 1523 1.8 christos /* Transform opcode space encoded in the opcode into opcode modifier 1524 1.8 christos representation. */ 1525 1.8 christos if (length > 1 && (opcode >> (8 * length - 8)) == 0xf) 1526 1.8 christos { 1527 1.8 christos switch ((opcode >> (8 * length - 16)) & 0xff) 1528 1.1 christos { 1529 1.8 christos default: space = SPACE_0F; break; 1530 1.8 christos case 0x38: space = SPACE_0F38; break; 1531 1.8 christos case 0x3A: space = SPACE_0F3A; break; 1532 1.1 christos } 1533 1.8 christos 1534 1.8 christos if (space != SPACE_0F && --length == 1) 1535 1.9 christos fail ("%s:%d: %s: unrecognized opcode encoding space\n", 1536 1.8 christos filename, lineno, name); 1537 1.8 christos opcode &= (1ULL << (8 * --length)) - 1; 1538 1.1 christos } 1539 1.1 christos 1540 1.8 christos if (length > 2) 1541 1.9 christos fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n", 1542 1.8 christos filename, lineno, name, 2 * length, opcode); 1543 1.8 christos 1544 1.9 christos ident = mkident (name); 1545 1.9 christos fprintf (table, " { MN_%s, 0x%0*llx%s, %u,", 1546 1.9 christos ident, 2 * (int)length, opcode, end, i); 1547 1.9 christos free (ident); 1548 1.8 christos 1549 1.8 christos process_i386_opcode_modifier (table, opcode_modifier, space, prefix, 1550 1.9 christos extension_opcode, operand_types, lineno, 1551 1.9 christos rex2_disallowed (opcode, length, space, 1552 1.9 christos cpu_flags)); 1553 1.1 christos 1554 1.9 christos process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax); 1555 1.1 christos 1556 1.1 christos fprintf (table, " { "); 1557 1.1 christos 1558 1.1 christos for (i = 0; i < ARRAY_SIZE (operand_types); i++) 1559 1.1 christos { 1560 1.8 christos if (!operand_types[i]) 1561 1.1 christos { 1562 1.1 christos if (i == 0) 1563 1.6 christos process_i386_operand_type (table, "0", stage_opcodes, "\t ", 1564 1.6 christos lineno); 1565 1.1 christos break; 1566 1.1 christos } 1567 1.1 christos 1568 1.1 christos if (i != 0) 1569 1.1 christos fprintf (table, ",\n "); 1570 1.1 christos 1571 1.6 christos process_i386_operand_type (table, operand_types[i], stage_opcodes, 1572 1.1 christos "\t ", lineno); 1573 1.1 christos } 1574 1.1 christos fprintf (table, " } },\n"); 1575 1.1 christos } 1576 1.1 christos 1577 1.1 christos struct opcode_hash_entry 1578 1.1 christos { 1579 1.9 christos const char *name; 1580 1.9 christos struct opcode_entry 1581 1.9 christos { 1582 1.9 christos struct opcode_entry *next; 1583 1.9 christos char *opcode; 1584 1.9 christos int lineno; 1585 1.9 christos } entry; 1586 1.1 christos }; 1587 1.1 christos 1588 1.1 christos /* Calculate the hash value of an opcode hash entry P. */ 1589 1.1 christos 1590 1.1 christos static hashval_t 1591 1.1 christos opcode_hash_hash (const void *p) 1592 1.1 christos { 1593 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p; 1594 1.1 christos return htab_hash_string (entry->name); 1595 1.1 christos } 1596 1.1 christos 1597 1.1 christos /* Compare a string Q against an opcode hash entry P. */ 1598 1.1 christos 1599 1.1 christos static int 1600 1.1 christos opcode_hash_eq (const void *p, const void *q) 1601 1.1 christos { 1602 1.1 christos struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p; 1603 1.1 christos const char *name = (const char *) q; 1604 1.1 christos return strcmp (name, entry->name) == 0; 1605 1.1 christos } 1606 1.1 christos 1607 1.10 christos static bool 1608 1.8 christos parse_template (char *buf, int lineno) 1609 1.8 christos { 1610 1.10 christos char sep, *end, *ptr; 1611 1.9 christos struct template *tmpl; 1612 1.8 christos struct template_instance *last_inst = NULL; 1613 1.8 christos 1614 1.8 christos buf = remove_leading_whitespaces (buf + 1); 1615 1.8 christos end = strchr (buf, ':'); 1616 1.8 christos if (end == NULL) 1617 1.9 christos { 1618 1.9 christos struct template *prev = NULL; 1619 1.9 christos 1620 1.9 christos end = strchr (buf, '>'); 1621 1.9 christos if (end == NULL) 1622 1.9 christos fail ("%s: %d: missing ':' or '>'\n", filename, lineno); 1623 1.9 christos if (*remove_leading_whitespaces (end + 1)) 1624 1.9 christos fail ("%s: %d: malformed template purge\n", filename, lineno); 1625 1.9 christos *end = '\0'; 1626 1.9 christos remove_trailing_whitespaces (buf); 1627 1.9 christos /* Don't bother freeing the various structures. */ 1628 1.9 christos for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next) 1629 1.9 christos if (!strcmp (buf, tmpl->name)) 1630 1.9 christos break; 1631 1.9 christos if (tmpl == NULL) 1632 1.9 christos fail ("%s: %d: no template '%s'\n", filename, lineno, buf); 1633 1.9 christos if (prev) 1634 1.9 christos prev->next = tmpl->next; 1635 1.9 christos else 1636 1.9 christos templates = tmpl->next; 1637 1.10 christos return true; 1638 1.9 christos } 1639 1.10 christos 1640 1.10 christos /* Check whether this actually is a reference to an existing template: 1641 1.10 christos If there's '>' ahead of ':', it can't be a new template definition 1642 1.10 christos (and template undefs have are dealt with above). */ 1643 1.10 christos ptr = strchr (buf, '>'); 1644 1.10 christos if (ptr != NULL && ptr < end) 1645 1.10 christos return false; 1646 1.10 christos 1647 1.8 christos *end++ = '\0'; 1648 1.8 christos remove_trailing_whitespaces (buf); 1649 1.8 christos 1650 1.8 christos if (*buf == '\0') 1651 1.8 christos fail ("%s: %d: missing template identifier\n", filename, lineno); 1652 1.9 christos tmpl = xmalloc (sizeof (*tmpl)); 1653 1.8 christos tmpl->name = xstrdup (buf); 1654 1.8 christos 1655 1.8 christos tmpl->params = NULL; 1656 1.8 christos do { 1657 1.8 christos struct template_param *param; 1658 1.8 christos 1659 1.8 christos buf = remove_leading_whitespaces (end); 1660 1.8 christos end = strpbrk (buf, ":,"); 1661 1.8 christos if (end == NULL) 1662 1.8 christos fail ("%s: %d: missing ':' or ','\n", filename, lineno); 1663 1.8 christos 1664 1.8 christos sep = *end; 1665 1.8 christos *end++ = '\0'; 1666 1.8 christos remove_trailing_whitespaces (buf); 1667 1.8 christos 1668 1.8 christos param = xmalloc (sizeof (*param)); 1669 1.8 christos param->name = xstrdup (buf); 1670 1.8 christos param->next = tmpl->params; 1671 1.8 christos tmpl->params = param; 1672 1.8 christos } while (sep == ':'); 1673 1.8 christos 1674 1.8 christos tmpl->instances = NULL; 1675 1.8 christos do { 1676 1.8 christos struct template_instance *inst; 1677 1.8 christos char *cur, *next; 1678 1.8 christos const struct template_param *param; 1679 1.8 christos 1680 1.8 christos buf = remove_leading_whitespaces (end); 1681 1.8 christos end = strpbrk (buf, ",>"); 1682 1.8 christos if (end == NULL) 1683 1.8 christos fail ("%s: %d: missing ',' or '>'\n", filename, lineno); 1684 1.8 christos 1685 1.8 christos sep = *end; 1686 1.8 christos *end++ = '\0'; 1687 1.8 christos 1688 1.8 christos inst = xmalloc (sizeof (*inst)); 1689 1.8 christos inst->next = NULL; 1690 1.8 christos inst->args = NULL; 1691 1.8 christos 1692 1.8 christos cur = next_field (buf, ':', &next, end); 1693 1.8 christos inst->name = *cur != '$' ? xstrdup (cur) : ""; 1694 1.8 christos 1695 1.8 christos for (param = tmpl->params; param; param = param->next) 1696 1.8 christos { 1697 1.8 christos struct template_arg *arg = xmalloc (sizeof (*arg)); 1698 1.8 christos 1699 1.8 christos cur = next_field (next, ':', &next, end); 1700 1.8 christos if (next > end) 1701 1.8 christos fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name); 1702 1.8 christos arg->val = xstrdup (cur); 1703 1.8 christos arg->next = inst->args; 1704 1.8 christos inst->args = arg; 1705 1.8 christos } 1706 1.8 christos 1707 1.8 christos if (tmpl->instances) 1708 1.8 christos last_inst->next = inst; 1709 1.8 christos else 1710 1.8 christos tmpl->instances = inst; 1711 1.8 christos last_inst = inst; 1712 1.8 christos } while (sep == ','); 1713 1.8 christos 1714 1.8 christos buf = remove_leading_whitespaces (end); 1715 1.8 christos if (*buf) 1716 1.8 christos fprintf(stderr, "%s: %d: excess characters '%s'\n", 1717 1.8 christos filename, lineno, buf); 1718 1.8 christos 1719 1.8 christos tmpl->next = templates; 1720 1.8 christos templates = tmpl; 1721 1.10 christos 1722 1.10 christos return true; 1723 1.10 christos } 1724 1.10 christos 1725 1.10 christos static void 1726 1.10 christos expand_template (const struct template *tmpl, 1727 1.10 christos const struct template_instance *inst, 1728 1.10 christos char *dst, const char *src, int lineno) 1729 1.10 christos { 1730 1.10 christos while (*src) 1731 1.10 christos { 1732 1.10 christos const char *ident = tmpl->name, *end; 1733 1.10 christos const struct template_param *param; 1734 1.10 christos const struct template_arg *arg; 1735 1.10 christos 1736 1.10 christos if ((*dst = *src++) != '<') 1737 1.10 christos { 1738 1.10 christos ++dst; 1739 1.10 christos continue; 1740 1.10 christos } 1741 1.10 christos while (ISSPACE(*src)) 1742 1.10 christos ++src; 1743 1.10 christos while (*ident && *src == *ident) 1744 1.10 christos ++src, ++ident; 1745 1.10 christos while (ISSPACE(*src)) 1746 1.10 christos ++src; 1747 1.10 christos if (*src != ':' || *ident != '\0') 1748 1.10 christos { 1749 1.10 christos memcpy (++dst, tmpl->name, ident - tmpl->name); 1750 1.10 christos dst += ident - tmpl->name; 1751 1.10 christos continue; 1752 1.10 christos } 1753 1.10 christos while (ISSPACE(*++src)) 1754 1.10 christos ; 1755 1.10 christos 1756 1.10 christos end = src; 1757 1.10 christos while (*end != '\0' && !ISSPACE(*end) && *end != '>') 1758 1.10 christos ++end; 1759 1.10 christos 1760 1.10 christos for (param = tmpl->params, arg = inst->args; param; 1761 1.10 christos param = param->next, arg = arg->next) 1762 1.10 christos { 1763 1.10 christos if (end - src == strlen (param->name) 1764 1.10 christos && !memcmp (src, param->name, end - src)) 1765 1.10 christos { 1766 1.10 christos src = end; 1767 1.10 christos break; 1768 1.10 christos } 1769 1.10 christos } 1770 1.10 christos 1771 1.10 christos if (param == NULL) 1772 1.10 christos fail ("template '%s' has no parameter '%.*s'\n", 1773 1.10 christos tmpl->name, (int)(end - src), src); 1774 1.10 christos 1775 1.10 christos while (ISSPACE(*src)) 1776 1.10 christos ++src; 1777 1.10 christos if (*src != '>') 1778 1.10 christos fail ("%s: %d: missing '>'\n", filename, lineno); 1779 1.10 christos 1780 1.10 christos memcpy(dst, arg->val, strlen(arg->val)); 1781 1.10 christos dst += strlen(arg->val); 1782 1.10 christos ++src; 1783 1.10 christos } 1784 1.10 christos 1785 1.10 christos *dst = '\0'; 1786 1.8 christos } 1787 1.8 christos 1788 1.8 christos static unsigned int 1789 1.8 christos expand_templates (char *name, const char *str, htab_t opcode_hash_table, 1790 1.8 christos struct opcode_hash_entry ***opcode_array_p, int lineno) 1791 1.8 christos { 1792 1.8 christos static unsigned int idx, opcode_array_size; 1793 1.8 christos struct opcode_hash_entry **opcode_array = *opcode_array_p; 1794 1.9 christos struct opcode_hash_entry **hash_slot; 1795 1.9 christos struct opcode_entry *entry; 1796 1.8 christos char *ptr1 = strchr(name, '<'), *ptr2; 1797 1.8 christos 1798 1.8 christos if (ptr1 == NULL) 1799 1.8 christos { 1800 1.8 christos /* Get the slot in hash table. */ 1801 1.8 christos hash_slot = (struct opcode_hash_entry **) 1802 1.8 christos htab_find_slot_with_hash (opcode_hash_table, name, 1803 1.8 christos htab_hash_string (name), 1804 1.8 christos INSERT); 1805 1.8 christos 1806 1.8 christos if (*hash_slot == NULL) 1807 1.8 christos { 1808 1.8 christos /* It is the new one. Put it on opcode array. */ 1809 1.8 christos if (idx >= opcode_array_size) 1810 1.8 christos { 1811 1.8 christos /* Grow the opcode array when needed. */ 1812 1.8 christos opcode_array_size += 1024; 1813 1.8 christos opcode_array = (struct opcode_hash_entry **) 1814 1.8 christos xrealloc (opcode_array, 1815 1.8 christos sizeof (*opcode_array) * opcode_array_size); 1816 1.8 christos *opcode_array_p = opcode_array; 1817 1.8 christos } 1818 1.8 christos 1819 1.8 christos opcode_array[idx] = (struct opcode_hash_entry *) 1820 1.8 christos xmalloc (sizeof (struct opcode_hash_entry)); 1821 1.8 christos opcode_array[idx]->name = xstrdup (name); 1822 1.8 christos *hash_slot = opcode_array[idx]; 1823 1.9 christos entry = &opcode_array[idx]->entry; 1824 1.8 christos idx++; 1825 1.8 christos } 1826 1.8 christos else 1827 1.8 christos { 1828 1.8 christos /* Append it to the existing one. */ 1829 1.9 christos struct opcode_entry **entryp = &(*hash_slot)->entry.next; 1830 1.9 christos 1831 1.9 christos while (*entryp != NULL) 1832 1.9 christos entryp = &(*entryp)->next; 1833 1.9 christos entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry)); 1834 1.9 christos *entryp = entry; 1835 1.8 christos } 1836 1.9 christos 1837 1.9 christos entry->next = NULL; 1838 1.9 christos entry->opcode = xstrdup (str); 1839 1.9 christos entry->lineno = lineno; 1840 1.8 christos } 1841 1.8 christos else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL) 1842 1.8 christos fail ("%s: %d: missing '>'\n", filename, lineno); 1843 1.8 christos else 1844 1.8 christos { 1845 1.8 christos const struct template *tmpl; 1846 1.8 christos const struct template_instance *inst; 1847 1.8 christos 1848 1.8 christos *ptr1 = '\0'; 1849 1.8 christos ptr1 = remove_leading_whitespaces (ptr1 + 1); 1850 1.8 christos remove_trailing_whitespaces (ptr1); 1851 1.8 christos 1852 1.8 christos *ptr2++ = '\0'; 1853 1.8 christos 1854 1.8 christos for ( tmpl = templates; tmpl; tmpl = tmpl->next ) 1855 1.8 christos if (!strcmp(ptr1, tmpl->name)) 1856 1.8 christos break; 1857 1.8 christos if (!tmpl) 1858 1.8 christos fail ("reference to unknown template '%s'\n", ptr1); 1859 1.8 christos 1860 1.8 christos for (inst = tmpl->instances; inst; inst = inst->next) 1861 1.8 christos { 1862 1.10 christos char *name2 = xmalloc(strlen(name) + strlen(inst->name) 1863 1.10 christos + 2 * strlen(ptr2) + 1); 1864 1.8 christos char *str2 = xmalloc(2 * strlen(str)); 1865 1.8 christos 1866 1.10 christos ptr1 = stpcpy (name2, name); 1867 1.10 christos ptr1 = stpcpy (ptr1, inst->name); 1868 1.8 christos 1869 1.10 christos /* Expand this template in trailing portion of mnemonic. */ 1870 1.10 christos expand_template (tmpl, inst, ptr1, ptr2, lineno); 1871 1.8 christos 1872 1.10 christos /* Expand this template in attributes and operands. */ 1873 1.10 christos expand_template (tmpl, inst, str2, str, lineno); 1874 1.8 christos 1875 1.10 christos /* Expand further templates, if any. */ 1876 1.8 christos expand_templates (name2, str2, opcode_hash_table, opcode_array_p, 1877 1.8 christos lineno); 1878 1.8 christos 1879 1.8 christos free (str2); 1880 1.8 christos free (name2); 1881 1.8 christos } 1882 1.8 christos } 1883 1.8 christos 1884 1.8 christos return idx; 1885 1.8 christos } 1886 1.8 christos 1887 1.9 christos static int mnemonic_cmp(const void *p1, const void *p2) 1888 1.9 christos { 1889 1.9 christos const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2; 1890 1.9 christos const char *s1 = (*e1)->name, *s2 = (*e2)->name; 1891 1.9 christos unsigned int i; 1892 1.9 christos size_t l1 = strlen (s1), l2 = strlen (s2); 1893 1.9 christos 1894 1.9 christos for (i = 1; i <= l1 && i <= l2; ++i) 1895 1.9 christos { 1896 1.9 christos if (s1[l1 - i] != s2[l2 - i]) 1897 1.9 christos return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i]; 1898 1.9 christos } 1899 1.9 christos 1900 1.9 christos return (int)(l1 - l2); 1901 1.9 christos } 1902 1.9 christos 1903 1.8 christos static void 1904 1.1 christos process_i386_opcodes (FILE *table) 1905 1.1 christos { 1906 1.1 christos FILE *fp; 1907 1.1 christos char buf[2048]; 1908 1.9 christos unsigned int i, j, nr, offs; 1909 1.9 christos size_t l; 1910 1.9 christos char *str, *p, *last; 1911 1.1 christos htab_t opcode_hash_table; 1912 1.8 christos struct opcode_hash_entry **opcode_array = NULL; 1913 1.7 christos int lineno = 0, marker = 0; 1914 1.1 christos 1915 1.1 christos filename = "i386-opc.tbl"; 1916 1.7 christos fp = stdin; 1917 1.1 christos 1918 1.1 christos i = 0; 1919 1.1 christos opcode_hash_table = htab_create_alloc (16, opcode_hash_hash, 1920 1.1 christos opcode_hash_eq, NULL, 1921 1.1 christos xcalloc, free); 1922 1.1 christos 1923 1.9 christos fprintf (table, "\n#include \"i386-mnem.h\"\n"); 1924 1.1 christos fprintf (table, "\n/* i386 opcode table. */\n\n"); 1925 1.9 christos fprintf (table, "static const insn_template i386_optab[] =\n{\n"); 1926 1.1 christos 1927 1.1 christos /* Put everything on opcode array. */ 1928 1.1 christos while (!feof (fp)) 1929 1.1 christos { 1930 1.9 christos char *name; 1931 1.9 christos 1932 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL) 1933 1.1 christos break; 1934 1.1 christos 1935 1.9 christos p = remove_leading_whitespaces (buf); 1936 1.9 christos 1937 1.9 christos for ( ; ; ) 1938 1.9 christos { 1939 1.9 christos lineno++; 1940 1.1 christos 1941 1.9 christos /* Skip comments. */ 1942 1.9 christos str = strstr (p, "//"); 1943 1.9 christos if (str != NULL) 1944 1.9 christos { 1945 1.9 christos str[0] = '\0'; 1946 1.9 christos remove_trailing_whitespaces (p); 1947 1.9 christos break; 1948 1.9 christos } 1949 1.1 christos 1950 1.9 christos /* Look for line continuation character. */ 1951 1.9 christos remove_trailing_whitespaces (p); 1952 1.9 christos j = strlen (buf); 1953 1.9 christos if (!j || buf[j - 1] != '+') 1954 1.9 christos break; 1955 1.9 christos if (j >= sizeof (buf) - 1) 1956 1.9 christos fail ("%s: %d: (continued) line too long\n", filename, lineno); 1957 1.1 christos 1958 1.9 christos if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL) 1959 1.9 christos { 1960 1.9 christos fprintf (stderr, "%s: Line continuation on last line?\n", 1961 1.9 christos filename); 1962 1.9 christos break; 1963 1.9 christos } 1964 1.9 christos } 1965 1.1 christos 1966 1.1 christos switch (p[0]) 1967 1.1 christos { 1968 1.1 christos case '#': 1969 1.7 christos if (!strcmp("### MARKER ###", buf)) 1970 1.7 christos marker = 1; 1971 1.7 christos else 1972 1.7 christos { 1973 1.7 christos /* Since we ignore all included files (we only care about their 1974 1.7 christos #define-s here), we don't need to monitor filenames. The final 1975 1.7 christos line number directive is going to refer to the main source file 1976 1.7 christos again. */ 1977 1.7 christos char *end; 1978 1.7 christos unsigned long ln; 1979 1.7 christos 1980 1.7 christos p = remove_leading_whitespaces (p + 1); 1981 1.7 christos if (!strncmp(p, "line", 4)) 1982 1.7 christos p += 4; 1983 1.7 christos ln = strtoul (p, &end, 10); 1984 1.7 christos if (ln > 1 && ln < INT_MAX 1985 1.7 christos && *remove_leading_whitespaces (end) == '"') 1986 1.7 christos lineno = ln - 1; 1987 1.7 christos } 1988 1.1 christos /* Ignore comments. */ 1989 1.1 christos case '\0': 1990 1.1 christos continue; 1991 1.10 christos 1992 1.10 christos case '<': 1993 1.10 christos if (parse_template (p, lineno)) 1994 1.10 christos continue; 1995 1.1 christos break; 1996 1.10 christos 1997 1.1 christos default: 1998 1.7 christos if (!marker) 1999 1.7 christos continue; 2000 1.1 christos break; 2001 1.1 christos } 2002 1.1 christos 2003 1.1 christos last = p + strlen (p); 2004 1.1 christos 2005 1.1 christos /* Find name. */ 2006 1.1 christos name = next_field (p, ',', &str, last); 2007 1.1 christos 2008 1.8 christos i = expand_templates (name, str, opcode_hash_table, &opcode_array, 2009 1.8 christos lineno); 2010 1.1 christos } 2011 1.1 christos 2012 1.1 christos /* Process opcode array. */ 2013 1.1 christos for (j = 0; j < i; j++) 2014 1.1 christos { 2015 1.9 christos const char *name = opcode_array[j]->name; 2016 1.9 christos struct opcode_entry *next; 2017 1.8 christos 2018 1.9 christos for (next = &opcode_array[j]->entry; next; next = next->next) 2019 1.1 christos { 2020 1.1 christos str = next->opcode; 2021 1.1 christos lineno = next->lineno; 2022 1.1 christos last = str + strlen (str); 2023 1.1 christos output_i386_opcode (table, name, str, last, lineno); 2024 1.1 christos } 2025 1.1 christos } 2026 1.1 christos 2027 1.1 christos fclose (fp); 2028 1.1 christos 2029 1.9 christos fprintf (table, "};\n"); 2030 1.9 christos 2031 1.9 christos /* Generate opcode sets array. */ 2032 1.9 christos fprintf (table, "\n/* i386 opcode sets table. */\n\n"); 2033 1.9 christos fprintf (table, "typedef unsigned short i386_op_off_t;\n"); 2034 1.9 christos fprintf (table, "static const i386_op_off_t i386_op_sets[] =\n{\n "); 2035 1.9 christos 2036 1.9 christos for (nr = j = 0; j < i; j++) 2037 1.9 christos { 2038 1.9 christos struct opcode_entry *next = &opcode_array[j]->entry; 2039 1.9 christos 2040 1.9 christos if ((j + 1) % 8 != 0) 2041 1.9 christos fprintf (table, "%5u,", nr); 2042 1.9 christos else 2043 1.9 christos fprintf (table, "%5u,\n ", nr); 2044 1.9 christos do 2045 1.9 christos { 2046 1.9 christos ++nr; 2047 1.9 christos next = next->next; 2048 1.9 christos } 2049 1.9 christos while (next); 2050 1.9 christos } 2051 1.9 christos 2052 1.9 christos fprintf (table, "%5u\n};\n", nr); 2053 1.9 christos 2054 1.9 christos /* Emit mnemonics and associated #define-s. */ 2055 1.9 christos qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp); 2056 1.9 christos 2057 1.9 christos fp = fopen ("i386-mnem.h", "w"); 2058 1.9 christos if (fp == NULL) 2059 1.9 christos fail ("can't create i386-mnem.h, errno = %s\n", 2060 1.9 christos xstrerror (errno)); 2061 1.8 christos 2062 1.9 christos process_copyright (fp); 2063 1.1 christos 2064 1.9 christos fprintf (table, "\n/* i386 mnemonics table. */\n\n"); 2065 1.9 christos fprintf (table, "const char i386_mnemonics[] =\n"); 2066 1.9 christos fprintf (fp, "\nextern const char i386_mnemonics[];\n\n"); 2067 1.9 christos 2068 1.9 christos str = NULL; 2069 1.9 christos for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++) 2070 1.9 christos { 2071 1.9 christos const char *name = opcode_array[j]->name; 2072 1.9 christos const char *next = NULL; 2073 1.9 christos size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0; 2074 1.9 christos 2075 1.9 christos if (str == NULL) 2076 1.9 christos str = mkident (name); 2077 1.9 christos if (l < l1 && !strcmp(name, next + l1 - l)) 2078 1.9 christos { 2079 1.9 christos fprintf (fp, "#define MN_%s ", str); 2080 1.9 christos free (str); 2081 1.9 christos str = mkident (next); 2082 1.9 christos fprintf (fp, "(MN_%s + %zu)\n", str, l1 - l); 2083 1.9 christos } 2084 1.9 christos else 2085 1.9 christos { 2086 1.9 christos fprintf (table, " \"\\0\"\"%s\"\n", name); 2087 1.9 christos fprintf (fp, "#define MN_%s %#x\n", str, offs + 1); 2088 1.9 christos offs += strlen (name) + 1; 2089 1.9 christos free (str); 2090 1.9 christos str = NULL; 2091 1.9 christos } 2092 1.9 christos l = l1; 2093 1.9 christos } 2094 1.9 christos 2095 1.9 christos fprintf (table, " \"\\0\"\".insn\"\n"); 2096 1.9 christos fprintf (fp, "#define MN__insn %#x\n", offs + 1); 2097 1.1 christos 2098 1.9 christos fprintf (table, ";\n"); 2099 1.1 christos 2100 1.9 christos fclose (fp); 2101 1.1 christos } 2102 1.1 christos 2103 1.1 christos static void 2104 1.1 christos process_i386_registers (FILE *table) 2105 1.1 christos { 2106 1.1 christos FILE *fp; 2107 1.1 christos char buf[2048]; 2108 1.1 christos char *str, *p, *last; 2109 1.1 christos char *reg_name, *reg_type, *reg_flags, *reg_num; 2110 1.1 christos char *dw2_32_num, *dw2_64_num; 2111 1.1 christos int lineno = 0; 2112 1.1 christos 2113 1.1 christos filename = "i386-reg.tbl"; 2114 1.1 christos fp = fopen (filename, "r"); 2115 1.1 christos if (fp == NULL) 2116 1.9 christos fail ("can't find i386-reg.tbl for reading, errno = %s\n", 2117 1.1 christos xstrerror (errno)); 2118 1.1 christos 2119 1.1 christos fprintf (table, "\n/* i386 register table. */\n\n"); 2120 1.9 christos fprintf (table, "static const reg_entry i386_regtab[] =\n{\n"); 2121 1.1 christos 2122 1.1 christos while (!feof (fp)) 2123 1.1 christos { 2124 1.1 christos if (fgets (buf, sizeof (buf), fp) == NULL) 2125 1.1 christos break; 2126 1.1 christos 2127 1.1 christos lineno++; 2128 1.1 christos 2129 1.1 christos p = remove_leading_whitespaces (buf); 2130 1.1 christos 2131 1.1 christos /* Skip comments. */ 2132 1.1 christos str = strstr (p, "//"); 2133 1.1 christos if (str != NULL) 2134 1.1 christos str[0] = '\0'; 2135 1.1 christos 2136 1.1 christos /* Remove trailing white spaces. */ 2137 1.1 christos remove_trailing_whitespaces (p); 2138 1.1 christos 2139 1.1 christos switch (p[0]) 2140 1.1 christos { 2141 1.1 christos case '#': 2142 1.1 christos fprintf (table, "%s\n", p); 2143 1.1 christos case '\0': 2144 1.1 christos continue; 2145 1.1 christos break; 2146 1.1 christos default: 2147 1.1 christos break; 2148 1.1 christos } 2149 1.1 christos 2150 1.1 christos last = p + strlen (p); 2151 1.1 christos 2152 1.1 christos /* Find reg_name. */ 2153 1.1 christos reg_name = next_field (p, ',', &str, last); 2154 1.1 christos 2155 1.1 christos /* Find reg_type. */ 2156 1.1 christos reg_type = next_field (str, ',', &str, last); 2157 1.1 christos 2158 1.1 christos /* Find reg_flags. */ 2159 1.1 christos reg_flags = next_field (str, ',', &str, last); 2160 1.1 christos 2161 1.1 christos /* Find reg_num. */ 2162 1.1 christos reg_num = next_field (str, ',', &str, last); 2163 1.1 christos 2164 1.1 christos fprintf (table, " { \"%s\",\n ", reg_name); 2165 1.1 christos 2166 1.6 christos process_i386_operand_type (table, reg_type, stage_registers, "\t", 2167 1.6 christos lineno); 2168 1.1 christos 2169 1.1 christos /* Find 32-bit Dwarf2 register number. */ 2170 1.1 christos dw2_32_num = next_field (str, ',', &str, last); 2171 1.1 christos 2172 1.1 christos /* Find 64-bit Dwarf2 register number. */ 2173 1.1 christos dw2_64_num = next_field (str, ',', &str, last); 2174 1.1 christos 2175 1.1 christos fprintf (table, ",\n %s, %s, { %s, %s } },\n", 2176 1.1 christos reg_flags, reg_num, dw2_32_num, dw2_64_num); 2177 1.1 christos } 2178 1.1 christos 2179 1.1 christos fclose (fp); 2180 1.1 christos 2181 1.1 christos fprintf (table, "};\n"); 2182 1.1 christos 2183 1.9 christos fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n"); 2184 1.1 christos } 2185 1.1 christos 2186 1.1 christos static void 2187 1.1 christos process_i386_initializers (void) 2188 1.1 christos { 2189 1.1 christos unsigned int i; 2190 1.1 christos FILE *fp = fopen ("i386-init.h", "w"); 2191 1.1 christos 2192 1.1 christos if (fp == NULL) 2193 1.9 christos fail ("can't create i386-init.h, errno = %s\n", 2194 1.1 christos xstrerror (errno)); 2195 1.1 christos 2196 1.1 christos process_copyright (fp); 2197 1.1 christos 2198 1.9 christos for (i = 0; i < CpuMax; i++) 2199 1.9 christos process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i); 2200 1.9 christos 2201 1.9 christos for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++) 2202 1.1 christos { 2203 1.9 christos char *deps = xstrdup (isa_dependencies[i].deps); 2204 1.9 christos 2205 1.9 christos process_i386_cpu_flag (fp, deps, isa_dependencies[i].name, 2206 1.9 christos "", " ", -1, CpuMax); 2207 1.9 christos free (deps); 2208 1.1 christos } 2209 1.1 christos 2210 1.9 christos /* Early x87 is somewhat special: Both 287 and 387 not only add new insns 2211 1.9 christos but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't 2212 1.9 christos one to 387. We want the reverse to be true though: Disabling 8087 also 2213 1.9 christos is to disable 287+ and later; disabling 287 also means disabling 387+. */ 2214 1.9 christos memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387], 2215 1.9 christos sizeof (isa_reverse_deps[0])); 2216 1.9 christos isa_reverse_deps[Cpu287][Cpu387] = 1; 2217 1.9 christos memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287], 2218 1.9 christos sizeof (isa_reverse_deps[0])); 2219 1.9 christos isa_reverse_deps[Cpu8087][Cpu287] = 1; 2220 1.9 christos 2221 1.9 christos /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not 2222 1.9 christos lead to disabling of anything else. */ 2223 1.9 christos memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0])); 2224 1.9 christos 2225 1.9 christos for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++) 2226 1.1 christos { 2227 1.9 christos size_t len; 2228 1.9 christos char *upper; 2229 1.9 christos 2230 1.9 christos if (memchr(isa_reverse_deps[i], 1, 2231 1.9 christos ARRAY_SIZE (isa_reverse_deps[0])) == NULL) 2232 1.9 christos continue; 2233 1.9 christos 2234 1.9 christos isa_reverse_deps[i][i] = 1; 2235 1.9 christos process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i); 2236 1.1 christos } 2237 1.9 christos 2238 1.1 christos fprintf (fp, "\n"); 2239 1.1 christos 2240 1.1 christos fclose (fp); 2241 1.1 christos } 2242 1.1 christos 2243 1.1 christos /* Program options. */ 2244 1.1 christos #define OPTION_SRCDIR 200 2245 1.1 christos 2246 1.1 christos struct option long_options[] = 2247 1.1 christos { 2248 1.1 christos {"srcdir", required_argument, NULL, OPTION_SRCDIR}, 2249 1.1 christos {"debug", no_argument, NULL, 'd'}, 2250 1.1 christos {"version", no_argument, NULL, 'V'}, 2251 1.1 christos {"help", no_argument, NULL, 'h'}, 2252 1.1 christos {0, no_argument, NULL, 0} 2253 1.1 christos }; 2254 1.1 christos 2255 1.1 christos static void 2256 1.1 christos print_version (void) 2257 1.1 christos { 2258 1.1 christos printf ("%s: version 1.0\n", program_name); 2259 1.1 christos xexit (0); 2260 1.1 christos } 2261 1.1 christos 2262 1.1 christos static void 2263 1.1 christos usage (FILE * stream, int status) 2264 1.1 christos { 2265 1.1 christos fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n", 2266 1.1 christos program_name); 2267 1.1 christos xexit (status); 2268 1.1 christos } 2269 1.1 christos 2270 1.1 christos int 2271 1.1 christos main (int argc, char **argv) 2272 1.1 christos { 2273 1.1 christos extern int chdir (char *); 2274 1.1 christos char *srcdir = NULL; 2275 1.1 christos int c; 2276 1.5 christos unsigned int i, cpumax; 2277 1.1 christos FILE *table; 2278 1.1 christos 2279 1.1 christos program_name = *argv; 2280 1.1 christos xmalloc_set_program_name (program_name); 2281 1.1 christos 2282 1.1 christos while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF) 2283 1.1 christos switch (c) 2284 1.1 christos { 2285 1.1 christos case OPTION_SRCDIR: 2286 1.1 christos srcdir = optarg; 2287 1.1 christos break; 2288 1.1 christos case 'V': 2289 1.1 christos case 'v': 2290 1.1 christos print_version (); 2291 1.1 christos break; 2292 1.1 christos case 'd': 2293 1.1 christos debug = 1; 2294 1.1 christos break; 2295 1.1 christos case 'h': 2296 1.1 christos case '?': 2297 1.1 christos usage (stderr, 0); 2298 1.1 christos default: 2299 1.1 christos case 0: 2300 1.1 christos break; 2301 1.1 christos } 2302 1.1 christos 2303 1.1 christos if (optind != argc) 2304 1.1 christos usage (stdout, 1); 2305 1.1 christos 2306 1.1 christos if (srcdir != NULL) 2307 1.1 christos if (chdir (srcdir) != 0) 2308 1.9 christos fail ("unable to change directory to \"%s\", errno = %s\n", 2309 1.1 christos srcdir, xstrerror (errno)); 2310 1.1 christos 2311 1.5 christos /* cpu_flags isn't sorted by position. */ 2312 1.5 christos cpumax = 0; 2313 1.5 christos for (i = 0; i < ARRAY_SIZE (cpu_flags); i++) 2314 1.5 christos if (cpu_flags[i].position > cpumax) 2315 1.5 christos cpumax = cpu_flags[i].position; 2316 1.5 christos 2317 1.1 christos /* Check the unused bitfield in i386_cpu_flags. */ 2318 1.5 christos #ifdef CpuUnused 2319 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2); 2320 1.7 christos 2321 1.5 christos if ((cpumax - 1) != CpuMax) 2322 1.9 christos fail ("CpuMax != %d!\n", cpumax); 2323 1.5 christos #else 2324 1.7 christos static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1); 2325 1.7 christos 2326 1.5 christos if (cpumax != CpuMax) 2327 1.9 christos fail ("CpuMax != %d!\n", cpumax); 2328 1.5 christos 2329 1.1 christos c = CpuNumOfBits - CpuMax - 1; 2330 1.1 christos if (c) 2331 1.9 christos fail ("%d unused bits in i386_cpu_flags.\n", c); 2332 1.9 christos #endif 2333 1.9 christos 2334 1.9 christos /* If this triggers, CpuIsaBits needs to be increased. */ 2335 1.9 christos static_assert (CpuAttrEnums <= (1u << CpuIsaBits)); 2336 1.9 christos 2337 1.9 christos /* Check the unused bitfield in i386_cpu_attr. */ 2338 1.9 christos #ifndef CpuAttrUnused 2339 1.9 christos c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums); 2340 1.9 christos if (c) 2341 1.9 christos fail ("%d unused bits in i386_cpu_attr.\n", c); 2342 1.1 christos #endif 2343 1.1 christos 2344 1.7 christos static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num); 2345 1.7 christos 2346 1.1 christos /* Check the unused bitfield in i386_operand_type. */ 2347 1.7 christos #ifdef OTUnused 2348 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH 2349 1.7 christos == OTNum + 1); 2350 1.7 christos #else 2351 1.7 christos static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH 2352 1.7 christos == OTNum); 2353 1.7 christos 2354 1.7 christos c = OTNumOfBits - OTNum; 2355 1.1 christos if (c) 2356 1.9 christos fail ("%d unused bits in i386_operand_type.\n", c); 2357 1.1 christos #endif 2358 1.1 christos 2359 1.1 christos qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]), 2360 1.1 christos compare); 2361 1.1 christos 2362 1.1 christos qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers), 2363 1.1 christos sizeof (opcode_modifiers [0]), compare); 2364 1.1 christos 2365 1.1 christos qsort (operand_types, ARRAY_SIZE (operand_types), 2366 1.1 christos sizeof (operand_types [0]), compare); 2367 1.1 christos 2368 1.9 christos process_i386_initializers (); 2369 1.9 christos 2370 1.1 christos table = fopen ("i386-tbl.h", "w"); 2371 1.1 christos if (table == NULL) 2372 1.9 christos fail ("can't create i386-tbl.h, errno = %s\n", 2373 1.1 christos xstrerror (errno)); 2374 1.1 christos 2375 1.1 christos process_copyright (table); 2376 1.1 christos 2377 1.1 christos process_i386_opcodes (table); 2378 1.1 christos process_i386_registers (table); 2379 1.1 christos 2380 1.1 christos fclose (table); 2381 1.1 christos 2382 1.1 christos exit (0); 2383 1.1 christos } 2384