Home | History | Annotate | Line # | Download | only in opcodes
s390-mkopc.c revision 1.1.1.10.2.1
      1           1.1  christos /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
      2  1.1.1.10.2.1  perseant    Copyright (C) 2000-2024 Free Software Foundation, Inc.
      3           1.1  christos    Contributed by Martin Schwidefsky (schwidefsky (at) de.ibm.com).
      4           1.1  christos 
      5           1.1  christos    This file is part of the GNU opcodes library.
      6           1.1  christos 
      7           1.1  christos    This library is free software; you can redistribute it and/or modify
      8           1.1  christos    it under the terms of the GNU General Public License as published by
      9           1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10           1.1  christos    any later version.
     11           1.1  christos 
     12           1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     13           1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14           1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15           1.1  christos    License for more details.
     16           1.1  christos 
     17           1.1  christos    You should have received a copy of the GNU General Public License
     18           1.1  christos    along with this file; see the file COPYING.  If not, write to the
     19           1.1  christos    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     20           1.1  christos    MA 02110-1301, USA.  */
     21           1.1  christos 
     22           1.1  christos #include <stdio.h>
     23           1.1  christos #include <stdlib.h>
     24  1.1.1.10.2.1  perseant #include <stdarg.h>
     25           1.1  christos #include <string.h>
     26       1.1.1.5  christos #include "opcode/s390.h"
     27           1.1  christos 
     28  1.1.1.10.2.1  perseant #define STRINGIFY(x) _STRINGIFY(x)
     29  1.1.1.10.2.1  perseant #define _STRINGIFY(x) #x
     30  1.1.1.10.2.1  perseant 
     31  1.1.1.10.2.1  perseant /* Length of strings without terminating '\0' character.  */
     32  1.1.1.10.2.1  perseant #define MAX_OPCODE_LEN 15
     33  1.1.1.10.2.1  perseant #define MAX_MNEMONIC_LEN 15
     34  1.1.1.10.2.1  perseant #define MAX_FORMAT_LEN 15
     35  1.1.1.10.2.1  perseant #define MAX_DESCRIPTION_LEN 127
     36  1.1.1.10.2.1  perseant 
     37  1.1.1.10.2.1  perseant #define MAX_CPU_LEN 15
     38  1.1.1.10.2.1  perseant #define MAX_MODES_LEN 15
     39  1.1.1.10.2.1  perseant #define MAX_FLAGS_LEN 79
     40  1.1.1.10.2.1  perseant 
     41  1.1.1.10.2.1  perseant /* Return code.  */
     42  1.1.1.10.2.1  perseant int return_code = EXIT_SUCCESS;
     43  1.1.1.10.2.1  perseant 
     44  1.1.1.10.2.1  perseant /* Helper to print an error message and set the return code.  */
     45  1.1.1.10.2.1  perseant static void __attribute__ ((format (printf, 1, 2)))
     46  1.1.1.10.2.1  perseant print_error (const char *fmt, ...)
     47  1.1.1.10.2.1  perseant {
     48  1.1.1.10.2.1  perseant   va_list ap;
     49  1.1.1.10.2.1  perseant 
     50  1.1.1.10.2.1  perseant   va_start(ap, fmt);
     51  1.1.1.10.2.1  perseant   fprintf(stderr, "Error: ");
     52  1.1.1.10.2.1  perseant   vfprintf(stderr, fmt, ap);
     53  1.1.1.10.2.1  perseant   va_end(ap);
     54  1.1.1.10.2.1  perseant 
     55  1.1.1.10.2.1  perseant   return_code = EXIT_FAILURE;
     56  1.1.1.10.2.1  perseant }
     57  1.1.1.10.2.1  perseant 
     58           1.1  christos struct op_struct
     59           1.1  christos   {
     60  1.1.1.10.2.1  perseant     char  opcode[MAX_OPCODE_LEN + 1];
     61  1.1.1.10.2.1  perseant     char  mnemonic[MAX_MNEMONIC_LEN + 1];
     62  1.1.1.10.2.1  perseant     char  format[MAX_FORMAT_LEN + 1];
     63           1.1  christos     int   mode_bits;
     64           1.1  christos     int   min_cpu;
     65       1.1.1.5  christos     int   flags;
     66  1.1.1.10.2.1  perseant     char  description[MAX_DESCRIPTION_LEN + 1];
     67       1.1.1.2  christos 
     68           1.1  christos     unsigned long long sort_value;
     69           1.1  christos     int   no_nibbles;
     70           1.1  christos   };
     71           1.1  christos 
     72           1.1  christos struct op_struct *op_array;
     73           1.1  christos int max_ops;
     74           1.1  christos int no_ops;
     75           1.1  christos 
     76           1.1  christos static void
     77           1.1  christos createTable (void)
     78           1.1  christos {
     79           1.1  christos   max_ops = 256;
     80           1.1  christos   op_array = malloc (max_ops * sizeof (struct op_struct));
     81           1.1  christos   no_ops = 0;
     82           1.1  christos }
     83           1.1  christos 
     84           1.1  christos /* `insertOpcode': insert an op_struct into sorted opcode array.  */
     85           1.1  christos 
     86           1.1  christos static void
     87           1.1  christos insertOpcode (char *opcode, char *mnemonic, char *format,
     88  1.1.1.10.2.1  perseant 	      int min_cpu, int mode_bits, int flags, char* description)
     89           1.1  christos {
     90           1.1  christos   char *str;
     91           1.1  christos   unsigned long long sort_value;
     92           1.1  christos   int no_nibbles;
     93           1.1  christos   int ix, k;
     94           1.1  christos 
     95           1.1  christos   while (no_ops >= max_ops)
     96           1.1  christos     {
     97           1.1  christos       max_ops = max_ops * 2;
     98           1.1  christos       op_array = realloc (op_array, max_ops * sizeof (struct op_struct));
     99           1.1  christos     }
    100           1.1  christos 
    101           1.1  christos   sort_value = 0;
    102           1.1  christos   str = opcode;
    103           1.1  christos   for (ix = 0; ix < 16; ix++)
    104           1.1  christos     {
    105           1.1  christos       if (*str >= '0' && *str <= '9')
    106           1.1  christos 	sort_value = (sort_value << 4) + (*str - '0');
    107           1.1  christos       else if (*str >= 'a' && *str <= 'f')
    108           1.1  christos 	sort_value = (sort_value << 4) + (*str - 'a' + 10);
    109           1.1  christos       else if (*str >= 'A' && *str <= 'F')
    110           1.1  christos 	sort_value = (sort_value << 4) + (*str - 'A' + 10);
    111           1.1  christos       else if (*str == '?')
    112           1.1  christos 	sort_value <<= 4;
    113           1.1  christos       else
    114           1.1  christos 	break;
    115           1.1  christos       str ++;
    116           1.1  christos     }
    117           1.1  christos   sort_value <<= 4*(16 - ix);
    118           1.1  christos   sort_value += (min_cpu << 8) + mode_bits;
    119           1.1  christos   no_nibbles = ix;
    120           1.1  christos   for (ix = 0; ix < no_ops; ix++)
    121           1.1  christos     if (sort_value > op_array[ix].sort_value)
    122           1.1  christos       break;
    123           1.1  christos   for (k = no_ops; k > ix; k--)
    124           1.1  christos     op_array[k] = op_array[k-1];
    125  1.1.1.10.2.1  perseant   strncpy (op_array[ix].opcode, opcode, MAX_OPCODE_LEN);
    126  1.1.1.10.2.1  perseant   op_array[ix].opcode[MAX_OPCODE_LEN] = '\0';
    127  1.1.1.10.2.1  perseant   strncpy (op_array[ix].mnemonic, mnemonic, MAX_MNEMONIC_LEN);
    128  1.1.1.10.2.1  perseant   op_array[ix].mnemonic[MAX_MNEMONIC_LEN] = '\0';
    129  1.1.1.10.2.1  perseant   strncpy (op_array[ix].format, format, MAX_FORMAT_LEN);
    130  1.1.1.10.2.1  perseant   op_array[ix].format[MAX_FORMAT_LEN] = '\0';
    131           1.1  christos   op_array[ix].sort_value = sort_value;
    132           1.1  christos   op_array[ix].no_nibbles = no_nibbles;
    133           1.1  christos   op_array[ix].min_cpu = min_cpu;
    134           1.1  christos   op_array[ix].mode_bits = mode_bits;
    135       1.1.1.5  christos   op_array[ix].flags = flags;
    136  1.1.1.10.2.1  perseant   strncpy (op_array[ix].description, description, MAX_DESCRIPTION_LEN);
    137  1.1.1.10.2.1  perseant   op_array[ix].description[MAX_DESCRIPTION_LEN] = '\0';
    138           1.1  christos   no_ops++;
    139           1.1  christos }
    140           1.1  christos 
    141           1.1  christos struct s390_cond_ext_format
    142           1.1  christos {
    143           1.1  christos   char nibble;
    144           1.1  christos   char extension[4];
    145  1.1.1.10.2.1  perseant   char *description_suffix;
    146  1.1.1.10.2.1  perseant 
    147           1.1  christos };
    148           1.1  christos 
    149           1.1  christos /* The mnemonic extensions for conditional jumps used to replace
    150           1.1  christos    the '*' tag.  */
    151           1.1  christos #define NUM_COND_EXTENSIONS 20
    152           1.1  christos const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
    153  1.1.1.10.2.1  perseant { { '1', "o", "on overflow / if ones" },	/* jump on overflow / if ones */
    154  1.1.1.10.2.1  perseant   { '2', "h", "on A high" },			/* jump on A high */
    155  1.1.1.10.2.1  perseant   { '2', "p", "on plus" },			/* jump on plus */
    156  1.1.1.10.2.1  perseant   { '3', "nle", "on not low or equal" },	/* jump on not low or equal */
    157  1.1.1.10.2.1  perseant   { '4', "l", "on A low" },			/* jump on A low */
    158  1.1.1.10.2.1  perseant   { '4', "m", "on minus / if mixed" },		/* jump on minus / if mixed */
    159  1.1.1.10.2.1  perseant   { '5', "nhe", "on not high or equal" },	/* jump on not high or equal */
    160  1.1.1.10.2.1  perseant   { '6', "lh", "on low or high" },		/* jump on low or high */
    161  1.1.1.10.2.1  perseant   { '7', "ne", "on A not equal B" },		/* jump on A not equal B */
    162  1.1.1.10.2.1  perseant   { '7', "nz", "on not zero / if not zeros" },	/* jump on not zero / if not zeros */
    163  1.1.1.10.2.1  perseant   { '8', "e", "on A equal B" },			/* jump on A equal B */
    164  1.1.1.10.2.1  perseant   { '8', "z", "on zero / if zeros" },		/* jump on zero / if zeros */
    165  1.1.1.10.2.1  perseant   { '9', "nlh", "on not low or high" },		/* jump on not low or high */
    166  1.1.1.10.2.1  perseant   { 'a', "he", "on high or equal" },		/* jump on high or equal */
    167  1.1.1.10.2.1  perseant   { 'b', "nl", "on A not low" },		/* jump on A not low */
    168  1.1.1.10.2.1  perseant   { 'b', "nm", "on not minus / if not mixed" },	/* jump on not minus / if not mixed */
    169  1.1.1.10.2.1  perseant   { 'c', "le", "on low or equal" },		/* jump on low or equal */
    170  1.1.1.10.2.1  perseant   { 'd', "nh", "on A not high" },		/* jump on A not high */
    171  1.1.1.10.2.1  perseant   { 'd', "np", "on not plus" },			/* jump on not plus */
    172  1.1.1.10.2.1  perseant   { 'e', "no", "on not overflow / if not ones" },/* jump on not overflow / if not ones */
    173           1.1  christos };
    174           1.1  christos 
    175           1.1  christos /* The mnemonic extensions for conditional branches used to replace
    176           1.1  christos    the '$' tag.  */
    177           1.1  christos #define NUM_CRB_EXTENSIONS 12
    178           1.1  christos const struct s390_cond_ext_format s390_crb_extensions[NUM_CRB_EXTENSIONS] =
    179  1.1.1.10.2.1  perseant { { '2', "h", "on A high" },			/* jump on A high */
    180  1.1.1.10.2.1  perseant   { '2', "nle", "on not low or equal" },	/* jump on not low or equal */
    181  1.1.1.10.2.1  perseant   { '4', "l", "on A low" },			/* jump on A low */
    182  1.1.1.10.2.1  perseant   { '4', "nhe", "on not high or equal" },	/* jump on not high or equal */
    183  1.1.1.10.2.1  perseant   { '6', "ne", "on A not equal B" },		/* jump on A not equal B */
    184  1.1.1.10.2.1  perseant   { '6', "lh", "on low or high" },		/* jump on low or high */
    185  1.1.1.10.2.1  perseant   { '8', "e", "on A equal B" },			/* jump on A equal B */
    186  1.1.1.10.2.1  perseant   { '8', "nlh", "on not low or high" },		/* jump on not low or high */
    187  1.1.1.10.2.1  perseant   { 'a', "nl", "on A not low" },		/* jump on A not low */
    188  1.1.1.10.2.1  perseant   { 'a', "he", "on high or equal" },		/* jump on high or equal */
    189  1.1.1.10.2.1  perseant   { 'c', "nh", "on A not high" },		/* jump on A not high */
    190  1.1.1.10.2.1  perseant   { 'c', "le", "on low or equal" },		/* jump on low or equal */
    191           1.1  christos };
    192           1.1  christos 
    193           1.1  christos /* As with insertOpcode instructions are added to the sorted opcode
    194           1.1  christos    array.  Additionally mnemonics containing the '*<number>' tag are
    195           1.1  christos    expanded to the set of conditional instructions described by
    196           1.1  christos    s390_cond_extensions with the tag replaced by the respective
    197           1.1  christos    mnemonic extensions.  */
    198           1.1  christos 
    199           1.1  christos static void
    200           1.1  christos insertExpandedMnemonic (char *opcode, char *mnemonic, char *format,
    201  1.1.1.10.2.1  perseant 			int min_cpu, int mode_bits, int flags, char *description)
    202           1.1  christos {
    203           1.1  christos   char *tag;
    204  1.1.1.10.2.1  perseant   char prefix[MAX_MNEMONIC_LEN + 1];
    205  1.1.1.10.2.1  perseant   char suffix[MAX_MNEMONIC_LEN + 1];
    206  1.1.1.10.2.1  perseant   char number[MAX_MNEMONIC_LEN + 1];
    207           1.1  christos   int mask_start, i = 0, tag_found = 0, reading_number = 0;
    208           1.1  christos   int number_p = 0, suffix_p = 0, prefix_p = 0;
    209           1.1  christos   const struct s390_cond_ext_format *ext_table;
    210           1.1  christos   int ext_table_length;
    211           1.1  christos 
    212           1.1  christos   if (!(tag = strpbrk (mnemonic, "*$")))
    213           1.1  christos     {
    214  1.1.1.10.2.1  perseant       insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags, description);
    215           1.1  christos       return;
    216           1.1  christos     }
    217           1.1  christos 
    218           1.1  christos   while (mnemonic[i] != '\0')
    219           1.1  christos     {
    220           1.1  christos       if (mnemonic[i] == *tag)
    221           1.1  christos 	{
    222           1.1  christos 	  if (tag_found)
    223           1.1  christos 	    goto malformed_mnemonic;
    224           1.1  christos 
    225           1.1  christos 	  tag_found = 1;
    226           1.1  christos 	  reading_number = 1;
    227           1.1  christos 	}
    228           1.1  christos       else
    229           1.1  christos 	switch (mnemonic[i])
    230           1.1  christos 	  {
    231           1.1  christos 	  case '0': case '1': case '2': case '3': case '4':
    232           1.1  christos 	  case '5': case '6': case '7': case '8': case '9':
    233           1.1  christos 	    if (!tag_found || !reading_number)
    234           1.1  christos 	      goto malformed_mnemonic;
    235           1.1  christos 
    236           1.1  christos 	    number[number_p++] = mnemonic[i];
    237           1.1  christos 	    break;
    238           1.1  christos 
    239           1.1  christos 	  default:
    240           1.1  christos 	    if (reading_number)
    241           1.1  christos 	      {
    242           1.1  christos 		if (!number_p)
    243           1.1  christos 		  goto malformed_mnemonic;
    244           1.1  christos 		else
    245           1.1  christos 		  reading_number = 0;
    246           1.1  christos 	      }
    247           1.1  christos 
    248           1.1  christos 	    if (tag_found)
    249           1.1  christos 	      suffix[suffix_p++] = mnemonic[i];
    250           1.1  christos 	    else
    251           1.1  christos 	      prefix[prefix_p++] = mnemonic[i];
    252           1.1  christos 	  }
    253           1.1  christos       i++;
    254           1.1  christos     }
    255           1.1  christos 
    256           1.1  christos   prefix[prefix_p] = '\0';
    257           1.1  christos   suffix[suffix_p] = '\0';
    258           1.1  christos   number[number_p] = '\0';
    259           1.1  christos 
    260           1.1  christos   if (sscanf (number, "%d", &mask_start) != 1)
    261           1.1  christos     goto malformed_mnemonic;
    262           1.1  christos 
    263           1.1  christos   if (mask_start & 3)
    264           1.1  christos     {
    265  1.1.1.10.2.1  perseant       print_error ("Mnemonic \"%s\": Conditional mask not at nibble boundary\n", mnemonic);
    266           1.1  christos       return;
    267           1.1  christos     }
    268           1.1  christos 
    269           1.1  christos   mask_start >>= 2;
    270           1.1  christos 
    271           1.1  christos   switch (*tag)
    272           1.1  christos     {
    273           1.1  christos     case '*':
    274           1.1  christos       ext_table = s390_cond_extensions;
    275           1.1  christos       ext_table_length = NUM_COND_EXTENSIONS;
    276           1.1  christos       break;
    277           1.1  christos     case '$':
    278           1.1  christos       ext_table = s390_crb_extensions;
    279           1.1  christos       ext_table_length = NUM_CRB_EXTENSIONS;
    280           1.1  christos       break;
    281       1.1.1.9  christos     default:
    282       1.1.1.9  christos       abort ();			/* Should be unreachable.  */
    283           1.1  christos     }
    284           1.1  christos 
    285           1.1  christos   for (i = 0; i < ext_table_length; i++)
    286           1.1  christos     {
    287  1.1.1.10.2.1  perseant       char new_mnemonic[MAX_MNEMONIC_LEN + 1];
    288  1.1.1.10.2.1  perseant       char new_description[MAX_DESCRIPTION_LEN + 1];
    289           1.1  christos 
    290           1.1  christos       opcode[mask_start] = ext_table[i].nibble;
    291  1.1.1.10.2.1  perseant 
    292  1.1.1.10.2.1  perseant       if (snprintf (new_mnemonic, sizeof (new_mnemonic), "%s%s%s", prefix,
    293  1.1.1.10.2.1  perseant 		    ext_table[i].extension, suffix) >= sizeof (new_mnemonic))
    294  1.1.1.10.2.1  perseant 	{
    295  1.1.1.10.2.1  perseant 	  print_error ("Mnemonic: \"%s\": Concatenated mnemonic exceeds max. length\n", mnemonic);
    296  1.1.1.10.2.1  perseant 	  return;
    297  1.1.1.10.2.1  perseant 	}
    298  1.1.1.10.2.1  perseant 
    299  1.1.1.10.2.1  perseant       if (snprintf (new_description, sizeof (new_description), "%s %s", description,
    300  1.1.1.10.2.1  perseant 		    ext_table[i].description_suffix) >= sizeof (new_description))
    301  1.1.1.10.2.1  perseant 	{
    302  1.1.1.10.2.1  perseant 	  print_error ("Mnemonic \"%s\": Concatenated description exceeds max. length\n", mnemonic);
    303  1.1.1.10.2.1  perseant 	  return;
    304  1.1.1.10.2.1  perseant 	}
    305  1.1.1.10.2.1  perseant 
    306  1.1.1.10.2.1  perseant       insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags, new_description);
    307           1.1  christos     }
    308           1.1  christos   return;
    309           1.1  christos 
    310           1.1  christos  malformed_mnemonic:
    311  1.1.1.10.2.1  perseant   print_error ("Malformed mnemonic: %s\n", mnemonic);
    312           1.1  christos }
    313           1.1  christos 
    314       1.1.1.2  christos static const char file_header[] =
    315           1.1  christos   "/* The opcode table. This file was generated by s390-mkopc.\n\n"
    316           1.1  christos   "   The format of the opcode table is:\n\n"
    317           1.1  christos   "   NAME	     OPCODE	MASK	OPERANDS\n\n"
    318           1.1  christos   "   Name is the name of the instruction.\n"
    319           1.1  christos   "   OPCODE is the instruction opcode.\n"
    320           1.1  christos   "   MASK is the opcode mask; this is used to tell the disassembler\n"
    321           1.1  christos   "     which bits in the actual opcode must match OPCODE.\n"
    322           1.1  christos   "   OPERANDS is the list of operands.\n\n"
    323           1.1  christos   "   The disassembler reads the table in order and prints the first\n"
    324       1.1.1.5  christos   "   instruction which matches.\n"
    325       1.1.1.5  christos   "   MODE_BITS - zarch or esa\n"
    326       1.1.1.5  christos   "   MIN_CPU - number of the min cpu level required\n"
    327  1.1.1.10.2.1  perseant   "   FLAGS - instruction flags.\n"
    328  1.1.1.10.2.1  perseant   "   DESCRIPTION - description of the instruction.  */\n\n"
    329           1.1  christos   "const struct s390_opcode s390_opcodes[] =\n  {\n";
    330           1.1  christos 
    331           1.1  christos /* `dumpTable': write opcode table.  */
    332           1.1  christos 
    333           1.1  christos static void
    334           1.1  christos dumpTable (void)
    335           1.1  christos {
    336           1.1  christos   char *str;
    337           1.1  christos   int  ix;
    338           1.1  christos 
    339           1.1  christos   /*  Write hash table entries (slots).  */
    340       1.1.1.3  christos   printf ("%s", file_header);
    341           1.1  christos 
    342           1.1  christos   for (ix = 0; ix < no_ops; ix++)
    343           1.1  christos     {
    344           1.1  christos       printf ("  { \"%s\", ", op_array[ix].mnemonic);
    345           1.1  christos       for (str = op_array[ix].opcode; *str != 0; str++)
    346           1.1  christos 	if (*str == '?')
    347           1.1  christos 	  *str = '0';
    348       1.1.1.2  christos       printf ("OP%i(0x%sLL), ",
    349           1.1  christos 	      op_array[ix].no_nibbles*4, op_array[ix].opcode);
    350           1.1  christos       printf ("MASK_%s, INSTR_%s, ",
    351           1.1  christos 	      op_array[ix].format, op_array[ix].format);
    352           1.1  christos       printf ("%i, ", op_array[ix].mode_bits);
    353       1.1.1.5  christos       printf ("%i, ", op_array[ix].min_cpu);
    354  1.1.1.10.2.1  perseant       printf ("%i, ", op_array[ix].flags);
    355  1.1.1.10.2.1  perseant       printf ("\"%s\" }", op_array[ix].description);
    356           1.1  christos       if (ix < no_ops-1)
    357           1.1  christos 	printf (",\n");
    358           1.1  christos       else
    359           1.1  christos 	printf ("\n");
    360           1.1  christos     }
    361           1.1  christos   printf ("};\n\n");
    362           1.1  christos   printf ("const int s390_num_opcodes =\n");
    363           1.1  christos   printf ("  sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
    364           1.1  christos }
    365           1.1  christos 
    366           1.1  christos int
    367           1.1  christos main (void)
    368           1.1  christos {
    369           1.1  christos   char currentLine[256];
    370       1.1.1.2  christos 
    371           1.1  christos   createTable ();
    372           1.1  christos 
    373           1.1  christos   /*  Read opcode descriptions from `stdin'.  For each mnemonic,
    374           1.1  christos       make an entry into the opcode table.  */
    375           1.1  christos   while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
    376           1.1  christos     {
    377  1.1.1.10.2.1  perseant       char  opcode[MAX_OPCODE_LEN + 1];
    378  1.1.1.10.2.1  perseant       char  mnemonic[MAX_MNEMONIC_LEN + 1];
    379  1.1.1.10.2.1  perseant       char  format[MAX_FORMAT_LEN + 1];
    380  1.1.1.10.2.1  perseant       char  description[MAX_DESCRIPTION_LEN + 1];
    381  1.1.1.10.2.1  perseant       char  cpu_string[MAX_CPU_LEN + 1];
    382  1.1.1.10.2.1  perseant       char  modes_string[MAX_MODES_LEN + 1];
    383  1.1.1.10.2.1  perseant       char  flags_string[MAX_FLAGS_LEN + 1];
    384           1.1  christos       int   min_cpu;
    385           1.1  christos       int   mode_bits;
    386       1.1.1.5  christos       int   flag_bits;
    387       1.1.1.5  christos       int   num_matched;
    388           1.1  christos       char  *str;
    389           1.1  christos 
    390       1.1.1.2  christos       if (currentLine[0] == '#' || currentLine[0] == '\n')
    391       1.1.1.7  christos 	continue;
    392  1.1.1.10.2.1  perseant       memset (opcode, '\0', sizeof(opcode));
    393  1.1.1.10.2.1  perseant       num_matched = sscanf (currentLine,
    394  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_OPCODE_LEN) "s "
    395  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_MNEMONIC_LEN) "s "
    396  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_FORMAT_LEN) "s "
    397  1.1.1.10.2.1  perseant 			    "\"%" STRINGIFY (MAX_DESCRIPTION_LEN) "[^\"]\" "
    398  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_CPU_LEN) "s "
    399  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_MODES_LEN) "s "
    400  1.1.1.10.2.1  perseant 			    "%" STRINGIFY (MAX_FLAGS_LEN) "[^\n]",
    401  1.1.1.10.2.1  perseant 			    opcode, mnemonic, format, description,
    402  1.1.1.10.2.1  perseant 			    cpu_string, modes_string, flags_string);
    403       1.1.1.5  christos       if (num_matched != 6 && num_matched != 7)
    404           1.1  christos 	{
    405  1.1.1.10.2.1  perseant 	  print_error ("Couldn't scan line %s\n", currentLine);
    406  1.1.1.10.2.1  perseant 	  exit (EXIT_FAILURE);
    407       1.1.1.5  christos 	}
    408           1.1  christos 
    409       1.1.1.7  christos       if (strcmp (cpu_string, "g5") == 0
    410       1.1.1.7  christos 	  || strcmp (cpu_string, "arch3") == 0)
    411       1.1.1.5  christos 	min_cpu = S390_OPCODE_G5;
    412       1.1.1.5  christos       else if (strcmp (cpu_string, "g6") == 0)
    413       1.1.1.5  christos 	min_cpu = S390_OPCODE_G6;
    414       1.1.1.7  christos       else if (strcmp (cpu_string, "z900") == 0
    415       1.1.1.7  christos 	       || strcmp (cpu_string, "arch5") == 0)
    416       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z900;
    417       1.1.1.7  christos       else if (strcmp (cpu_string, "z990") == 0
    418       1.1.1.7  christos 	       || strcmp (cpu_string, "arch6") == 0)
    419       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z990;
    420       1.1.1.5  christos       else if (strcmp (cpu_string, "z9-109") == 0)
    421       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z9_109;
    422       1.1.1.7  christos       else if (strcmp (cpu_string, "z9-ec") == 0
    423       1.1.1.7  christos 	       || strcmp (cpu_string, "arch7") == 0)
    424       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z9_EC;
    425       1.1.1.7  christos       else if (strcmp (cpu_string, "z10") == 0
    426       1.1.1.7  christos 	       || strcmp (cpu_string, "arch8") == 0)
    427       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z10;
    428       1.1.1.7  christos       else if (strcmp (cpu_string, "z196") == 0
    429       1.1.1.7  christos 	       || strcmp (cpu_string, "arch9") == 0)
    430       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z196;
    431       1.1.1.7  christos       else if (strcmp (cpu_string, "zEC12") == 0
    432       1.1.1.7  christos 	       || strcmp (cpu_string, "arch10") == 0)
    433       1.1.1.5  christos 	min_cpu = S390_OPCODE_ZEC12;
    434       1.1.1.7  christos       else if (strcmp (cpu_string, "z13") == 0
    435       1.1.1.7  christos 	       || strcmp (cpu_string, "arch11") == 0)
    436       1.1.1.5  christos 	min_cpu = S390_OPCODE_Z13;
    437       1.1.1.8  christos       else if (strcmp (cpu_string, "z14") == 0
    438       1.1.1.8  christos 	       || strcmp (cpu_string, "arch12") == 0)
    439       1.1.1.7  christos 	min_cpu = S390_OPCODE_ARCH12;
    440       1.1.1.9  christos       else if (strcmp (cpu_string, "z15") == 0
    441       1.1.1.9  christos 	       || strcmp (cpu_string, "arch13") == 0)
    442       1.1.1.8  christos 	min_cpu = S390_OPCODE_ARCH13;
    443      1.1.1.10  christos       else if (strcmp (cpu_string, "z16") == 0
    444      1.1.1.10  christos 	       || strcmp (cpu_string, "arch14") == 0)
    445      1.1.1.10  christos 	min_cpu = S390_OPCODE_ARCH14;
    446       1.1.1.5  christos       else {
    447  1.1.1.10.2.1  perseant 	print_error ("Mnemonic \"%s\": Couldn't parse CPU string: %s\n",
    448  1.1.1.10.2.1  perseant 		     mnemonic, cpu_string);
    449  1.1.1.10.2.1  perseant 	goto continue_loop;
    450       1.1.1.5  christos       }
    451       1.1.1.5  christos 
    452       1.1.1.5  christos       str = modes_string;
    453       1.1.1.5  christos       mode_bits = 0;
    454       1.1.1.5  christos       do {
    455       1.1.1.5  christos 	if (strncmp (str, "esa", 3) == 0
    456       1.1.1.5  christos 	    && (str[3] == 0 || str[3] == ',')) {
    457       1.1.1.5  christos 	  mode_bits |= 1 << S390_OPCODE_ESA;
    458       1.1.1.5  christos 	  str += 3;
    459       1.1.1.5  christos 	} else if (strncmp (str, "zarch", 5) == 0
    460       1.1.1.5  christos 		   && (str[5] == 0 || str[5] == ',')) {
    461       1.1.1.5  christos 	  mode_bits |= 1 << S390_OPCODE_ZARCH;
    462       1.1.1.5  christos 	  str += 5;
    463       1.1.1.5  christos 	} else {
    464  1.1.1.10.2.1  perseant 	  print_error ("Mnemonic \"%s\": Couldn't parse modes string: %s\n",
    465  1.1.1.10.2.1  perseant 		       mnemonic, modes_string);
    466  1.1.1.10.2.1  perseant 	  goto continue_loop;
    467       1.1.1.5  christos 	}
    468       1.1.1.5  christos 	if (*str == ',')
    469       1.1.1.5  christos 	  str++;
    470       1.1.1.5  christos       } while (*str != 0);
    471       1.1.1.5  christos 
    472       1.1.1.5  christos       flag_bits = 0;
    473       1.1.1.5  christos 
    474       1.1.1.5  christos       if (num_matched == 7)
    475       1.1.1.5  christos 	{
    476       1.1.1.5  christos 	  str = flags_string;
    477           1.1  christos 	  do {
    478       1.1.1.5  christos 	    if (strncmp (str, "optparm", 7) == 0
    479       1.1.1.5  christos 		&& (str[7] == 0 || str[7] == ',')) {
    480       1.1.1.5  christos 	      flag_bits |= S390_INSTR_FLAG_OPTPARM;
    481       1.1.1.5  christos 	      str += 7;
    482       1.1.1.8  christos 	    } else if (strncmp (str, "optparm2", 8) == 0
    483       1.1.1.8  christos 		       && (str[8] == 0 || str[8] == ',')) {
    484       1.1.1.8  christos 	      flag_bits |= S390_INSTR_FLAG_OPTPARM2;
    485       1.1.1.8  christos 	      str += 8;
    486       1.1.1.6  christos 	    } else if (strncmp (str, "htm", 3) == 0
    487       1.1.1.8  christos 		       && (str[3] == 0 || str[3] == ',')) {
    488       1.1.1.6  christos 	      flag_bits |= S390_INSTR_FLAG_HTM;
    489       1.1.1.6  christos 	      str += 3;
    490       1.1.1.6  christos 	    } else if (strncmp (str, "vx", 2) == 0
    491       1.1.1.8  christos 		       && (str[2] == 0 || str[2] == ',')) {
    492       1.1.1.6  christos 	      flag_bits |= S390_INSTR_FLAG_VX;
    493       1.1.1.6  christos 	      str += 2;
    494  1.1.1.10.2.1  perseant 	    } else if (strncmp (str, "jump", 4) == 0
    495  1.1.1.10.2.1  perseant 		&& (str[4] == 0 || str[4] == ',')) {
    496  1.1.1.10.2.1  perseant 	      flag_bits |= S390_INSTR_FLAGS_CLASS_JUMP;
    497  1.1.1.10.2.1  perseant 	      str += 4;
    498  1.1.1.10.2.1  perseant 	    } else if (strncmp (str, "condjump", 8) == 0
    499  1.1.1.10.2.1  perseant 		&& (str[8] == 0 || str[8] == ',')) {
    500  1.1.1.10.2.1  perseant 	      flag_bits |= S390_INSTR_FLAGS_CLASS_CONDJUMP;
    501  1.1.1.10.2.1  perseant 	      str += 8;
    502  1.1.1.10.2.1  perseant 	    } else if (strncmp (str, "jumpsr", 6) == 0
    503  1.1.1.10.2.1  perseant 		&& (str[6] == 0 || str[6] == ',')) {
    504  1.1.1.10.2.1  perseant 	      flag_bits |= S390_INSTR_FLAGS_CLASS_JUMPSR;
    505  1.1.1.10.2.1  perseant 	      str += 6;
    506           1.1  christos 	    } else {
    507  1.1.1.10.2.1  perseant 	      print_error ("Mnemonic \"%s\": Couldn't parse flags string: %s\n",
    508  1.1.1.10.2.1  perseant 			   mnemonic, flags_string);
    509  1.1.1.10.2.1  perseant 	      goto continue_loop;
    510           1.1  christos 	    }
    511           1.1  christos 	    if (*str == ',')
    512           1.1  christos 	      str++;
    513           1.1  christos 	  } while (*str != 0);
    514           1.1  christos 	}
    515  1.1.1.10.2.1  perseant       insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits, description);
    516  1.1.1.10.2.1  perseant 
    517  1.1.1.10.2.1  perseant  continue_loop:
    518  1.1.1.10.2.1  perseant       ;
    519           1.1  christos     }
    520           1.1  christos 
    521           1.1  christos   dumpTable ();
    522  1.1.1.10.2.1  perseant   return return_code;
    523           1.1  christos }
    524