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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [a29k-dis.c] - Blame information for rev 1776

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

Line No. Rev Author Line
1 578 markom
/* Instruction printing code for the AMD 29000
2
   Copyright 1990, 1993, 1994, 1995, 1998, 2000
3
   Free Software Foundation, Inc.
4
   Contributed by Cygnus Support.  Written by Jim Kingdon.
5
 
6
This file is part of GDB.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
#include "sysdep.h"
23
#include "dis-asm.h"
24
#include "opcode/a29k.h"
25
 
26
/* Print a symbolic representation of a general-purpose
27
   register number NUM on STREAM.
28
   NUM is a number as found in the instruction, not as found in
29
   debugging symbols; it must be in the range 0-255.  */
30
static void
31
print_general (num, info)
32
     int num;
33
     struct disassemble_info *info;
34
{
35
  if (num < 128)
36
    (*info->fprintf_func) (info->stream, "gr%d", num);
37
  else
38
    (*info->fprintf_func) (info->stream, "lr%d", num - 128);
39
}
40
 
41
/* Like print_general but a special-purpose register.
42
 
43
   The mnemonics used by the AMD assembler are not quite the same
44
   as the ones in the User's Manual.  We use the ones that the
45
   assembler uses.  */
46
static void
47
print_special (num, info)
48
     unsigned int num;
49
     struct disassemble_info *info;
50
{
51
  /* Register names of registers 0-SPEC0_NUM-1.  */
52
  static char *spec0_names[] = {
53
    "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
54
    "pc0", "pc1", "pc2", "mmu", "lru", "rsn", "rma0", "rmc0", "rma1", "rmc1",
55
    "spc0", "spc1", "spc2", "iba0", "ibc0", "iba1", "ibc1", "dba", "dbc",
56
    "cir", "cdr"
57
    };
58
#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
59
 
60
  /* Register names of registers 128-128+SPEC128_NUM-1.  */
61
  static char *spec128_names[] = {
62
    "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
63
    };
64
#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
65
 
66
  /* Register names of registers 160-160+SPEC160_NUM-1.  */
67
  static char *spec160_names[] = {
68
    "fpe", "inte", "fps", "sr163", "exop"
69
    };
70
#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
71
 
72
  if (num < SPEC0_NUM)
73
    (*info->fprintf_func) (info->stream, spec0_names[num]);
74
  else if (num >= 128 && num < 128 + SPEC128_NUM)
75
    (*info->fprintf_func) (info->stream, spec128_names[num-128]);
76
  else if (num >= 160 && num < 160 + SPEC160_NUM)
77
    (*info->fprintf_func) (info->stream, spec160_names[num-160]);
78
  else
79
    (*info->fprintf_func) (info->stream, "sr%d", num);
80
}
81
 
82
/* Is an instruction with OPCODE a delayed branch?  */
83
static int
84
is_delayed_branch (opcode)
85
     int opcode;
86
{
87
  return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1
88
          || opcode == 0xa4 || opcode == 0xa5
89
          || opcode == 0xb4 || opcode == 0xb5
90
          || opcode == 0xc4 || opcode == 0xc0
91
          || opcode == 0xac || opcode == 0xad
92
          || opcode == 0xcc);
93
}
94
 
95
/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}.  */
96
static void
97
find_bytes_big (insn, insn0, insn8, insn16, insn24)
98
     char *insn;
99
     unsigned char *insn0;
100
     unsigned char *insn8;
101
     unsigned char *insn16;
102
     unsigned char *insn24;
103
{
104
  *insn24 = insn[0];
105
  *insn16 = insn[1];
106
  *insn8  = insn[2];
107
  *insn0  = insn[3];
108
}
109
 
110
static void
111
find_bytes_little (insn, insn0, insn8, insn16, insn24)
112
     char *insn;
113
     unsigned char *insn0;
114
     unsigned char *insn8;
115
     unsigned char *insn16;
116
     unsigned char *insn24;
117
{
118
  *insn24 = insn[3];
119
  *insn16 = insn[2];
120
  *insn8 = insn[1];
121
  *insn0 = insn[0];
122
}
123
 
