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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [opcodes/] [s390-mkopc.c] - Blame information for rev 6

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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