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