124
typedef void (*find_byte_func_type)
125
     PARAMS ((char *, unsigned char *, unsigned char *,
126
              unsigned char *, unsigned char *));
127
 
128
/* Print one instruction from MEMADDR on INFO->STREAM.
129
   Return the size of the instruction (always 4 on a29k).  */
130
 
131
static int
132
print_insn (memaddr, info)
133
     bfd_vma memaddr;
134
     struct disassemble_info *info;
135
{
136
  /* The raw instruction.  */
137
  char insn[4];
138
 
139
  /* The four bytes of the instruction.  */
140
  unsigned char insn24, insn16, insn8, insn0;
141
 
142
  find_byte_func_type find_byte_func = (find_byte_func_type)info->private_data;
143
 
144
  struct a29k_opcode CONST * opcode;
145
 
146
  {
147
    int status =
148
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn[0], 4, info);
149
    if (status != 0)
150
      {
151
        (*info->memory_error_func) (status, memaddr, info);
152
        return -1;
153
      }
154
  }
155
 
156
  (*find_byte_func) (insn, &insn0, &insn8, &insn16, &insn24);
157
 
158
  printf ("%02x%02x%02x%02x ", insn24, insn16, insn8, insn0);
159
 
160
  /* Handle the nop (aseq 0x40,gr1,gr1) specially */
161
  if ((insn24==0x70) && (insn16==0x40) && (insn8==0x01) && (insn0==0x01)) {
162
    (*info->fprintf_func) (info->stream,"nop");
163
    return 4;
164
  }
165
 
166
  /* The opcode is always in insn24.  */
167
  for (opcode = &a29k_opcodes[0];
168
       opcode < &a29k_opcodes[num_opcodes];
169
       ++opcode)
