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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [v850-dis.c] - Blame information for rev 1778

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

Line No. Rev Author Line
1 578 markom
/* Disassemble V850 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/v850.h" 
23
#include "dis-asm.h"
24
#include "opintl.h"
25
 
26
static const char *const v850_reg_names[] =
27
{ "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
28
  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
29
  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
30
  "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
31
 
32
static const char *const v850_sreg_names[] =
33
{ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
34
  "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
35
  "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
36
  "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
37
  "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
38
  "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
39
 
40
static const char *const v850_cc_names[] =
41
{ "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
42
  "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
43
 
44
static int
45
disassemble (memaddr, info, insn)
46
     bfd_vma memaddr;
47
     struct disassemble_info *info;
48
     unsigned long insn;
49
{
50
  struct v850_opcode *          op = (struct v850_opcode *)v850_opcodes;
51
  const struct v850_operand *   operand;
52
  int                           match = 0;
53
  int                           short_op = ((insn & 0x0600) != 0x0600);
54
  int                           bytes_read;
55
  int                           target_processor;
56
 
57
  /* Special case: 32 bit MOV */
58
  if ((insn & 0xffe0) == 0x0620)
59
    short_op = true;
60
 
61
  bytes_read = short_op ? 2 : 4;
62
 
63
  /* If this is a two byte insn, then mask off the high bits. */
64
  if (short_op)
65
    insn &= 0xffff;
66
 
67
  switch (info->mach)
68
    {
69
    case 0:
70
    default:
71
      target_processor = PROCESSOR_V850;
72
      break;
73
 
74
    case bfd_mach_v850e:
75
      target_processor = PROCESSOR_V850E;
76
      break;
77
 
78
    case bfd_mach_v850ea:
79
      target_processor = PROCESSOR_V850EA;
80
      break;
81
    }
82
 
83
  /* Find the opcode.  */
84
  while (op->name)
