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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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