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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [ia64-dis.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-dis.c -- Disassemble ia64 instructions
2
   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
3
   Contributed by David Mosberger-Tang <davidm@hpl.hp.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 <assert.h>
23
#include <string.h>
24
 
25
#include "dis-asm.h"
26
#include "opcode/ia64.h"
27
 
28
#define NELEMS(a)       ((int) (sizeof (a) / sizeof (a[0])))
29
 
30
/* Disassemble ia64 instruction.  */
31
 
32
/* Return the instruction type for OPCODE found in unit UNIT. */
33
 
34
static enum ia64_insn_type
35
unit_to_type (ia64_insn opcode, enum ia64_unit unit)
36
{
37
  enum ia64_insn_type type;
38
  int op;
39
 
40
  op = IA64_OP (opcode);
41
 
42
  if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
43
    {
44
      type = IA64_TYPE_A;
45
    }
46
  else
47
    {
48
      switch (unit)
49
        {
50
        case IA64_UNIT_I:
51
          type = IA64_TYPE_I; break;
52
        case IA64_UNIT_M:
53
          type = IA64_TYPE_M; break;
54
        case IA64_UNIT_B:
55
          type = IA64_TYPE_B; break;
56
        case IA64_UNIT_F:
57
          type = IA64_TYPE_F; break;
58
        case IA64_UNIT_L:
59
        case IA64_UNIT_X:
60
          type = IA64_TYPE_X; break;
61
        default:
62
          type = -1;
63
        }
64
    }
65
  return type;
66
}
67
 
68
int
69
print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
70
{
71
  ia64_insn t0, t1, slot[3], template, s_bit, insn;
72
  int slotnum, j, status, need_comma, retval, slot_multiplier;
73
  const struct ia64_operand *odesc;
74
  const struct ia64_opcode *idesc;
75
  const char *err, *str, *tname;
76
  BFD_HOST_U_64_BIT value;
77
  bfd_byte bundle[16];
78
  enum ia64_unit unit;
79
  char regname[16];
80
 
81
  if (info->bytes_per_line == 0)
82
    info->bytes_per_line = 6;
83
  info->display_endian = info->endian;
84
 
85
  slot_multiplier = info->bytes_per_line;
86
  retval = slot_multiplier;
87
 
88
  slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
89
  if (slotnum > 2)
90
    return -1;
91
 
92
  memaddr -= (memaddr & 0xf);
93
  status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
94
  if (status != 0)
95
    {
96
      (*info->memory_error_func) (status, memaddr, info);
97
      return -1;
98
    }
99
  /* bundles are always in little-endian byte order */
100
  t0 = bfd_getl64 (bundle);
101
  t1 = bfd_getl64 (bundle + 8);
102
  s_bit = t0 & 1;
103
  template = (t0 >> 1) & 0xf;
104
  slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
105
  slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
106
  slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
107
 
108
  tname = ia64_templ_desc[template].name;
109
  if (slotnum == 0)
110
    (*info->fprintf_func) (info->stream, "[%s] ", tname);
111
  else
112
    (*info->fprintf_func) (info->stream, "      ", tname);
113
 
114
  unit = ia64_templ_desc[template].exec_unit[slotnum];
115
 
116
  if (template == 2 && slotnum == 1)
117
    {
118
      /* skip L slot in MLI template: */
119
      slotnum = 2;
120
      retval += slot_multiplier;
121
    }
122
 
123
  insn = slot[slotnum];
124
 
125
  if (unit == IA64_UNIT_NIL)
126
    goto decoding_failed;
127
 
128
  idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
129
  if (idesc == NULL)
130
    goto decoding_failed;
131
 
132
  /* print predicate, if any: */
133
 
134
  if ((idesc->flags & IA64_OPCODE_NO_PRED)
135
      || (insn & 0x3f) == 0)
136
    (*info->fprintf_func) (info->stream, "      ");
137
  else
138
    (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
139
 
140
  /* now the actual instruction: */
141
 
142
  (*info->fprintf_func) (info->stream, "%s", idesc->name);
143
  if (idesc->operands[0])
144
    (*info->fprintf_func) (info->stream, " ");
145
 
146
  need_comma = 0;
147
  for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
148
    {
149
      odesc = elf64_ia64_operands + idesc->operands[j];
150
 
151
      if (need_comma)
152
        (*info->fprintf_func) (info->stream, ",");
153
 
154
      if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
155
        {
156
          /* special case of 64 bit immediate load: */
157
          value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
158
            | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
159
            | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
160
        }
161
      else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
162
        {
163
          /* 62-bit immediate for nop.x/break.x */
164
          value = ((slot[1] & 0x1ffffffffffLL) << 21)
165
            | (((insn >> 36) & 0x1) << 20)
166
            | ((insn >> 6) & 0xfffff);
167
        }
168
      else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
169
        {
170
          /* 60-bit immedate for long branches.  */
171
          value = (((insn >> 13) & 0xfffff)
172
                   | (((insn >> 36) & 1) << 59)
173
                   | (slot[1] << 20)) << 4;
174
        }
175
      else
176
        {
177
          err = (*odesc->extract) (odesc, insn, &value);
178
          if (err)
179
            {
180
              (*info->fprintf_func) (info->stream, "%s", err);
181
              goto done;
182
            }
183
        }
184
 
185
        switch (odesc->class)
186
          {
187
          case IA64_OPND_CLASS_CST:
188
            (*info->fprintf_func) (info->stream, "%s", odesc->str);
189
            break;
190
 
191
          case IA64_OPND_CLASS_REG:
192
            if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
193
              {
194
                switch (value)
195
                  {
196
                  case 0: case 1: case 2: case 3:
197
                  case 4: case 5: case 6: case 7:
198
                    sprintf (regname, "ar.k%u", (unsigned int) value);
199
                    break;
200
                  case 16:      strcpy (regname, "ar.rsc"); break;
201
                  case 17:      strcpy (regname, "ar.bsp"); break;
202
                  case 18:      strcpy (regname, "ar.bspstore"); break;
203
                  case 19:      strcpy (regname, "ar.rnat"); break;
204
                  case 32:      strcpy (regname, "ar.ccv"); break;
205
                  case 36:      strcpy (regname, "ar.unat"); break;
206
                  case 40:      strcpy (regname, "ar.fpsr"); break;
207
                  case 44:      strcpy (regname, "ar.itc"); break;
208
                  case 64:      strcpy (regname, "ar.pfs"); break;
209
                  case 65:      strcpy (regname, "ar.lc"); break;
210
                  case 66:      strcpy (regname, "ar.ec"); break;
211
                  default:
212
                    sprintf (regname, "ar%u", (unsigned int) value);
213
                    break;
214
                  }
215
                (*info->fprintf_func) (info->stream, "%s", regname);
216
              }
217
            else
218
              (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
219
            break;
220
 
221
          case IA64_OPND_CLASS_IND:
222
            (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
223
            break;
224
 
225
          case IA64_OPND_CLASS_ABS:
226
            str = 0;
227
            if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
228
              switch (value)
229
                {
230
                case 0x0: str = "@brcst"; break;
231
                case 0x8: str = "@mix"; break;
232
                case 0x9: str = "@shuf"; break;
233
                case 0xa: str = "@alt"; break;
234
                case 0xb: str = "@rev"; break;
235
                }
236
 
237
            if (str)
238
              (*info->fprintf_func) (info->stream, "%s", str);
239
            else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
240
              (*info->fprintf_func) (info->stream, "%lld", value);
241
            else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
242
              (*info->fprintf_func) (info->stream, "%llu", value);
243
            else
244
              (*info->fprintf_func) (info->stream, "0x%llx", value);
245
            break;
246
 
247
          case IA64_OPND_CLASS_REL:
248
            (*info->print_address_func) (memaddr + value, info);
249
            break;
250
          }
251
 
252
      need_comma = 1;
253
      if (j + 1 == idesc->num_outputs)
254
        {
255
          (*info->fprintf_func) (info->stream, "=");
256
          need_comma = 0;
257
        }
258
    }
259
  if (slotnum + 1 == ia64_templ_desc[template].group_boundary
260
      || ((slotnum == 2) && s_bit))
261
    (*info->fprintf_func) (info->stream, ";;");
262
 
263
 done:
264
  ia64_free_opcode ((struct ia64_opcode *)idesc);
265
 failed:
266
  if (slotnum == 2)
267
    retval += 16 - 3*slot_multiplier;
268
  return retval;
269
 
270
 decoding_failed:
271
  (*info->fprintf_func) (info->stream, "      data8 %#011llx", insn);
272
  goto failed;
273
}

powered by: WebSVN 2.1.0

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