Home | History | Annotate | Line # | Download | only in opcodes
i386-gen.c revision 1.10
      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