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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [d10v-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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