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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [ia64-opc.c] - Blame information for rev 18

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 18 khays
/* ia64-opc.c -- Functions to access the compacted opcode table
2
   Copyright 1999, 2000, 2001, 2003, 2005, 2007, 2009 Free Software Foundation, Inc.
3
   Written by Bob Manson of Cygnus Solutions, <manson@cygnus.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 "ansidecl.h"
23
#include "sysdep.h"
24
#include "libiberty.h"
25
#include "ia64-asmtab.h"
26
#include "ia64-asmtab.c"
27
 
28
static void get_opc_prefix (const char **, char *);
29
static short int find_string_ent (const char *);
30
static short int find_main_ent (short int);
31
static short int find_completer (short int, short int, const char *);
32
static ia64_insn apply_completer (ia64_insn, int);
33
static int extract_op_bits (int, int, int);
34
static int extract_op (int, int *, unsigned int *);
35
static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
36
static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
37
static struct ia64_opcode *make_ia64_opcode
38
  (ia64_insn, const char *, int, int);
39
static struct ia64_opcode *ia64_find_matching_opcode
40
  (const char *, short int);
41
 
42
const struct ia64_templ_desc ia64_templ_desc[16] =
43
  {
44
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },     /* 0 */
45
    { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
46
    { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
47
    { 0, { 0, },                              "-3-" },
48
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },     /* 4 */
49
    { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
50
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
51
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
52
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },     /* 8 */
53
    { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
54
    { 0, { 0, },                              "-a-" },
55
    { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
56
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },     /* c */
57
    { 0, { 0, },                              "-d-" },
58
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
59
    { 0, { 0, },                              "-f-" },
60
  };
61
 
62
 
63
/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
64
   PTR will be adjusted to point to the start of the next portion
65
   of the opcode, or at the NUL character. */
66
 
67
static void
68
get_opc_prefix (const char **ptr, char *dest)
69
{
70
  char *c = strchr (*ptr, '.');
71
  if (c != NULL)
72
    {
73
      memcpy (dest, *ptr, c - *ptr);
74
      dest[c - *ptr] = '\0';
75
      *ptr = c + 1;
76
    }
77
  else
78
    {
79
      int l = strlen (*ptr);
80
      memcpy (dest, *ptr, l);
81
      dest[l] = '\0';
82
      *ptr += l;
83
    }
84
}
85
 
86
/* Find the index of the entry in the string table corresponding to
87
   STR; return -1 if one does not exist. */
88
 
89
static short
90
find_string_ent (const char *str)
91
{
92
  short start = 0;
93
  short end = sizeof (ia64_strings) / sizeof (const char *);
94
  short i = (start + end) / 2;
95
 
96
  if (strcmp (str, ia64_strings[end - 1]) > 0)
97
    {
98
      return -1;
99
    }
100
  while (start <= end)
101
    {
102
      int c = strcmp (str, ia64_strings[i]);
103
      if (c < 0)
104
        {
105
          end = i - 1;
106
        }
107
      else if (c == 0)
108
        {
109
          return i;
110
        }
111
      else
112
        {
113
          start = i + 1;
114
        }
115
      i = (start + end) / 2;
116
    }
117
  return -1;
118
}
119
 
120
/* Find the opcode in the main opcode table whose name is STRINGINDEX, or
121
   return -1 if one does not exist. */
122
 
123
static short
124
find_main_ent (short nameindex)
125
{
126
  short start = 0;
127
  short end = sizeof (main_table) / sizeof (struct ia64_main_table);
128
  short i = (start + end) / 2;
129
 
130
  if (nameindex < main_table[0].name_index
131
      || nameindex > main_table[end - 1].name_index)
132
    {
133
      return -1;
134
    }
135
  while (start <= end)
136
    {
137
      if (nameindex < main_table[i].name_index)
138
        {
139
          end = i - 1;
140
        }
141
      else if (nameindex == main_table[i].name_index)
142
        {
143
          while (i > 0 && main_table[i - 1].name_index == nameindex)
144
            {
145
              i--;
146
            }
147
          return i;
148
        }
149
      else
150
        {
151
          start = i + 1;
152
        }
153
      i = (start + end) / 2;
154
    }
155
  return -1;
156
}
157
 
158
/* Find the index of the entry in the completer table that is part of
159
   MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
160
   return -1 if one does not exist. */
161
 
162
static short
163
find_completer (short main_ent, short prev_completer, const char *name)
164
{
165
  short name_index = find_string_ent (name);
166
 
167
  if (name_index < 0)
168
    {
169
      return -1;
170
    }
171
 
172
  if (prev_completer == -1)
173
    {
174
      prev_completer = main_table[main_ent].completers;
175
    }
176
  else
177
    {
178
      prev_completer = completer_table[prev_completer].subentries;
179
    }
180
 
181
  while (prev_completer != -1)
182
    {
183
      if (completer_table[prev_completer].name_index == name_index)
184
        {
185
          return prev_completer;
186
        }
187
      prev_completer = completer_table[prev_completer].alternative;
188
    }
189
  return -1;
190
}
191
 
192
/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
193
   return the result. */
194
 
195
static ia64_insn
196
apply_completer (ia64_insn opcode, int completer_index)
197
{
198
  ia64_insn mask = completer_table[completer_index].mask;
199
  ia64_insn bits = completer_table[completer_index].bits;
200
  int shiftamt = (completer_table[completer_index].offset & 63);
201
 
202
  mask = mask << shiftamt;
203
  bits = bits << shiftamt;
204
  opcode = (opcode & ~mask) | bits;
205
  return opcode;
206
}
207
 
208
/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
209
   the dis_table array, and return its value.  (BITOFFSET is numbered
210
   starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
211
   first byte in OP_POINTER.) */
212
 
213
static int
214
extract_op_bits (int op_pointer, int bitoffset, int bits)
215
{
216
  int res = 0;
217
 
218
  op_pointer += (bitoffset / 8);
219
 
220
  if (bitoffset % 8)
221
    {
222
      unsigned int op = dis_table[op_pointer++];
223
      int numb = 8 - (bitoffset % 8);
224
      int mask = (1 << numb) - 1;
225
      int bata = (bits < numb) ? bits : numb;
226
      int delta = numb - bata;
227
 
228
      res = (res << bata) | ((op & mask) >> delta);
229
      bitoffset += bata;
230
      bits -= bata;
231
    }
232
  while (bits >= 8)
233
    {
234
      res = (res << 8) | (dis_table[op_pointer++] & 255);
235
      bits -= 8;
236
    }
237
  if (bits > 0)
238
    {
239
      unsigned int op = (dis_table[op_pointer++] & 255);
240
      res = (res << bits) | (op >> (8 - bits));
241
    }
242
  return res;
243
}
244
 
245
/* Examine the state machine entry at OP_POINTER in the dis_table
246
   array, and extract its values into OPVAL and OP.  The length of the
247
   state entry in bits is returned. */
248
 
249
static int
250
extract_op (int op_pointer, int *opval, unsigned int *op)
251
{
252
  int oplen = 5;
253
 
254
  *op = dis_table[op_pointer];
255
 
256
  if ((*op) & 0x40)
257
    {
258
      opval[0] = extract_op_bits (op_pointer, oplen, 5);
259
      oplen += 5;
260
    }
261
  switch ((*op) & 0x30)
262
    {
263
    case 0x10:
264
      {
265
        opval[1] = extract_op_bits (op_pointer, oplen, 8);
266
        oplen += 8;
267
        opval[1] += op_pointer;
268
        break;
269
      }
270
    case 0x20:
271
      {
272
        opval[1] = extract_op_bits (op_pointer, oplen, 16);
273
        if (! (opval[1] & 32768))
274
          {
275
            opval[1] += op_pointer;
276
          }
277
        oplen += 16;
278
        break;
279
      }
280
    case 0x30:
281
      {
282
        oplen--;
283
        opval[2] = extract_op_bits (op_pointer, oplen, 12);
284
        oplen += 12;
285
        opval[2] |= 32768;
286
        break;
287
      }
288
    }
289
  if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
290
    {
291
      opval[2] = extract_op_bits (op_pointer, oplen, 16);
292
      oplen += 16;
293
      if (! (opval[2] & 32768))
294
        {
295
          opval[2] += op_pointer;
296
        }
297
    }
298
  return oplen;
299
}
300
 
301
/* Returns a non-zero value if the opcode in the main_table list at
302
   PLACE matches OPCODE and is of type TYPE. */
303
 
304
static int
305
opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
306
{
307
  if (main_table[place].opcode_type != type)
308
    {
309
      return 0;
310
    }
311
  if (main_table[place].flags
312
      & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
313
    {
314
      const struct ia64_operand *o1, *o2;
315
      ia64_insn f2, f3;
316
 
317
      if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
318
        {
319
          o1 = elf64_ia64_operands + IA64_OPND_F2;
320
          o2 = elf64_ia64_operands + IA64_OPND_F3;
321
          (*o1->extract) (o1, opcode, &f2);
322
          (*o2->extract) (o2, opcode, &f3);
323
          if (f2 != f3)
324
            return 0;
325
        }
326
      else
327
        {
328
          ia64_insn len, count;
329
 
330
          /* length must equal 64-count: */
331
          o1 = elf64_ia64_operands + IA64_OPND_LEN6;
332
          o2 = elf64_ia64_operands + main_table[place].operands[2];
333
          (*o1->extract) (o1, opcode, &len);
334
          (*o2->extract) (o2, opcode, &count);
335
          if (len != 64 - count)
336
            return 0;
337
        }
338
    }
339
  return 1;
340
}
341
 
342
/* Find an instruction entry in the ia64_dis_names array that matches
343
   opcode OPCODE and is of type TYPE.  Returns either a positive index
344
   into the array, or a negative value if an entry for OPCODE could
345
   not be found.  Checks all matches and returns the one with the highest
346
   priority. */
347
 
348
static int
349
locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
350
{
351
  int currtest[41];
352
  int bitpos[41];
353
  int op_ptr[41];
354
  int currstatenum = 0;
355
  short found_disent = -1;
356
  short found_priority = -1;
357
 
358
  currtest[currstatenum] = 0;
359
  op_ptr[currstatenum] = 0;
360
  bitpos[currstatenum] = 40;
361
 
362
  while (1)
363
    {
364
      int op_pointer = op_ptr[currstatenum];
365
      unsigned int op;
366
      int currbitnum = bitpos[currstatenum];
367
      int oplen;
368
      int opval[3] = {0};
369
      int next_op;
370
      int currbit;
371
 
372
      oplen = extract_op (op_pointer, opval, &op);
373
 
374
      bitpos[currstatenum] = currbitnum;
375
 
376
      /* Skip opval[0] bits in the instruction. */
377
      if (op & 0x40)
378
        {
379
          currbitnum -= opval[0];
380
        }
381
 
382
      /* The value of the current bit being tested. */
383
      currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
384
      next_op = -1;
385
 
386
      /* We always perform the tests specified in the current state in
387
         a particular order, falling through to the next test if the
388
         previous one failed. */
389
      switch (currtest[currstatenum])
390
        {
391
        case 0:
392
          currtest[currstatenum]++;
393
          if (currbit == 0 && (op & 0x80))
394
            {
395
              /* Check for a zero bit.  If this test solely checks for
396
                 a zero bit, we can check for up to 8 consecutive zero
397
                 bits (the number to check is specified by the lower 3
398
                 bits in the state code.)
399
 
400
                 If the state instruction matches, we go to the very
401
                 next state instruction; otherwise, try the next test. */
402
 
403
              if ((op & 0xf8) == 0x80)
404
                {
405
                  int count = op & 0x7;
406
                  int x;
407
 
408
                  for (x = 0; x <= count; x++)
409
                    {
410
                      int i =
411
                        opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
412
                      if (i)
413
                        {
414
                          break;
415
                        }
416
                    }
417
                  if (x > count)
418
                    {
419
                      next_op = op_pointer + ((oplen + 7) / 8);
420
                      currbitnum -= count;
421
                      break;
422
                    }
423
                }
424
              else if (! currbit)
425
                {
426
                  next_op = op_pointer + ((oplen + 7) / 8);
427
                  break;
428
                }
429
            }
430
          /* FALLTHROUGH */
431
        case 1:
432
          /* If the bit in the instruction is one, go to the state
433
             instruction specified by opval[1]. */
434
          currtest[currstatenum]++;
435
          if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
436
            {
437
              next_op = opval[1];
438
              break;
439
            }
440
          /* FALLTHROUGH */
441
        case 2:
442
          /* Don't care.  Skip the current bit and go to the state
443
             instruction specified by opval[2].
444
 
445
             An encoding of 0x30 is special; this means that a 12-bit
446
             offset into the ia64_dis_names[] array is specified.  */
447
          currtest[currstatenum]++;
448
          if ((op & 0x08) || ((op & 0x30) == 0x30))
449
            {
450
              next_op = opval[2];
451
              break;
452
            }
453
        }
454
 
455
      /* If bit 15 is set in the address of the next state, an offset
456
         in the ia64_dis_names array was specified instead.  We then
457
         check to see if an entry in the list of opcodes matches the
458
         opcode we were given; if so, we have succeeded.  */
459
 
460
      if ((next_op >= 0) && (next_op & 32768))
461
        {
462
          short disent = next_op & 32767;
463
          short priority = -1;
464
 
465
          if (next_op > 65535)
466
            {
467
              abort ();
468
            }
469
 
470
          /* Run through the list of opcodes to check, trying to find
471
             one that matches.  */
472
          while (disent >= 0)
473
            {
474
              int place = ia64_dis_names[disent].insn_index;
475
 
476
              priority = ia64_dis_names[disent].priority;
477
 
478
              if (opcode_verify (opcode, place, type)
479
                  && priority > found_priority)
480
                {
481
                  break;
482
                }
483
              if (ia64_dis_names[disent].next_flag)
484
                {
485
                  disent++;
486
                }
487
              else
488
                {
489
                  disent = -1;
490
                }
491
            }
492
 
493
          if (disent >= 0)
494
            {
495
              found_disent = disent;
496
              found_priority = priority;
497
            }
498
          /* Try the next test in this state, regardless of whether a match
499
             was found. */
500
          next_op = -2;
501
        }
502
 
503
      /* next_op == -1 is "back up to the previous state".
504
         next_op == -2 is "stay in this state and try the next test".
505
         Otherwise, transition to the state indicated by next_op. */
506
 
507
      if (next_op == -1)
508
        {
509
          currstatenum--;
510
          if (currstatenum < 0)
511
            {
512
              return found_disent;
513
            }
514
        }
515
      else if (next_op >= 0)
516
        {
517
          currstatenum++;
518
          bitpos[currstatenum] = currbitnum - 1;
519
          op_ptr[currstatenum] = next_op;
520
          currtest[currstatenum] = 0;
521
        }
522
    }
523
}
524
 
525
/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
526
 
527
static struct ia64_opcode *
528
make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
529
{
530
  struct ia64_opcode *res =
531
    (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
532
  res->name = xstrdup (name);
533
  res->type = main_table[place].opcode_type;
534
  res->num_outputs = main_table[place].num_outputs;
535
  res->opcode = opcode;
536
  res->mask = main_table[place].mask;
537
  res->operands[0] = main_table[place].operands[0];
538
  res->operands[1] = main_table[place].operands[1];
539
  res->operands[2] = main_table[place].operands[2];
540
  res->operands[3] = main_table[place].operands[3];
541
  res->operands[4] = main_table[place].operands[4];
542
  res->flags = main_table[place].flags;
543
  res->ent_index = place;
544
  res->dependencies = &op_dependencies[depind];
545
  return res;
546
}
547
 
548
/* Determine the ia64_opcode entry for the opcode specified by INSN
549
   and TYPE.  If a valid entry is not found, return NULL. */
550
struct ia64_opcode *
551
ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
552
{
553
  int disent = locate_opcode_ent (insn, type);
554
 
555
  if (disent < 0)
556
    {
557
      return NULL;
558
    }
559
  else
560
    {
561
      unsigned int cb = ia64_dis_names[disent].completer_index;
562
      static char name[128];
563
      int place = ia64_dis_names[disent].insn_index;
564
      int ci = main_table[place].completers;
565
      ia64_insn tinsn = main_table[place].opcode;
566
 
567
      strcpy (name, ia64_strings [main_table[place].name_index]);
568
 
569
      while (cb)
570
        {
571
          if (cb & 1)
572
            {
573
              int cname = completer_table[ci].name_index;
574
 
575
              tinsn = apply_completer (tinsn, ci);
576
 
577
              if (ia64_strings[cname][0] != '\0')
578
                {
579
                  strcat (name, ".");
580
                  strcat (name, ia64_strings[cname]);
581
                }
582
              if (cb != 1)
583
                {
584
                  ci = completer_table[ci].subentries;
585
                }
586
            }
587
          else
588
            {
589
              ci = completer_table[ci].alternative;
590
            }
591
          if (ci < 0)
592
            {
593
              abort ();
594
            }
595
          cb = cb >> 1;
596
        }
597
      if (tinsn != (insn & main_table[place].mask))
598
        {
599
          abort ();
600
        }
601
      return make_ia64_opcode (insn, name, place,
602
                               completer_table[ci].dependencies);
603
    }
604
}
605
 
606
/* Search the main_opcode table starting from PLACE for an opcode that
607
   matches NAME.  Return NULL if one is not found. */
608
 
609
static struct ia64_opcode *
610
ia64_find_matching_opcode (const char *name, short place)
611
{
612
  char op[129];
613
  const char *suffix;
614
  short name_index;
615
 
616
  if (strlen (name) > 128)
617
    {
618
      return NULL;
619
    }
620
  suffix = name;
621
  get_opc_prefix (&suffix, op);
622
  name_index = find_string_ent (op);
623
  if (name_index < 0)
624
    {
625
      return NULL;
626
    }
627
 
628
  while (main_table[place].name_index == name_index)
629
    {
630
      const char *curr_suffix = suffix;
631
      ia64_insn curr_insn = main_table[place].opcode;
632
      short completer = -1;
633
 
634
      do {
635
        if (suffix[0] == '\0')
636
          {
637
            completer = find_completer (place, completer, suffix);
638
          }
639
        else
640
          {
641
            get_opc_prefix (&curr_suffix, op);
642
            completer = find_completer (place, completer, op);
643
          }
644
        if (completer != -1)
645
          {
646
            curr_insn = apply_completer (curr_insn, completer);
647
          }
648
      } while (completer != -1 && curr_suffix[0] != '\0');
649
 
650
      if (completer != -1 && curr_suffix[0] == '\0'
651
          && completer_table[completer].terminal_completer)
652
        {
653
          int depind = completer_table[completer].dependencies;
654
          return make_ia64_opcode (curr_insn, name, place, depind);
655
        }
656
      else
657
        {
658
          place++;
659
        }
660
    }
661
  return NULL;
662
}
663
 
664
/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
665
   if one does not exist.
666
 
667
   It is the caller's responsibility to invoke ia64_free_opcode () to
668
   release any resources used by the returned entry. */
669
 
670
struct ia64_opcode *
671
ia64_find_next_opcode (struct ia64_opcode *prev_ent)
672
{
673
  return ia64_find_matching_opcode (prev_ent->name,
674
                                    prev_ent->ent_index + 1);
675
}
676
 
677
/* Find the first opcode that matches NAME, or return NULL if it does
678
   not exist.
679
 
680
   It is the caller's responsibility to invoke ia64_free_opcode () to
681
   release any resources used by the returned entry. */
682
 
683
struct ia64_opcode *
684
ia64_find_opcode (const char *name)
685
{
686
  char op[129];
687
  const char *suffix;
688
  short place;
689
  short name_index;
690
 
691
  if (strlen (name) > 128)
692
    {
693
      return NULL;
694
    }
695
  suffix = name;
696
  get_opc_prefix (&suffix, op);
697
  name_index = find_string_ent (op);
698
  if (name_index < 0)
699
    {
700
      return NULL;
701
    }
702
 
703
  place = find_main_ent (name_index);
704
 
705
  if (place < 0)
706
    {
707
      return NULL;
708
    }
709
  return ia64_find_matching_opcode (name, place);
710
}
711
 
712
/* Free any resources used by ENT. */
713
void
714
ia64_free_opcode (struct ia64_opcode *ent)
715
{
716
  free ((void *)ent->name);
717
  free (ent);
718
}
719
 
720
const struct ia64_dependency *
721
ia64_find_dependency (int dep_index)
722
{
723
  dep_index = DEP(dep_index);
724
 
725
  if (dep_index < 0
726
      || dep_index >= (int) ARRAY_SIZE (dependencies))
727
    return NULL;
728
 
729
  return &dependencies[dep_index];
730
}

powered by: WebSVN 2.1.0

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