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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [opcodes/] [a29k-dis.c] - Blame information for rev 107

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

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

powered by: WebSVN 2.1.0

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