170
    {
171
      if (((unsigned long) insn24 << 24) == opcode->opcode)
172
        {
173
          char *s;
174
 
175
          (*info->fprintf_func) (info->stream, "%s ", opcode->name);
176
          for (s = opcode->args; *s != '\0'; ++s)
177
            {
178
              switch (*s)
179
                {
180
                case 'a':
181
                  print_general (insn8, info);
182
                  break;
183
 
184
                case 'b':
185
                  print_general (insn0, info);
186
                  break;
187
 
188
                case 'c':
189
                  print_general (insn16, info);
190
                  break;
191
 
192
                case 'i':
193
                  (*info->fprintf_func) (info->stream, "%d", insn0);
194
                  break;
195
 
196
                case 'x':
197
                  (*info->fprintf_func) (info->stream, "0x%x", (insn16 << 8) + insn0);
198
                  break;
199
 
200
                case 'h':
201
                  /* This used to be %x for binutils.  */
202
                  (*info->fprintf_func) (info->stream, "0x%x",
203
                                    (insn16 << 24) + (insn0 << 16));
204
                  break;
205
 
206
                case 'X':
207
                  (*info->fprintf_func) (info->stream, "%d",
208
                                    ((insn16 << 8) + insn0) | 0xffff0000);
209
                  break;
210
 
211
                case 'P':
212
                  /* This output looks just like absolute addressing, but
213
                     maybe that's OK (it's what the GDB m68k and EBMON
214
                     a29k disassemblers do).  */
215
                  /* All the shifting is to sign-extend it.  p*/
216
                  (*info->print_address_func)
217
                    (memaddr +
218
                     (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
219
                     info);
220
                  break;
221
 
222
                case 'A':
223
                  (*info->print_address_func)
224
                    ((insn16 << 10) + (insn0 << 2), info);
225
                  break;
226
 
227
                case 'e':
228
                  (*info->fprintf_func) (info->stream, "%d", insn16 >> 7);
229
                  break;
230
 
231
                case 'n':
232
                  (*info->fprintf_func) (info->stream, "0x%x", insn16 & 0x7f);
233
                  break;
234
 
235
                case 'v':
236
                  (*info->fprintf_func) (info->stream, "0x%x", insn16);
237
                  break;
238
 
239
                case 's':
240
                  print_special (insn8, info);
241
                  break;
242
 
243
                case 'u':
244
                  (*info->fprintf_func) (info->stream, "%d", insn0 >> 7);
245
                  break;
246
 
247
                case 'r':
248
                  (*info->fprintf_func) (info->stream, "%d", (insn0 >> 4) & 7);
249
                  break;
250
 
251
                case 'I':
252
                  if ((insn16 & 3) != 0)
253
                    (*info->fprintf_func) (info->stream, "%d", insn16 & 3);
254
                  break;
255
 
256
                case 'd':
257
                  (*info->fprintf_func) (info->stream, "%d", (insn0 >> 2) & 3);
258
                  break;
259
 
260
                case 'f':
261
                  (*info->fprintf_func) (info->stream, "%d", insn0 & 3);
262
                  break;
263
 
264
                case 'F':
265
                  (*info->fprintf_func) (info->stream, "%d", (insn16 >> 2) & 15);
266
                  break;
267
 
268
                case 'C':
269
                  (*info->fprintf_func) (info->stream, "%d", insn16 & 3);
270
                  break;
271
 
272
                default:
273
                  (*info->fprintf_func) (info->stream, "%c", *s);
274
                }
275
            }
276
 
277
          /* Now we look for a const,consth pair of instructions,
278
             in which case we try to print the symbolic address.  */
279
          if (insn24 == 2)  /* consth */
280
            {
281
              int errcode;
282
              char prev_insn[4];
283
              unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
284
 
285
              errcode = (*info->read_memory_func) (memaddr - 4,
286
                                                   (bfd_byte *) &prev_insn[0],
287
                                                   4,
288
                                                   info);
289
              if (errcode == 0)
290
                {
291
                  /* If it is a delayed branch, we need to look at the
292
                     instruction before the delayed brach to handle
293
                     things like
294
 
295
                     const _foo
296
                     call _printf
297
                     consth _foo
298
                     */
299
                  (*find_byte_func) (prev_insn, &prev_insn0, &prev_insn8,
300
                                     &prev_insn16, &prev_insn24);
301
                  if (is_delayed_branch (prev_insn24))
302
                    {
303
                      errcode = (*info->read_memory_func)
304
                        (memaddr - 8, (bfd_byte *) &prev_insn[0], 4, info);
305
                      (*find_byte_func) (prev_insn, &prev_insn0, &prev_insn8,
306
                                         &prev_insn16, &prev_insn24);
307
                    }
308
                }
309
 
310
              /* If there was a problem reading memory, then assume
311
                 the previous instruction was not const.  */
312
              if (errcode == 0)
313
                {
314
                  /* Is it const to the same register?  */
315
                  if (prev_insn24 == 3
316
                      && prev_insn8 == insn8)
317
                    {
318
                      (*info->fprintf_func) (info->stream, "\t; ");
319
                      (*info->print_address_func)
320
                        (((insn16 << 24) + (insn0 << 16)
321
                          + (prev_insn16 << 8) + (prev_insn0)),
322
                         info);
323
                    }
324
                }
325
            }
326
 
327
          return 4;
328
        }
329
    }
330
  /* This used to be %8x for binutils.  */
331
  (*info->fprintf_func)
332
    (info->stream, ".word 0x%08x",
333
     (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
334
  return 4;
335
}
336
 
337
/* Disassemble an big-endian a29k instruction.  */
338
int
339
print_insn_big_a29k (memaddr, info)
340
     bfd_vma memaddr;
341
     struct disassemble_info *info;
342
{
343
  info->private_data = (PTR) find_bytes_big;
344
  return print_insn (memaddr, info);
345
}
346
 
347
/* Disassemble a little-endian a29k instruction.  */
348
int
349
print_insn_little_a29k (memaddr, info)
350
     bfd_vma memaddr;
351
     struct disassemble_info *info;
352
{
353
  info->private_data = (PTR) find_bytes_little;
354
  return print_insn (memaddr, info);
355
}

powered by: WebSVN 2.1.0

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