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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [opcodes/] [d10v-dis.c] - Blame information for rev 205

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

Line No. Rev Author Line
1 205 julius
/* Disassemble D10V instructions.
2
   Copyright 1996, 1997, 1998, 2000, 2001, 2005, 2007
3
   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 program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include <stdio.h>
23
 
24
#include "sysdep.h"
25
#include "opcode/d10v.h"
26
#include "dis-asm.h"
27
 
28
/* The PC wraps at 18 bits, except for the segment number,
29
   so use this mask to keep the parts we want.  */
30
#define PC_MASK 0x0303FFFF
31
 
32
static void
33
print_operand (struct d10v_operand *oper,
34
               unsigned long insn,
35
               struct d10v_opcode *op,
36
               bfd_vma memaddr,
37
               struct disassemble_info *info)
38
{
39
  int num, shift;
40
 
41
  if (oper->flags == OPERAND_ATMINUS)
42
    {
43
      (*info->fprintf_func) (info->stream, "@-");
44
      return;
45
    }
46
  if (oper->flags == OPERAND_MINUS)
47
    {
48
      (*info->fprintf_func) (info->stream, "-");
49
      return;
50
    }
51
  if (oper->flags == OPERAND_PLUS)
52
    {
53
      (*info->fprintf_func) (info->stream, "+");
54
      return;
55
    }
56
  if (oper->flags == OPERAND_ATSIGN)
57
    {
58
      (*info->fprintf_func) (info->stream, "@");
59
      return;
60
    }
61
  if (oper->flags == OPERAND_ATPAR)
62
    {
63
      (*info->fprintf_func) (info->stream, "@(");
64
      return;
65
    }
66
 
67
  shift = oper->shift;
68
 
69
  /* The LONG_L format shifts registers over by 15.  */
70
  if (op->format == LONG_L && (oper->flags & OPERAND_REG))
71
    shift += 15;
72
 
73
  num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits));
74
 
75
  if (oper->flags & OPERAND_REG)
76
    {
77
      int i;
78
      int match = 0;
79
 
80
      num += (oper->flags
81
              & (OPERAND_GPR | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL));
82
      if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
83
        num += num ? OPERAND_ACC1 : OPERAND_ACC0;
84
      for (i = 0; i < d10v_reg_name_cnt (); i++)
85
        {
86
          if (num == (d10v_predefined_registers[i].value & ~ OPERAND_SP))
87
            {
88
              if (d10v_predefined_registers[i].pname)
89
                (*info->fprintf_func) (info->stream, "%s",
90
                                       d10v_predefined_registers[i].pname);
91
              else
92
                (*info->fprintf_func) (info->stream, "%s",
93
                                       d10v_predefined_registers[i].name);
94
              match = 1;
95
              break;
96
            }
97
        }
98
      if (match == 0)
99
        {
100
          /* This would only get executed if a register was not in the
101
             register table.  */
102
          if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
103
            (*info->fprintf_func) (info->stream, "a");
104
          else if (oper->flags & OPERAND_CONTROL)
105
            (*info->fprintf_func) (info->stream, "cr");
106
          else if (oper->flags & OPERAND_REG)
107
            (*info->fprintf_func) (info->stream, "r");
108
          (*info->fprintf_func) (info->stream, "%d", num & REGISTER_MASK);
109
        }
110
    }
111
  else
112
    {
113
      /* Addresses are right-shifted by 2.  */
114
      if (oper->flags & OPERAND_ADDR)
115
        {
116
          long max;
117
          int neg = 0;
118
 
119
          max = (1 << (oper->bits - 1));
120
          if (num & max)
121
            {
122
              num = -num & ((1 << oper->bits) - 1);
123
              neg = 1;
124
            }
125
          num = num << 2;
126
          if (info->flags & INSN_HAS_RELOC)
127
            (*info->print_address_func) (num & PC_MASK, info);
128
          else
129
            {
130
              if (neg)
131
                (*info->print_address_func) ((memaddr - num) & PC_MASK, info);
132
              else
133
                (*info->print_address_func) ((memaddr + num) & PC_MASK, info);
134
            }
135
        }
136
      else
137
        {
138
          if (oper->flags & OPERAND_SIGNED)
139
            {
140
              int max = (1 << (oper->bits - 1));
141
              if (num & max)
142
                {
143
                  num = -num & ((1 << oper->bits) - 1);
144
                  (*info->fprintf_func) (info->stream, "-");
145
                }
146
            }
147
          (*info->fprintf_func) (info->stream, "0x%x", num);
148
        }
149
    }
