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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [d10v-dis.c] - Blame information for rev 1775

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

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

powered by: WebSVN 2.1.0

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