Home | History | Annotate | Line # | Download | only in opcodes
s390-mkopc.c revision 1.5
      1  1.1  christos /* s390-mkopc.c -- Generates opcode table out of s390-opc.txt
      2  1.3  christos    Copyright (C) 2000-2015 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  christos #include <string.h>
     25  1.5  christos #include "opcode/s390.h"
     26  1.1  christos 
     27  1.1  christos struct op_struct
     28  1.1  christos   {
     29  1.1  christos     char  opcode[16];
     30  1.1  christos     char  mnemonic[16];
     31  1.1  christos     char  format[16];
     32  1.1  christos     int   mode_bits;
     33  1.1  christos     int   min_cpu;
     34  1.5  christos     int   flags;
     35  1.1  christos 
     36  1.1  christos     unsigned long long sort_value;
     37  1.1  christos     int   no_nibbles;
     38  1.1  christos   };
     39  1.1  christos 
     40  1.1  christos struct op_struct *op_array;
     41  1.1  christos int max_ops;
     42  1.1  christos int no_ops;
     43  1.1  christos 
     44  1.1  christos static void
     45  1.1  christos createTable (void)
     46  1.1  christos {
     47  1.1  christos   max_ops = 256;
     48  1.1  christos   op_array = malloc (max_ops * sizeof (struct op_struct));
     49  1.1  christos   no_ops = 0;
     50  1.1  christos }
     51  1.1  christos 
     52  1.1  christos /* `insertOpcode': insert an op_struct into sorted opcode array.  */
     53  1.1  christos 
     54  1.1  christos static void
     55  1.1  christos insertOpcode (char *opcode, char *mnemonic, char *format,
     56  1.5  christos 	      int min_cpu, int mode_bits, int flags)
     57  1.1  christos {
     58  1.1  christos   char *str;
     59  1.1  christos   unsigned long long sort_value;
     60  1.1  christos   int no_nibbles;
     61  1.1  christos   int ix, k;
     62  1.1  christos 
     63  1.1  christos   while (no_ops >= max_ops)
     64  1.1  christos     {
     65  1.1  christos       max_ops = max_ops * 2;
     66  1.1  christos       op_array = realloc (op_array, max_ops * sizeof (struct op_struct));
     67  1.1  christos     }
     68  1.1  christos 
     69  1.1  christos   sort_value = 0;
     70  1.1  christos   str = opcode;
     71  1.1  christos   for (ix = 0; ix < 16; ix++)
     72  1.1  christos     {
     73  1.1  christos       if (*str >= '0' && *str <= '9')
     74  1.1  christos 	sort_value = (sort_value << 4) + (*str - '0');
     75  1.1  christos       else if (*str >= 'a' && *str <= 'f')
     76  1.1  christos 	sort_value = (sort_value << 4) + (*str - 'a' + 10);
     77  1.1  christos       else if (*str >= 'A' && *str <= 'F')
     78  1.1  christos 	sort_value = (sort_value << 4) + (*str - 'A' + 10);
     79  1.1  christos       else if (*str == '?')
     80  1.1  christos 	sort_value <<= 4;
     81  1.1  christos       else
     82  1.1  christos 	break;
     83  1.1  christos       str ++;
     84  1.1  christos     }
     85  1.1  christos   sort_value <<= 4*(16 - ix);
     86  1.1  christos   sort_value += (min_cpu << 8) + mode_bits;
     87  1.1  christos   no_nibbles = ix;
     88  1.1  christos   for (ix = 0; ix < no_ops; ix++)
     89  1.1  christos     if (sort_value > op_array[ix].sort_value)
     90  1.1  christos       break;
     91  1.1  christos   for (k = no_ops; k > ix; k--)
     92  1.1  christos     op_array[k] = op_array[k-1];
     93  1.1  christos   strcpy(op_array[ix].opcode, opcode);
     94  1.1  christos   strcpy(op_array[ix].mnemonic, mnemonic);
     95  1.1  christos   strcpy(op_array[ix].format, format);
     96  1.1  christos   op_array[ix].sort_value = sort_value;
     97  1.1  christos   op_array[ix].no_nibbles = no_nibbles;
     98  1.1  christos   op_array[ix].min_cpu = min_cpu;
     99  1.1  christos   op_array[ix].mode_bits = mode_bits;
    100  1.5  christos   op_array[ix].flags = flags;
    101  1.1  christos   no_ops++;
    102  1.1  christos }
    103  1.1  christos 
    104  1.1  christos struct s390_cond_ext_format
    105  1.1  christos {
    106  1.1  christos   char nibble;
    107  1.1  christos   char extension[4];
    108  1.1  christos };
    109  1.1  christos 
    110  1.1  christos /* The mnemonic extensions for conditional jumps used to replace
    111  1.1  christos    the '*' tag.  */
    112  1.1  christos #define NUM_COND_EXTENSIONS 20
    113  1.1  christos const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
    114  1.1  christos { { '1', "o" },    /* jump on overflow / if ones */
    115  1.1  christos   { '2', "h" },    /* jump on A high */
    116  1.1  christos   { '2', "p" },    /* jump on plus */
    117  1.1  christos   { '3', "nle" },  /* jump on not low or equal */
    118  1.1  christos   { '4', "l" },    /* jump on A low */
    119  1.1  christos   { '4', "m" },    /* jump on minus / if mixed */
    120  1.1  christos   { '5', "nhe" },  /* jump on not high or equal */
    121  1.1  christos   { '6', "lh" },   /* jump on low or high */
    122  1.1  christos   { '7', "ne" },   /* jump on A not equal B */
    123  1.1  christos   { '7', "nz" },   /* jump on not zero / if not zeros */
    124  1.1  christos   { '8', "e" },    /* jump on A equal B */
    125  1.1  christos   { '8', "z" },    /* jump on zero / if zeros */
    126  1.1  christos   { '9', "nlh" },  /* jump on not low or high */
    127  1.1  christos   { 'a', "he" },   /* jump on high or equal */
    128  1.1  christos   { 'b', "nl" },   /* jump on A not low */
    129  1.1  christos   { 'b', "nm" },   /* jump on not minus / if not mixed */
    130  1.1  christos   { 'c', "le" },   /* jump on low or equal */
    131  1.1  christos   { 'd', "nh" },   /* jump on A not high */
    132  1.1  christos   { 'd', "np" },   /* jump on not plus */
    133  1.1  christos   { 'e', "no" },   /* jump on not overflow / if not ones */
    134  1.1  christos };
    135  1.1  christos 
    136  1.1  christos /* The mnemonic extensions for conditional branches used to replace
    137  1.1  christos    the '$' tag.  */
    138  1.1  christos #define NUM_CRB_EXTENSIONS 12
    139  1.1  christos const struct s390_cond_ext_format s390_crb_extensions[NUM_CRB_EXTENSIONS] =
    140  1.1  christos { { '2', "h" },    /* jump on A high */
    141  1.1  christos   { '2', "nle" },  /* jump on not low or equal */
    142  1.1  christos   { '4', "l" },    /* jump on A low */
    143  1.1  christos   { '4', "nhe" },  /* jump on not high or equal */
    144  1.1  christos   { '6', "ne" },   /* jump on A not equal B */
    145  1.1  christos   { '6', "lh" },   /* jump on low or high */
    146  1.1  christos   { '8', "e" },    /* jump on A equal B */
    147  1.1  christos   { '8', "nlh" },  /* jump on not low or high */
    148  1.1  christos   { 'a', "nl" },   /* jump on A not low */
    149  1.1  christos   { 'a', "he" },   /* jump on high or equal */
    150  1.1  christos   { 'c', "nh" },   /* jump on A not high */
    151  1.1  christos   { 'c', "le" },   /* jump on low or equal */
    152  1.1  christos };
    153  1.1  christos 
    154  1.1  christos /* As with insertOpcode instructions are added to the sorted opcode
    155  1.1  christos    array.  Additionally mnemonics containing the '*<number>' tag are
    156  1.1  christos    expanded to the set of conditional instructions described by
    157  1.1  christos    s390_cond_extensions with the tag replaced by the respective
    158  1.1  christos    mnemonic extensions.  */
    159  1.1  christos 
    160  1.1  christos static void
    161  1.1  christos insertExpandedMnemonic (char *opcode, char *mnemonic, char *format,
    162  1.5  christos 			int min_cpu, int mode_bits, int flags)
    163  1.1  christos {
    164  1.1  christos   char *tag;
    165  1.1  christos   char prefix[15];
    166  1.1  christos   char suffix[15];
    167  1.1  christos   char number[15];
    168  1.1  christos   int mask_start, i = 0, tag_found = 0, reading_number = 0;
    169  1.1  christos   int number_p = 0, suffix_p = 0, prefix_p = 0;
    170  1.1  christos   const struct s390_cond_ext_format *ext_table;
    171  1.1  christos   int ext_table_length;
    172  1.1  christos 
    173  1.1  christos   if (!(tag = strpbrk (mnemonic, "*$")))
    174  1.1  christos     {
    175  1.5  christos       insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits, flags);
    176  1.1  christos       return;
    177  1.1  christos     }
    178  1.1  christos 
    179  1.1  christos   while (mnemonic[i] != '\0')
    180  1.1  christos     {
    181  1.1  christos       if (mnemonic[i] == *tag)
    182  1.1  christos 	{
    183  1.1  christos 	  if (tag_found)
    184  1.1  christos 	    goto malformed_mnemonic;
    185  1.1  christos 
    186  1.1  christos 	  tag_found = 1;
    187  1.1  christos 	  reading_number = 1;
    188  1.1  christos 	}
    189  1.1  christos       else
    190  1.1  christos 	switch (mnemonic[i])
    191  1.1  christos 	  {
    192  1.1  christos 	  case '0': case '1': case '2': case '3': case '4':
    193  1.1  christos 	  case '5': case '6': case '7': case '8': case '9':
    194  1.1  christos 	    if (!tag_found || !reading_number)
    195  1.1  christos 	      goto malformed_mnemonic;
    196  1.1  christos 
    197  1.1  christos 	    number[number_p++] = mnemonic[i];
    198  1.1  christos 	    break;
    199  1.1  christos 
    200  1.1  christos 	  default:
    201  1.1  christos 	    if (reading_number)
    202  1.1  christos 	      {
    203  1.1  christos 		if (!number_p)
    204  1.1  christos 		  goto malformed_mnemonic;
    205  1.1  christos 		else
    206  1.1  christos 		  reading_number = 0;
    207  1.1  christos 	      }
    208  1.1  christos 
    209  1.1  christos 	    if (tag_found)
    210  1.1  christos 	      suffix[suffix_p++] = mnemonic[i];
    211  1.1  christos 	    else
    212  1.1  christos 	      prefix[prefix_p++] = mnemonic[i];
    213  1.1  christos 	  }
    214  1.1  christos       i++;
    215  1.1  christos     }
    216  1.1  christos 
    217  1.1  christos   prefix[prefix_p] = '\0';
    218  1.1  christos   suffix[suffix_p] = '\0';
    219  1.1  christos   number[number_p] = '\0';
    220  1.1  christos 
    221  1.1  christos   if (sscanf (number, "%d", &mask_start) != 1)
    222  1.1  christos     goto malformed_mnemonic;
    223  1.1  christos 
    224  1.1  christos   if (mask_start & 3)
    225  1.1  christos     {
    226  1.1  christos       fprintf (stderr, "Conditional mask not at nibble boundary in: %s\n",
    227  1.1  christos 	       mnemonic);
    228  1.1  christos       return;
    229  1.1  christos     }
    230  1.1  christos 
    231  1.1  christos   mask_start >>= 2;
    232  1.1  christos 
    233  1.1  christos   switch (*tag)
    234  1.1  christos     {
    235  1.1  christos     case '*':
    236  1.1  christos       ext_table = s390_cond_extensions;
    237  1.1  christos       ext_table_length = NUM_COND_EXTENSIONS;
    238  1.1  christos       break;
    239  1.1  christos     case '$':
    240  1.1  christos       ext_table = s390_crb_extensions;
    241  1.1  christos       ext_table_length = NUM_CRB_EXTENSIONS;
    242  1.1  christos       break;
    243  1.1  christos     default: fprintf (stderr, "Unknown tag char: %c\n", *tag);
    244  1.1  christos     }
    245  1.1  christos 
    246  1.1  christos   for (i = 0; i < ext_table_length; i++)
    247  1.1  christos     {
    248  1.1  christos       char new_mnemonic[15];
    249  1.1  christos 
    250  1.1  christos       strcpy (new_mnemonic, prefix);
    251  1.1  christos       opcode[mask_start] = ext_table[i].nibble;
    252  1.1  christos       strcat (new_mnemonic, ext_table[i].extension);
    253  1.1  christos       strcat (new_mnemonic, suffix);
    254  1.5  christos       insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits, flags);
    255  1.1  christos     }
    256  1.1  christos   return;
    257  1.1  christos 
    258  1.1  christos  malformed_mnemonic:
    259  1.1  christos   fprintf (stderr, "Malformed mnemonic: %s\n", mnemonic);
    260  1.1  christos }
    261  1.1  christos 
    262  1.1  christos static const char file_header[] =
    263  1.1  christos   "/* The opcode table. This file was generated by s390-mkopc.\n\n"
    264  1.1  christos   "   The format of the opcode table is:\n\n"
    265  1.1  christos   "   NAME	     OPCODE	MASK	OPERANDS\n\n"
    266  1.1  christos   "   Name is the name of the instruction.\n"
    267  1.1  christos   "   OPCODE is the instruction opcode.\n"
    268  1.1  christos   "   MASK is the opcode mask; this is used to tell the disassembler\n"
    269  1.1  christos   "     which bits in the actual opcode must match OPCODE.\n"
    270  1.1  christos   "   OPERANDS is the list of operands.\n\n"
    271  1.1  christos   "   The disassembler reads the table in order and prints the first\n"
    272  1.5  christos   "   instruction which matches.\n"
    273  1.5  christos   "   MODE_BITS - zarch or esa\n"
    274  1.5  christos   "   MIN_CPU - number of the min cpu level required\n"
    275  1.5  christos   "   FLAGS - instruction flags.  */\n\n"
    276  1.1  christos   "const struct s390_opcode s390_opcodes[] =\n  {\n";
    277  1.1  christos 
    278  1.1  christos /* `dumpTable': write opcode table.  */
    279  1.1  christos 
    280  1.1  christos static void
    281  1.1  christos dumpTable (void)
    282  1.1  christos {
    283  1.1  christos   char *str;
    284  1.1  christos   int  ix;
    285  1.1  christos 
    286  1.1  christos   /*  Write hash table entries (slots).  */
    287  1.1  christos   printf ("%s", file_header);
    288  1.1  christos 
    289  1.1  christos   for (ix = 0; ix < no_ops; ix++)
    290  1.1  christos     {
    291  1.1  christos       printf ("  { \"%s\", ", op_array[ix].mnemonic);
    292  1.1  christos       for (str = op_array[ix].opcode; *str != 0; str++)
    293  1.1  christos 	if (*str == '?')
    294  1.1  christos 	  *str = '0';
    295  1.1  christos       printf ("OP%i(0x%sLL), ",
    296  1.1  christos 	      op_array[ix].no_nibbles*4, op_array[ix].opcode);
    297  1.1  christos       printf ("MASK_%s, INSTR_%s, ",
    298  1.1  christos 	      op_array[ix].format, op_array[ix].format);
    299  1.1  christos       printf ("%i, ", op_array[ix].mode_bits);
    300  1.5  christos       printf ("%i, ", op_array[ix].min_cpu);
    301  1.5  christos       printf ("%i}", op_array[ix].flags);
    302  1.1  christos       if (ix < no_ops-1)
    303  1.1  christos 	printf (",\n");
    304  1.1  christos       else
    305  1.1  christos 	printf ("\n");
    306  1.1  christos     }
    307  1.1  christos   printf ("};\n\n");
    308  1.1  christos   printf ("const int s390_num_opcodes =\n");
    309  1.1  christos   printf ("  sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);\n\n");
    310  1.1  christos }
    311  1.1  christos 
    312  1.1  christos int
    313  1.1  christos main (void)
    314  1.1  christos {
    315  1.1  christos   char currentLine[256];
    316  1.1  christos 
    317  1.1  christos   createTable ();
    318  1.1  christos 
    319  1.1  christos   /*  Read opcode descriptions from `stdin'.  For each mnemonic,
    320  1.1  christos       make an entry into the opcode table.  */
    321  1.1  christos   while (fgets (currentLine, sizeof (currentLine), stdin) != NULL)
    322  1.1  christos     {
    323  1.1  christos       char  opcode[16];
    324  1.1  christos       char  mnemonic[16];
    325  1.1  christos       char  format[16];
    326  1.1  christos       char  description[80];
    327  1.1  christos       char  cpu_string[16];
    328  1.1  christos       char  modes_string[16];
    329  1.5  christos       char  flags_string[80];
    330  1.1  christos       int   min_cpu;
    331  1.1  christos       int   mode_bits;
    332  1.5  christos       int   flag_bits;
    333  1.5  christos       int   num_matched;
    334  1.1  christos       char  *str;
    335  1.1  christos 
    336  1.1  christos       if (currentLine[0] == '#' || currentLine[0] == '\n')
    337  1.1  christos         continue;
    338  1.1  christos       memset (opcode, 0, 8);
    339  1.5  christos       num_matched =
    340  1.5  christos 	sscanf (currentLine, "%15s %15s %15s \"%79[^\"]\" %15s %15s %79[^\n]",
    341  1.5  christos 		opcode, mnemonic, format, description,
    342  1.5  christos 		cpu_string, modes_string, flags_string);
    343  1.5  christos       if (num_matched != 6 && num_matched != 7)
    344  1.1  christos 	{
    345  1.5  christos 	  fprintf (stderr, "Couldn't scan line %s\n", currentLine);
    346  1.5  christos 	  exit (1);
    347  1.5  christos 	}
    348  1.5  christos 
    349  1.5  christos       if (strcmp (cpu_string, "g5") == 0)
    350  1.5  christos 	min_cpu = S390_OPCODE_G5;
    351  1.5  christos       else if (strcmp (cpu_string, "g6") == 0)
    352  1.5  christos 	min_cpu = S390_OPCODE_G6;
    353  1.5  christos       else if (strcmp (cpu_string, "z900") == 0)
    354  1.5  christos 	min_cpu = S390_OPCODE_Z900;
    355  1.5  christos       else if (strcmp (cpu_string, "z990") == 0)
    356  1.5  christos 	min_cpu = S390_OPCODE_Z990;
    357  1.5  christos       else if (strcmp (cpu_string, "z9-109") == 0)
    358  1.5  christos 	min_cpu = S390_OPCODE_Z9_109;
    359  1.5  christos       else if (strcmp (cpu_string, "z9-ec") == 0)
    360  1.5  christos 	min_cpu = S390_OPCODE_Z9_EC;
    361  1.5  christos       else if (strcmp (cpu_string, "z10") == 0)
    362  1.5  christos 	min_cpu = S390_OPCODE_Z10;
    363  1.5  christos       else if (strcmp (cpu_string, "z196") == 0)
    364  1.5  christos 	min_cpu = S390_OPCODE_Z196;
    365  1.5  christos       else if (strcmp (cpu_string, "zEC12") == 0)
    366  1.5  christos 	min_cpu = S390_OPCODE_ZEC12;
    367  1.5  christos       else if (strcmp (cpu_string, "z13") == 0)
    368  1.5  christos 	min_cpu = S390_OPCODE_Z13;
    369  1.5  christos       else {
    370  1.5  christos 	fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
    371  1.5  christos 	exit (1);
    372  1.5  christos       }
    373  1.5  christos 
    374  1.5  christos       str = modes_string;
    375  1.5  christos       mode_bits = 0;
    376  1.5  christos       do {
    377  1.5  christos 	if (strncmp (str, "esa", 3) == 0
    378  1.5  christos 	    && (str[3] == 0 || str[3] == ',')) {
    379  1.5  christos 	  mode_bits |= 1 << S390_OPCODE_ESA;
    380  1.5  christos 	  str += 3;
    381  1.5  christos 	} else if (strncmp (str, "zarch", 5) == 0
    382  1.5  christos 		   && (str[5] == 0 || str[5] == ',')) {
    383  1.5  christos 	  mode_bits |= 1 << S390_OPCODE_ZARCH;
    384  1.5  christos 	  str += 5;
    385  1.5  christos 	} else {
    386  1.5  christos 	  fprintf (stderr, "Couldn't parse modes string %s\n",
    387  1.5  christos 		   modes_string);
    388  1.5  christos 	  exit (1);
    389  1.5  christos 	}
    390  1.5  christos 	if (*str == ',')
    391  1.5  christos 	  str++;
    392  1.5  christos       } while (*str != 0);
    393  1.5  christos 
    394  1.5  christos       flag_bits = 0;
    395  1.1  christos 
    396  1.5  christos       if (num_matched == 7)
    397  1.5  christos 	{
    398  1.5  christos 	  str = flags_string;
    399  1.1  christos 	  do {
    400  1.5  christos 	    if (strncmp (str, "optparm", 7) == 0
    401  1.5  christos 		&& (str[7] == 0 || str[7] == ',')) {
    402  1.5  christos 	      flag_bits |= S390_INSTR_FLAG_OPTPARM;
    403  1.5  christos 	      str += 7;
    404  1.1  christos 	    } else {
    405  1.5  christos 	      fprintf (stderr, "Couldn't parse flags string %s\n",
    406  1.5  christos 		       flags_string);
    407  1.1  christos 	      exit (1);
    408  1.1  christos 	    }
    409  1.1  christos 	    if (*str == ',')
    410  1.1  christos 	      str++;
    411  1.1  christos 	  } while (*str != 0);
    412  1.1  christos 	}
    413  1.5  christos       insertExpandedMnemonic (opcode, mnemonic, format, min_cpu, mode_bits, flag_bits);
    414  1.1  christos     }
    415  1.1  christos 
    416  1.1  christos   dumpTable ();
    417  1.1  christos   return 0;
    418  1.1  christos }
    419