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