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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [ia64-opc.c] - Blame information for rev 1771

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

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

powered by: WebSVN 2.1.0

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