OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [s390-mkopc.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.