85
    {
86
      if ((op->mask & insn) == op->opcode
87
          && (op->processors & target_processor))
88
        {
89
          const unsigned char * opindex_ptr;
90
          unsigned int          opnum;
91
          unsigned int          memop;
92
 
93
          match = 1;
94
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
95
/*fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );*/
96
 
97
          memop = op->memop;
98
          /* Now print the operands.
99
 
100
             MEMOP is the operand number at which a memory
101
             address specification starts, or zero if this
102
             instruction has no memory addresses.
103
 
104
             A memory address is always two arguments.
105
 
106
             This information allows us to determine when to
107
             insert commas into the output stream as well as
108
             when to insert disp[reg] expressions onto the
109
             output stream.  */
110
 
111
          for (opindex_ptr = op->operands, opnum = 1;
112
               *opindex_ptr != 0;
113
               opindex_ptr++, opnum++)
114
            {
115
              long      value;
116
              int       flag;
117
              int       status;
118
              bfd_byte  buffer[ 4 ];
119
 
120
              operand = &v850_operands[*opindex_ptr];
121
 
122
              if (operand->extract)
123
                value = (operand->extract) (insn, 0);
124
              else
125
                {
126
                  if (operand->bits == -1)
127
                    value = (insn & operand->shift);
128
                  else
129
                    value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
130
 
131
                  if (operand->flags & V850_OPERAND_SIGNED)
132
                    value = ((long)(value << (32 - operand->bits))
133
                             >> (32 - operand->bits));
134
                }
135
 
136
              /* The first operand is always output without any
137
                 special handling.
138
 
139
                 For the following arguments:
140
 
141
                   If memop && opnum == memop + 1, then we need '[' since
142
                   we're about to output the register used in a memory
143
                   reference.
144
 
145
                   If memop && opnum == memop + 2, then we need ']' since
146
                   we just finished the register in a memory reference.  We
147
                   also need a ',' before this operand.
148
 
149
                   Else we just need a comma.
150
 
151
                   We may need to output a trailing ']' if the last operand
152
                   in an instruction is the register for a memory address.
153
 
154
                   The exception (and there's always an exception) is the
155
                   "jmp" insn which needs square brackets around it's only
156
                   register argument.  */
157
 
158
                   if (memop && opnum == memop + 1) info->fprintf_func (info->stream, "[");
159
              else if (memop && opnum == memop + 2) info->fprintf_func (info->stream, "],");
160
              else if (memop == 1 && opnum == 1
161
                       && (operand->flags & V850_OPERAND_REG))
162
                                                    info->fprintf_func (info->stream, "[");
163
              else if (opnum > 1)                   info->fprintf_func (info->stream, ", ");
164
 
165
              /* extract the flags, ignorng ones which do not effect disassembly output. */
166
              flag = operand->flags;
167
              flag &= ~ V850_OPERAND_SIGNED;
168
              flag &= ~ V850_OPERAND_RELAX;
169
              flag &= - flag;
170
 
171
              switch (flag)
172
                {
173
                case V850_OPERAND_REG:  info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
174
                case V850_OPERAND_SRG:  info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
175
                case V850_OPERAND_CC:   info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
176
                case V850_OPERAND_EP:   info->fprintf_func (info->stream, "ep"); break;
177
                default:                info->fprintf_func (info->stream, "%d", value); break;
178
                case V850_OPERAND_DISP:
179
                  {
180
                    bfd_vma addr = value + memaddr;
181
 
182
                    /* On the v850 the top 8 bits of an address are used by an overlay manager.
183
                       Thus it may happen that when we are looking for a symbol to match
184
                       against an address with some of its top bits set, the search fails to
185
                       turn up an exact match.  In this case we try to find an exact match
186
                       against a symbol in the lower address space, and if we find one, we
187
                       use that address.   We only do this for JARL instructions however, as
188
                       we do not want to misinterpret branch instructions.  */
189
                    if (operand->bits == 22)
190
                      {
191
                        if ( ! info->symbol_at_address_func (addr, info)
192
                            && ((addr & 0xFF000000) != 0)
193
                            && info->symbol_at_address_func (addr & 0x00FFFFFF, info))
194
                          {
195
                            addr &= 0x00FFFFFF;
196
                          }
197
                      }
198
                    info->print_address_func (addr, info);
199
                    break;
200
                  }
201
 
202
                case V850E_PUSH_POP:
203
                  {
204
                    static int list12_regs[32]   = { 30,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
205
                    static int list18_h_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
206
                    static int list18_l_regs[32] = {  3,  2,  1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 14, 15, 13, 12,  7,  6,  5,  4, 11, 10,  9,  8 };
207
                    int *             regs;
208
                    int               i;
209
                    unsigned long int mask = 0;
210
                    int               pc   = false;
211
                    int               sr   = false;
212
 
213
 
214
                    switch (operand->shift)
215
                      {
216
                      case 0xffe00001: regs = list12_regs; break;
217
                      case 0xfff8000f: regs = list18_h_regs; break;
218
                      case 0xfff8001f: regs = list18_l_regs; value &= ~0x10; break;  /* Do not include magic bit */
219
                      default:
220
                        /* xgettext:c-format */
221
                        fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
222
                        abort();
223
                      }
224
 
225
                    for (i = 0; i < 32; i++)
226
                      {
227
                        if (value & (1 << i))
228
                          {
229
                            switch (regs[ i ])
230
                              {
231
                              default: mask |= (1 << regs[ i ]); break;
232
                                /* xgettext:c-format */
233
                              case 0:  fprintf (stderr, _("unknown pop reg: %d\n"), i ); abort();
234
                              case -1: pc = true; break;
235
                              case -2: sr = true; break;
236
                              }
237
                          }
238
                      }
239
 
240
                    info->fprintf_func (info->stream, "{");
241
 
242
                    if (mask || pc || sr)
243
                      {
244
                        if (mask)
245
                          {
246
                            unsigned int bit;
247
                            int          shown_one = false;
248
 
249
                            for (bit = 0; bit < 32; bit++)
250
                              if (mask & (1 << bit))
251
                                {
252
                                  unsigned long int first = bit;
253
                                  unsigned long int last;
254
 
255
                                  if (shown_one)
256
                                    info->fprintf_func (info->stream, ", ");
257
                                  else
258
                                    shown_one = true;
259
 
260
                                  info->fprintf_func (info->stream, v850_reg_names[first]);
261
 
262
                                  for (bit++; bit < 32; bit++)
263
                                    if ((mask & (1 << bit)) == 0)
264
                                      break;
265
 
266
                                  last = bit;
267
 
268
                                  if (last > first + 1)
269
                                    {
270
                                      info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
271
                                    }
272
                                }
273
                          }
274
 
275
                        if (pc)
276
                          info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
277
                        if (sr)
278
                          info->fprintf_func (info->stream, "%sSR", (mask || pc) ? ", " : "");
279
                      }
280
 
281
                    info->fprintf_func (info->stream, "}");
282
                  }
283
                break;
284
 
285
                case V850E_IMMEDIATE16:
286
                  status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
287
                  if (status == 0)
288
                    {
289
                      bytes_read += 2;
290
                      value = bfd_getl16 (buffer);
291
 
292
                      /* If this is a DISPOSE instruction with ff set to 0x10, then shift value up by 16.  */
293
                      if ((insn & 0x001fffc0) == 0x00130780)
294
                        value <<= 16;
295
 
296
                      info->fprintf_func (info->stream, "0x%x", value);
297
                    }
298
                  else
299
                    {
300
                      info->memory_error_func (status, memaddr + bytes_read, info);
301
                    }
302
                  break;
303
 
304
                case V850E_IMMEDIATE32:
305
                  status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
306
                  if (status == 0)
307
                    {
308
                      bytes_read += 4;
309
                      value = bfd_getl32 (buffer);
310
                      info->fprintf_func (info->stream, "0x%lx", value);
311
                    }
312
                  else
313
                    {
314
                      info->memory_error_func (status, memaddr + bytes_read, info);
315
                    }
316
                  break;
317
                }
318
 
319
              /* Handle jmp correctly.  */
320
              if (memop == 1 && opnum == 1
321
                  && ((operand->flags & V850_OPERAND_REG) != 0))
322
                (*info->fprintf_func) (info->stream, "]");
323
            }
324
 
325
          /* Close any square bracket we left open.  */
326
          if (memop && opnum == memop + 2)
327
            (*info->fprintf_func) (info->stream, "]");
328
 
329
          /* All done. */
330
          break;
331
        }
332
      op++;
333
    }
334
 
335
  if (!match)
336
    {
337
      if (short_op)
338
        info->fprintf_func (info->stream, ".short\t0x%04x", insn);
339
      else
340
        info->fprintf_func (info->stream, ".long\t0x%08x", insn);
341
    }
342
 
343
  return bytes_read;
344
}
345
 
346
int
347
print_insn_v850 (memaddr, info)
348
     bfd_vma memaddr;
349
     struct disassemble_info * info;
350
{
351
  int           status;
352
  bfd_byte      buffer[ 4 ];
353
  unsigned long insn = 0;
354
 
355
  /* First figure out how big the opcode is.  */
356
 
357
  status = info->read_memory_func (memaddr, buffer, 2, info);
358
  if (status == 0)
359
    {
360
      insn = bfd_getl16 (buffer);
361
 
362
      if (   (insn & 0x0600) == 0x0600
363
          && (insn & 0xffe0) != 0x0620)
364
        {
365
          /* If this is a 4 byte insn, read 4 bytes of stuff.  */
366
          status = info->read_memory_func (memaddr, buffer, 4, info);
367
 
368
          if (status == 0)
369
            insn = bfd_getl32 (buffer);
370
        }
371
    }
372
 
373
  if (status != 0)
374
    {
375
      info->memory_error_func (status, memaddr, info);
376
      return -1;
377
    }
378
 
379
  /* Make sure we tell our caller how many bytes we consumed.  */
380
  return disassemble (memaddr, info, insn);
381
}

powered by: WebSVN 2.1.0

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