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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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