150
}
151
 
152
static void
153
dis_long (unsigned long insn,
154
          bfd_vma memaddr,
155
          struct disassemble_info *info)
156
{
157
  int i;
158
  struct d10v_opcode *op = (struct d10v_opcode *) d10v_opcodes;
159
  struct d10v_operand *oper;
160
  int need_paren = 0;
161
  int match = 0;
162
 
163
  while (op->name)
164
    {
165
      if ((op->format & LONG_OPCODE)
166
          && ((op->mask & insn) == (unsigned long) op->opcode))
167
        {
168
          match = 1;
169
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
170
 
171
          for (i = 0; op->operands[i]; i++)
172
            {
173
              oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
174
              if (oper->flags == OPERAND_ATPAR)
175
                need_paren = 1;
176
              print_operand (oper, insn, op, memaddr, info);
177
              if (op->operands[i + 1] && oper->bits
178
                  && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
179
                  && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
180
                (*info->fprintf_func) (info->stream, ", ");
181
            }
182
          break;
183
        }
184
      op++;
185
    }
186
 
187
  if (!match)
188
    (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
189
 
190
  if (need_paren)
191
    (*info->fprintf_func) (info->stream, ")");
192
}
193
 
194
static void
195
dis_2_short (unsigned long insn,
196
             bfd_vma memaddr,
197
             struct disassemble_info *info,
198
             int order)
199
{
200
  int i, j;
201
  unsigned int ins[2];
202
  struct d10v_opcode *op;
203
  int match, num_match = 0;
204
  struct d10v_operand *oper;
205
  int need_paren = 0;
206
 
207
  ins[0] = (insn & 0x3FFFFFFF) >> 15;
208
  ins[1] = insn & 0x00007FFF;
209
 
210
  for (j = 0; j < 2; j++)
211
    {
212
      op = (struct d10v_opcode *) d10v_opcodes;
213
      match = 0;
214
      while (op->name)
215
        {
216
          if ((op->format & SHORT_OPCODE)
217
              && ((((unsigned int) op->mask) & ins[j])
218
                  == (unsigned int) op->opcode))
219
            {
220
              (*info->fprintf_func) (info->stream, "%s\t", op->name);
221
              for (i = 0; op->operands[i]; i++)
222
                {
223
                  oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
224
                  if (oper->flags == OPERAND_ATPAR)
225
                    need_paren = 1;
226
                  print_operand (oper, ins[j], op, memaddr, info);
227
                  if (op->operands[i + 1] && oper->bits
228
                      && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
229
                      && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
230
                    (*info->fprintf_func) (info->stream, ", ");
231
                }
232
              match = 1;
233
              num_match++;
234
              break;
235
            }
236
          op++;
237
        }
238
      if (!match)
239
        (*info->fprintf_func) (info->stream, "unknown");
240
 
241
      switch (order)
242
        {
243
        case 0:
244
          (*info->fprintf_func) (info->stream, "\t->\t");
245
          order = -1;
246
          break;
247
        case 1:
248
          (*info->fprintf_func) (info->stream, "\t<-\t");
249
          order = -1;
250
          break;
251
        case 2:
252
          (*info->fprintf_func) (info->stream, "\t||\t");
253
          order = -1;
254
          break;
255
        default:
256
          break;
257
        }
258
    }
259
 
260
  if (num_match == 0)
261
    (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
262
 
263
  if (need_paren)
264
    (*info->fprintf_func) (info->stream, ")");
265
}
266
 
267
int
268
print_insn_d10v (bfd_vma memaddr, struct disassemble_info *info)
269
{
270
  int status;
271
  bfd_byte buffer[4];
272
  unsigned long insn;
273
 
274
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
275
  if (status != 0)
276
    {
277
      (*info->memory_error_func) (status, memaddr, info);
278
      return -1;
279
    }
280
  insn = bfd_getb32 (buffer);
281
 
282
  status = insn & FM11;
283
  switch (status)
284
    {
285
    case 0:
286
      dis_2_short (insn, memaddr, info, 2);
287
      break;
288
    case FM01:
289
      dis_2_short (insn, memaddr, info, 0);
290
      break;
291
    case FM10:
292
      dis_2_short (insn, memaddr, info, 1);
293
      break;
294
    case FM11:
295
      dis_long (insn, memaddr, info);
296
      break;
297
    }
298
  return 4;
299
}

powered by: WebSVN 2.1.0

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