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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [spu-dis.c] - Blame information for rev 298

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

Line No. Rev Author Line
1 18 khays
/* Disassemble SPU instructions
2
 
3
   Copyright 2006, 2007 Free Software Foundation, Inc.
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 "sysdep.h"
24
#include "dis-asm.h"
25
#include "opcode/spu.h"
26
 
27
/* This file provides a disassembler function which uses
28
   the disassembler interface defined in dis-asm.h.   */
29
 
30
extern const struct spu_opcode spu_opcodes[];
31
extern const int spu_num_opcodes;
32
 
33
static const struct spu_opcode *spu_disassemble_table[(1<<11)];
34
 
35
static void
36
init_spu_disassemble (void)
37
{
38
  int i;
39
 
40
  /* If two instructions have the same opcode then we prefer the first
41
   * one.  In most cases it is just an alternate mnemonic. */
42
  for (i = 0; i < spu_num_opcodes; i++)
43
    {
44
      int o = spu_opcodes[i].opcode;
45
      if (o >= (1 << 11))
46
        abort ();
47
      if (spu_disassemble_table[o] == 0)
48
        spu_disassemble_table[o] = &spu_opcodes[i];
49
    }
50
}
51
 
52
/* Determine the instruction from the 10 least significant bits. */
53
static const struct spu_opcode *
54
get_index_for_opcode (unsigned int insn)
55
{
56
  const struct spu_opcode *op_index;
57
  unsigned int opcode = insn >> (32-11);
58
 
59
  /* Init the table.  This assumes that element 0/opcode 0 (currently
60
   * NOP) is always used */
61
  if (spu_disassemble_table[0] == 0)
62
    init_spu_disassemble ();
63
 
64
  if ((op_index = spu_disassemble_table[opcode & 0x780]) != 0
65
      && op_index->insn_type == RRR)
66
    return op_index;
67
 
68
  if ((op_index = spu_disassemble_table[opcode & 0x7f0]) != 0
69
      && (op_index->insn_type == RI18 || op_index->insn_type == LBT))
70
    return op_index;
71
 
72
  if ((op_index = spu_disassemble_table[opcode & 0x7f8]) != 0
73
      && op_index->insn_type == RI10)
74
    return op_index;
75
 
76
  if ((op_index = spu_disassemble_table[opcode & 0x7fc]) != 0
77
      && (op_index->insn_type == RI16))
78
    return op_index;
79
 
80
  if ((op_index = spu_disassemble_table[opcode & 0x7fe]) != 0
81
      && (op_index->insn_type == RI8))
82
    return op_index;
83
 
84
  if ((op_index = spu_disassemble_table[opcode & 0x7ff]) != 0)
85
    return op_index;
86
 
87
  return 0;
88
}
89
 
90
/* Print a Spu instruction.  */
91
 
92
int
93
print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
94
{
95
  bfd_byte buffer[4];
96
  int value;
97
  int hex_value;
98
  int status;
99
  unsigned int insn;
100
  const struct spu_opcode *op_index;
101
  enum spu_insns tag;
102
 
103
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
104
  if (status != 0)
105
    {
106
      (*info->memory_error_func) (status, memaddr, info);
107
      return -1;
108
    }
109
 
110
  insn = bfd_getb32 (buffer);
111
 
112
  op_index = get_index_for_opcode (insn);
113
 
114
  if (op_index == 0)
115
    {
116
      (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
117
    }
118
  else
119
    {
120
      int i;
121
      int paren = 0;
122
      tag = (enum spu_insns)(op_index - spu_opcodes);
123
      (*info->fprintf_func) (info->stream, "%s", op_index->mnemonic);
124
      if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
125
          || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
126
          || tag == M_SYNC || tag == M_HBR)
127
        {
128
          int fb = (insn >> (32-18)) & 0x7f;
129
          if (fb & 0x40)
130
            (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
131
          if (fb & 0x20)
132
            (*info->fprintf_func) (info->stream, "d");
133
          if (fb & 0x10)
134
            (*info->fprintf_func) (info->stream, "e");
135
        }
136
      if (op_index->arg[0] != 0)
137
        (*info->fprintf_func) (info->stream, "\t");
138
      hex_value = 0;
139
      for (i = 1;  i <= op_index->arg[0]; i++)
140
        {
141
          int arg = op_index->arg[i];
142
          if (arg != A_P && !paren && i > 1)
143
            (*info->fprintf_func) (info->stream, ",");
144
 
145
          switch (arg)
146
            {
147
            case A_T:
148
              (*info->fprintf_func) (info->stream, "$%d",
149
                                     DECODE_INSN_RT (insn));
150
              break;
151
            case A_A:
152
              (*info->fprintf_func) (info->stream, "$%d",
153
                                     DECODE_INSN_RA (insn));
154
              break;
155
            case A_B:
156
              (*info->fprintf_func) (info->stream, "$%d",
157
                                     DECODE_INSN_RB (insn));
158
              break;
159
            case A_C:
160
              (*info->fprintf_func) (info->stream, "$%d",
161
                                     DECODE_INSN_RC (insn));
162
              break;
163
            case A_S:
164
              (*info->fprintf_func) (info->stream, "$sp%d",
165
                                     DECODE_INSN_RA (insn));
166
              break;
167
            case A_H:
168
              (*info->fprintf_func) (info->stream, "$ch%d",
169
                                     DECODE_INSN_RA (insn));
170
              break;
171
            case A_P:
172
              paren++;
173
              (*info->fprintf_func) (info->stream, "(");
174
              break;
175
            case A_U7A:
176
              (*info->fprintf_func) (info->stream, "%d",
177
                                     173 - DECODE_INSN_U8 (insn));
178
              break;
179
            case A_U7B:
180
              (*info->fprintf_func) (info->stream, "%d",
181
                                     155 - DECODE_INSN_U8 (insn));
182
              break;
183
            case A_S3:
184
            case A_S6:
185
            case A_S7:
186
            case A_S7N:
187
            case A_U3:
188
            case A_U5:
189
            case A_U6:
190
            case A_U7:
191
              hex_value = DECODE_INSN_I7 (insn);
192
              (*info->fprintf_func) (info->stream, "%d", hex_value);
193
              break;
194
            case A_S11:
195
              (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
196
                                           info);
197
              break;
198
            case A_S11I:
199
              (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
200
                                           info);
201
              break;
202
            case A_S10:
203
            case A_S10B:
204
              hex_value = DECODE_INSN_I10 (insn);
205
              (*info->fprintf_func) (info->stream, "%d", hex_value);
206
              break;
207
            case A_S14:
208
              hex_value = DECODE_INSN_I10 (insn) * 16;
209
              (*info->fprintf_func) (info->stream, "%d", hex_value);
210
              break;
211
            case A_S16:
212
              hex_value = DECODE_INSN_I16 (insn);
213
              (*info->fprintf_func) (info->stream, "%d", hex_value);
214
              break;
215
            case A_X16:
216
              hex_value = DECODE_INSN_U16 (insn);
217
              (*info->fprintf_func) (info->stream, "%u", hex_value);
218
              break;
219
            case A_R18:
220
              value = DECODE_INSN_I16 (insn) * 4;
221
              if (value == 0)
222
                (*info->fprintf_func) (info->stream, "%d", value);
223
              else
224
                {
225
                  hex_value = memaddr + value;
226
                  (*info->print_address_func) (hex_value & 0x3ffff, info);
227
                }
228
              break;
229
            case A_S18:
230
              value = DECODE_INSN_U16 (insn) * 4;
231
              if (value == 0)
232
                (*info->fprintf_func) (info->stream, "%d", value);
233
              else
234
                (*info->print_address_func) (value, info);
235
              break;
236
            case A_U18:
237
              value = DECODE_INSN_U18 (insn);
238
              if (value == 0 || !(*info->symbol_at_address_func)(0, info))
239
                {
240
                  hex_value = value;
241
                  (*info->fprintf_func) (info->stream, "%u", value);
242
                }
243
              else
244
                (*info->print_address_func) (value, info);
245
              break;
246
            case A_U14:
247
              hex_value = DECODE_INSN_U14 (insn);
248
              (*info->fprintf_func) (info->stream, "%u", hex_value);
249
              break;
250
            }
251
          if (arg != A_P && paren)
252
            {
253
              (*info->fprintf_func) (info->stream, ")");
254
              paren--;
255
            }
256
        }
257
      if (hex_value > 16)
258
        (*info->fprintf_func) (info->stream, "\t# %x", hex_value);
259
    }
260
  return 4;
261
}

powered by: WebSVN 2.1.0

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