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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [opcodes/] [m68k-dis.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Print Motorola 68k instructions.
2
   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3
   1998, 1999, 2000, 2001, 2002
4
   Free Software Foundation, Inc.
5
 
6
This file is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
20
#include "sysdep.h"
21
#include "dis-asm.h"
22
#include "floatformat.h"
23
#include "libiberty.h"
24
#include "opintl.h"
25
 
26
#include "opcode/m68k.h"
27
 
28
/* Local function prototypes */
29
 
30
static int
31
fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
32
 
33
static void
34
dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *));
35
 
36
static int
37
fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *));
38
 
39
static void
40
print_base PARAMS ((int, bfd_vma, disassemble_info *));
41
 
42
static unsigned char *
43
print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
44
 
45
static int
46
print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *,
47
                        bfd_vma, disassemble_info *));
48
 
49
const char * const fpcr_names[] = {
50
    "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
51
    "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
52
};
53
 
54
static char *const reg_names[] = {
55
    "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
56
    "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
57
    "%ps", "%pc"
58
};
59
 
60
/* Sign-extend an (unsigned char). */
61
#if __STDC__ == 1
62
#define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
63
#else
64
#define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
65
#endif
66
 
67
/* Get a 1 byte signed integer.  */
68
#define NEXTBYTE(p)  (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
69
 
70
/* Get a 2 byte signed integer.  */
71
#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
72
#define NEXTWORD(p)  \
73
  (p += 2, FETCH_DATA (info, p), \
74
   COERCE16 ((p[-2] << 8) + p[-1]))
75
 
76
/* Get a 4 byte signed integer.  */
77
#define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
78
#define NEXTLONG(p)  \
79
  (p += 4, FETCH_DATA (info, p), \
80
   (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
81
 
82
/* Get a 4 byte unsigned integer.  */
83
#define NEXTULONG(p)  \
84
  (p += 4, FETCH_DATA (info, p), \
85
   (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
86
 
87
/* Get a single precision float.  */
88
#define NEXTSINGLE(val, p) \
89
  (p += 4, FETCH_DATA (info, p), \
90
   floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
91
 
92
/* Get a double precision float.  */
93
#define NEXTDOUBLE(val, p) \
94
  (p += 8, FETCH_DATA (info, p), \
95
   floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
96
 
97
/* Get an extended precision float.  */
98
#define NEXTEXTEND(val, p) \
99
  (p += 12, FETCH_DATA (info, p), \
100
   floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
101
 
102
/* Need a function to convert from packed to double
103
   precision.   Actually, it's easier to print a
104
   packed number than a double anyway, so maybe
105
   there should be a special case to handle this... */
106
#define NEXTPACKED(p) \
107
  (p += 12, FETCH_DATA (info, p), 0.0)
108
 
109
/* Maximum length of an instruction.  */
110
#define MAXLEN 22
111
 
112
#include <setjmp.h>
113
 
114
struct private {
115
  /* Points to first byte not fetched.  */
116
  bfd_byte *max_fetched;
117
  bfd_byte the_buffer[MAXLEN];
118
  bfd_vma insn_start;
119
  jmp_buf bailout;
120
};
121
 
122
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
123
   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
124
   on error.  */
125
#define FETCH_DATA(info, addr) \
126
  ((addr) <= ((struct private *) (info->private_data))->max_fetched \
127
   ? 1 : fetch_data ((info), (addr)))
128
 
129
static int
130
fetch_data (info, addr)
131
     struct disassemble_info *info;
132
     bfd_byte *addr;
133
{
134
  int status;
135
  struct private *priv = (struct private *)info->private_data;
136
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
137
 
138
  status = (*info->read_memory_func) (start,
139
                                      priv->max_fetched,
140
                                      addr - priv->max_fetched,
141
                                      info);
142
  if (status != 0)
143
    {
144
      (*info->memory_error_func) (status, start, info);
145
      longjmp (priv->bailout, 1);
146
    }
147
  else
148
    priv->max_fetched = addr;
149
  return 1;
150
}
151
 
152
/* This function is used to print to the bit-bucket. */
153
static int
154
#ifdef __STDC__
155
dummy_printer (FILE *file ATTRIBUTE_UNUSED,
156
               const char *format ATTRIBUTE_UNUSED, ...)
157
#else
158
dummy_printer (file)
159
     FILE *file ATTRIBUTE_UNUSED;
160
#endif
161
{
162
  return 0;
163
}
164
 
165
static void
166
dummy_print_address (vma, info)
167
     bfd_vma vma ATTRIBUTE_UNUSED;
168
     struct disassemble_info *info ATTRIBUTE_UNUSED;
169
{
170
}
171
 
172
/* Print the m68k instruction at address MEMADDR in debugged memory,
173
   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
174
 
175
int
176
print_insn_m68k (memaddr, info)
177
     bfd_vma memaddr;
178
     disassemble_info *info;
179
{
180
  register int i;
181
  register unsigned char *p;
182
  unsigned char *save_p;
183
  register const char *d;
184
  register unsigned long bestmask;
185
  const struct m68k_opcode *best;
186
  unsigned int arch_mask;
187
  struct private priv;
188
  bfd_byte *buffer = priv.the_buffer;
189
  fprintf_ftype save_printer = info->fprintf_func;
190
  void (*save_print_address) PARAMS ((bfd_vma, struct disassemble_info *))
191
    = info->print_address_func;
192
  int major_opcode;
193
  static int numopcodes[16];
194
  static const struct m68k_opcode **opcodes[16];
195
 
196
  if (!opcodes[0])
197
    {
198
      /* Speed up the matching by sorting the opcode table on the upper
199
         four bits of the opcode.  */
200
      const struct m68k_opcode **opc_pointer[16];
201
 
202
      /* First count how many opcodes are in each of the sixteen buckets.  */
203
      for (i = 0; i < m68k_numopcodes; i++)
204
        numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
205
 
206
      /* Then create a sorted table of pointers that point into the
207
         unsorted table.  */
208
      opc_pointer[0] = ((const struct m68k_opcode **)
209
                        xmalloc (sizeof (struct m68k_opcode *)
210
                                 * m68k_numopcodes));
211
      opcodes[0] = opc_pointer[0];
212
      for (i = 1; i < 16; i++)
213
        {
214
          opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
215
          opcodes[i] = opc_pointer[i];
216
        }
217
 
218
      for (i = 0; i < m68k_numopcodes; i++)
219
        *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
220
 
221
    }
222
 
223
  info->private_data = (PTR) &priv;
224
  /* Tell objdump to use two bytes per chunk and six bytes per line for
225
     displaying raw data.  */
226
  info->bytes_per_chunk = 2;
227
  info->bytes_per_line = 6;
228
  info->display_endian = BFD_ENDIAN_BIG;
229
  priv.max_fetched = priv.the_buffer;
230
  priv.insn_start = memaddr;
231
  if (setjmp (priv.bailout) != 0)
232
    /* Error return.  */
233
    return -1;
234
 
235
  best = NULL;
236
  switch (info->mach)
237
    {
238
    default:
239
    case 0:
240
      arch_mask = (unsigned int) -1;
241
      break;
242
    case bfd_mach_m68000:
243
      arch_mask = m68000;
244
      break;
245
    case bfd_mach_m68008:
246
      arch_mask = m68008;
247
      break;
248
    case bfd_mach_m68010:
249
      arch_mask = m68010;
250
      break;
251
    case bfd_mach_m68020:
252
      arch_mask = m68020;
253
      break;
254
    case bfd_mach_m68030:
255
      arch_mask = m68030;
256
      break;
257
    case bfd_mach_m68040:
258
      arch_mask = m68040;
259
      break;
260
    case bfd_mach_m68060:
261
      arch_mask = m68060;
262
      break;
263
    case bfd_mach_mcf5200:
264
      arch_mask = mcf5200;
265
      break;
266
    case bfd_mach_mcf5206e:
267
      arch_mask = mcf5206e;
268
      break;
269
    case bfd_mach_mcf5307:
270
      arch_mask = mcf5307;
271
      break;
272
    case bfd_mach_mcf5407:
273
      arch_mask = mcf5407;
274
      break;
275
    }
276
 
277
  arch_mask |= m68881 | m68851;
278
 
279
  bestmask = 0;
280
  FETCH_DATA (info, buffer + 2);
281
  major_opcode = (buffer[0] >> 4) & 15;
282
  for (i = 0; i < numopcodes[major_opcode]; i++)
283
    {
284
      const struct m68k_opcode *opc = opcodes[major_opcode][i];
285
      unsigned long opcode = opc->opcode;
286
      unsigned long match = opc->match;
287
 
288
      if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
289
          && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
290
          /* Only fetch the next two bytes if we need to.  */
291
          && (((0xffff & match) == 0)
292
              ||
293
              (FETCH_DATA (info, buffer + 4)
294
               && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
295
               && ((0xff & buffer[3] & match) == (0xff & opcode)))
296
              )
297
          && (opc->arch & arch_mask) != 0)
298
        {
299
          /* Don't use for printout the variants of divul and divsl
300
             that have the same register number in two places.
301
             The more general variants will match instead.  */
302
          for (d = opc->args; *d; d += 2)
303
            if (d[1] == 'D')
304
              break;
305
 
306
          /* Don't use for printout the variants of most floating
307
             point coprocessor instructions which use the same
308
             register number in two places, as above. */
309
          if (*d == '\0')
310
            for (d = opc->args; *d; d += 2)
311
              if (d[1] == 't')
312
                break;
313
 
314
          /* Don't match fmovel with more than one register; wait for
315
             fmoveml.  */
316
          if (*d == '\0')
317
            {
318
              for (d = opc->args; *d; d += 2)
319
                {
320
                  if (d[0] == 's' && d[1] == '8')
321
                    {
322
                      int val;
323
 
324
                      val = fetch_arg (buffer, d[1], 3, info);
325
                      if ((val & (val - 1)) != 0)
326
                        break;
327
                    }
328
                }
329
            }
330
 
331
          if (*d == '\0' && match > bestmask)
332
            {
333
              best = opc;
334
              bestmask = match;
335
            }
336
        }
337
    }
338
 
339
  if (best == NULL)
340
    goto invalid;
341
 
342
  /* Point at first word of argument data,
343
     and at descriptor for first argument.  */
344
  p = buffer + 2;
345
 
346
  /* Figure out how long the fixed-size portion of the instruction is.
347
     The only place this is stored in the opcode table is
348
     in the arguments--look for arguments which specify fields in the 2nd
349
     or 3rd words of the instruction.  */
350
  for (d = best->args; *d; d += 2)
351
    {
352
      /* I don't think it is necessary to be checking d[0] here; I suspect
353
         all this could be moved to the case statement below.  */
354
      if (d[0] == '#')
355
        {
356
          if (d[1] == 'l' && p - buffer < 6)
357
            p = buffer + 6;
358
          else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
359
            p = buffer + 4;
360
        }
361
      if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
362
        p = buffer + 4;
363
      switch (d[1])
364
        {
365
        case '1':
366
        case '2':
367
        case '3':
368
        case '7':
369
        case '8':
370
        case '9':
371
        case 'i':
372
          if (p - buffer < 4)
373
            p = buffer + 4;
374
          break;
375
        case '4':
376
        case '5':
377
        case '6':
378
          if (p - buffer < 6)
379
            p = buffer + 6;
380
          break;
381
        default:
382
          break;
383
        }
384
    }
385
 
386
  /* pflusha is an exceptions.  It takes no arguments but is two words
387
     long.  Recognize it by looking at the lower 16 bits of the mask.  */
388
  if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
389
    p = buffer + 4;
390
 
391
  /* lpstop is another exception.  It takes a one word argument but is
392
     three words long.  */
393
  if (p - buffer < 6
394
      && (best->match & 0xffff) == 0xffff
395
      && best->args[0] == '#'
396
      && best->args[1] == 'w')
397
    {
398
      /* Copy the one word argument into the usual location for a one
399
         word argument, to simplify printing it.  We can get away with
400
         this because we know exactly what the second word is, and we
401
         aren't going to print anything based on it.  */
402
      p = buffer + 6;
403
      FETCH_DATA (info, p);
404
      buffer[2] = buffer[4];
405
      buffer[3] = buffer[5];
406
    }
407
 
408
  FETCH_DATA (info, p);
409
 
410
  d = best->args;
411
 
412
  /* We can the operands twice.  The first time we don't print anything,
413
     but look for errors. */
414
 
415
  save_p = p;
416
  info->print_address_func = dummy_print_address;
417
  info->fprintf_func = (fprintf_ftype) dummy_printer;
418
  for (; *d; d += 2)
419
    {
420
      int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
421
      if (eaten >= 0)
422
        p += eaten;
423
      else if (eaten == -1)
424
        goto invalid;
425
      else
426
        {
427
          (*info->fprintf_func) (info->stream,
428
                                 /* xgettext:c-format */
429
                                 _("<internal error in opcode table: %s %s>\n"),
430
                                 best->name,
431
                                 best->args);
432
          goto invalid;
433
        }
434
 
435
    }
436
  p = save_p;
437
  info->fprintf_func = save_printer;
438
  info->print_address_func = save_print_address;
439
 
440
  d = best->args;
441
 
442
  (*info->fprintf_func) (info->stream, "%s", best->name);
443
 
444
  if (*d)
445
    (*info->fprintf_func) (info->stream, " ");
446
 
447
  while (*d)
448
    {
449
      p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
450
      d += 2;
451
      if (*d && *(d - 2) != 'I' && *d != 'k')
452
        (*info->fprintf_func) (info->stream, ",");
453
    }
454
  return p - buffer;
455
 
456
 invalid:
457
  /* Handle undefined instructions.  */
458
  info->fprintf_func = save_printer;
459
  info->print_address_func = save_print_address;
460
  (*info->fprintf_func) (info->stream, "0%o",
461
                         (buffer[0] << 8) + buffer[1]);
462
  return 2;
463
}
464
 
465
/* Returns number of bytes "eaten" by the operand, or
466
   return -1 if an invalid operand was found, or -2 if
467
   an opcode tabe error was found. */
468
 
469
static int
470
print_insn_arg (d, buffer, p0, addr, info)
471
     const char *d;
472
     unsigned char *buffer;
473
     unsigned char *p0;
474
     bfd_vma addr;              /* PC for this arg to be relative to */
475
     disassemble_info *info;
476
{
477
  register int val = 0;
478
  register int place = d[1];
479
  register unsigned char *p = p0;
480
  int regno;
481
  register const char *regname;
482
  register unsigned char *p1;
483
  double flval;
484
  int flt_p;
485
  bfd_signed_vma disp;
486
  unsigned int uval;
487
 
488
  switch (*d)
489
    {
490
    case 'c':           /* cache identifier */
491
      {
492
        static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
493
        val = fetch_arg (buffer, place, 2, info);
494
        (*info->fprintf_func) (info->stream, cacheFieldName[val]);
495
        break;
496
      }
497
 
498
    case 'a':           /* address register indirect only. Cf. case '+'. */
499
      {
500
        (*info->fprintf_func)
501
          (info->stream,
502
           "%s@",
503
           reg_names[fetch_arg (buffer, place, 3, info) + 8]);
504
        break;
505
      }
506
 
507
    case '_':           /* 32-bit absolute address for move16. */
508
      {
509
        uval = NEXTULONG (p);
510
        (*info->print_address_func) (uval, info);
511
        break;
512
      }
513
 
514
    case 'C':
515
      (*info->fprintf_func) (info->stream, "%%ccr");
516
      break;
517
 
518
    case 'S':
519
      (*info->fprintf_func) (info->stream, "%%sr");
520
      break;
521
 
522
    case 'U':
523
      (*info->fprintf_func) (info->stream, "%%usp");
524
      break;
525
 
526
    case 'E':
527
      (*info->fprintf_func) (info->stream, "%%acc");
528
      break;
529
 
530
    case 'G':
531
      (*info->fprintf_func) (info->stream, "%%macsr");
532
      break;
533
 
534
    case 'H':
535
      (*info->fprintf_func) (info->stream, "%%mask");
536
      break;
537
 
538
    case 'J':
539
      {
540
        static const struct { char *name; int value; } names[]
541
          = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
542
             {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
543
             {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
544
             {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
545
             {"%msp", 0x803}, {"%isp", 0x804},
546
 
547
             /* Should we be calling this psr like we do in case 'Y'?  */
548
             {"%mmusr",0x805},
549
 
550
             {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
551
 
552
        val = fetch_arg (buffer, place, 12, info);
553
        for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
554
          if (names[regno].value == val)
555
            {
556
              (*info->fprintf_func) (info->stream, "%s", names[regno].name);
557
              break;
558
            }
559
        if (regno < 0)
560
          (*info->fprintf_func) (info->stream, "%d", val);
561
      }
562
      break;
563
 
564
    case 'Q':
565
      val = fetch_arg (buffer, place, 3, info);
566
      /* 0 means 8, except for the bkpt instruction... */
567
      if (val == 0 && d[1] != 's')
568
        val = 8;
569
      (*info->fprintf_func) (info->stream, "#%d", val);
570
      break;
571
 
572
    case 'M':
573
      if (place == 'h')
574
        {
575
          static char *const scalefactor_name[] = { "<<", ">>" };
576
          val = fetch_arg (buffer, place, 1, info);
577
          (*info->fprintf_func) (info->stream, scalefactor_name[val]);
578
        }
579
      else
580
        {
581
          val = fetch_arg (buffer, place, 8, info);
582
          if (val & 0x80)
583
            val = val - 0x100;
584
          (*info->fprintf_func) (info->stream, "#%d", val);
585
        }
586
      break;
587
 
588
    case 'T':
589
      val = fetch_arg (buffer, place, 4, info);
590
      (*info->fprintf_func) (info->stream, "#%d", val);
591
      break;
592
 
593
    case 'D':
594
      (*info->fprintf_func) (info->stream, "%s",
595
                             reg_names[fetch_arg (buffer, place, 3, info)]);
596
      break;
597
 
598
    case 'A':
599
      (*info->fprintf_func)
600
        (info->stream, "%s",
601
         reg_names[fetch_arg (buffer, place, 3, info) + 010]);
602
      break;
603
 
604
    case 'R':
605
      (*info->fprintf_func)
606
        (info->stream, "%s",
607
         reg_names[fetch_arg (buffer, place, 4, info)]);
608
      break;
609
 
610
    case 'r':
611
      regno = fetch_arg (buffer, place, 4, info);
612
      if (regno > 7)
613
        (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
614
      else
615
        (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
616
      break;
617
 
618
    case 'F':
619
      (*info->fprintf_func)
620
        (info->stream, "%%fp%d",
621
         fetch_arg (buffer, place, 3, info));
622
      break;
623
 
624
    case 'O':
625
      val = fetch_arg (buffer, place, 6, info);
626
      if (val & 0x20)
627
        (*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
628
      else
629
        (*info->fprintf_func) (info->stream, "%d", val);
630
      break;
631
 
632
    case '+':
633
      (*info->fprintf_func)
634
        (info->stream, "%s@+",
635
         reg_names[fetch_arg (buffer, place, 3, info) + 8]);
636
      break;
637
 
638
    case '-':
639
      (*info->fprintf_func)
640
        (info->stream, "%s@-",
641
         reg_names[fetch_arg (buffer, place, 3, info) + 8]);
642
      break;
643
 
644
    case 'k':
645
      if (place == 'k')
646
        (*info->fprintf_func)
647
          (info->stream, "{%s}",
648
           reg_names[fetch_arg (buffer, place, 3, info)]);
649
      else if (place == 'C')
650
        {
651
          val = fetch_arg (buffer, place, 7, info);
652
          if (val > 63)         /* This is a signed constant. */
653
            val -= 128;
654
          (*info->fprintf_func) (info->stream, "{#%d}", val);
655
        }
656
      else
657
        return -2;
658
      break;
659
 
660
    case '#':
661
    case '^':
662
      p1 = buffer + (*d == '#' ? 2 : 4);
663
      if (place == 's')
664
        val = fetch_arg (buffer, place, 4, info);
665
      else if (place == 'C')
666
        val = fetch_arg (buffer, place, 7, info);
667
      else if (place == '8')
668
        val = fetch_arg (buffer, place, 3, info);
669
      else if (place == '3')
670
        val = fetch_arg (buffer, place, 8, info);
671
      else if (place == 'b')
672
        val = NEXTBYTE (p1);
673
      else if (place == 'w' || place == 'W')
674
        val = NEXTWORD (p1);
675
      else if (place == 'l')
676
        val = NEXTLONG (p1);
677
      else
678
        return -2;
679
      (*info->fprintf_func) (info->stream, "#%d", val);
680
      break;
681
 
682
    case 'B':
683
      if (place == 'b')
684
        disp = NEXTBYTE (p);
685
      else if (place == 'B')
686
        disp = COERCE_SIGNED_CHAR (buffer[1]);
687
      else if (place == 'w' || place == 'W')
688
        disp = NEXTWORD (p);
689
      else if (place == 'l' || place == 'L' || place == 'C')
690
        disp = NEXTLONG (p);
691
      else if (place == 'g')
692
        {
693
          disp = NEXTBYTE (buffer);
694
          if (disp == 0)
695
            disp = NEXTWORD (p);
696
          else if (disp == -1)
697
            disp = NEXTLONG (p);
698
        }
699
      else if (place == 'c')
700
        {
701
          if (buffer[1] & 0x40)         /* If bit six is one, long offset */
702
            disp = NEXTLONG (p);
703
          else
704
            disp = NEXTWORD (p);
705
        }
706
      else
707
        return -2;
708
 
709
      (*info->print_address_func) (addr + disp, info);
710
      break;
711
 
712
    case 'd':
713
      val = NEXTWORD (p);
714
      (*info->fprintf_func)
715
        (info->stream, "%s@(%d)",
716
         reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
717
      break;
718
 
719
    case 's':
720
      (*info->fprintf_func) (info->stream, "%s",
721
                             fpcr_names[fetch_arg (buffer, place, 3, info)]);
722
      break;
723
 
724
    case 'I':
725
      /* Get coprocessor ID... */
726
      val = fetch_arg (buffer, 'd', 3, info);
727
 
728
      if (val != 1)                             /* Unusual coprocessor ID? */
729
        (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
730
      break;
731
 
732
    case '*':
733
    case '~':
734
    case '%':
735
    case ';':
736
    case '@':
737
    case '!':
738
    case '$':
739
    case '?':
740
    case '/':
741
    case '&':
742
    case '|':
743
    case '<':
744
    case '>':
745
    case 'm':
746
    case 'n':
747
    case 'o':
748
    case 'p':
749
    case 'q':
750
    case 'v':
751
 
752
      if (place == 'd')
753
        {
754
          val = fetch_arg (buffer, 'x', 6, info);
755
          val = ((val & 7) << 3) + ((val >> 3) & 7);
756
        }
757
      else
758
        val = fetch_arg (buffer, 's', 6, info);
759
 
760
      /* Get register number assuming address register.  */
761
      regno = (val & 7) + 8;
762
      regname = reg_names[regno];
763
      switch (val >> 3)
764
        {
765
        case 0:
766
          (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
767
          break;
768
 
769
        case 1:
770
          (*info->fprintf_func) (info->stream, "%s", regname);
771
          break;
772
 
773
        case 2:
774
          (*info->fprintf_func) (info->stream, "%s@", regname);
775
          break;
776
 
777
        case 3:
778
          (*info->fprintf_func) (info->stream, "%s@+", regname);
779
          break;
780
 
781
        case 4:
782
          (*info->fprintf_func) (info->stream, "%s@-", regname);
783
          break;
784
 
785
        case 5:
786
          val = NEXTWORD (p);
787
          (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
788
          break;
789
 
790
        case 6:
791
          p = print_indexed (regno, p, addr, info);
792
          break;
793
 
794
        case 7:
795
          switch (val & 7)
796
            {
797
            case 0:
798
              val = NEXTWORD (p);
799
              (*info->print_address_func) (val, info);
800
              break;
801
 
802
            case 1:
803
              uval = NEXTULONG (p);
804
              (*info->print_address_func) (uval, info);
805
              break;
806
 
807
            case 2:
808
              val = NEXTWORD (p);
809
              (*info->fprintf_func) (info->stream, "%%pc@(");
810
              (*info->print_address_func) (addr + val, info);
811
              (*info->fprintf_func) (info->stream, ")");
812
              break;
813
 
814
            case 3:
815
              p = print_indexed (-1, p, addr, info);
816
              break;
817
 
818
            case 4:
819
              flt_p = 1;        /* Assume it's a float... */
820
              switch (place)
821
              {
822
                case 'b':
823
                  val = NEXTBYTE (p);
824
                  flt_p = 0;
825
                  break;
826
 
827
                case 'w':
828
                  val = NEXTWORD (p);
829
                  flt_p = 0;
830
                  break;
831
 
832
                case 'l':
833
                  val = NEXTLONG (p);
834
                  flt_p = 0;
835
                  break;
836
 
837
                case 'f':
838
                  NEXTSINGLE (flval, p);
839
                  break;
840
 
841
                case 'F':
842
                  NEXTDOUBLE (flval, p);
843
                  break;
844
 
845
                case 'x':
846
                  NEXTEXTEND (flval, p);
847
                  break;
848
 
849
                case 'p':
850
                  flval = NEXTPACKED (p);
851
                  break;
852
 
853
                default:
854
                  return -1;
855
              }
856
              if (flt_p)        /* Print a float? */
857
                (*info->fprintf_func) (info->stream, "#%g", flval);
858
              else
859
                (*info->fprintf_func) (info->stream, "#%d", val);
860
              break;
861
 
862
            default:
863
              return -1;
864
            }
865
        }
866
      break;
867
 
868
    case 'L':
869
    case 'l':
870
        if (place == 'w')
871
          {
872
            char doneany;
873
            p1 = buffer + 2;
874
            val = NEXTWORD (p1);
875
            /* Move the pointer ahead if this point is farther ahead
876
               than the last.  */
877
            p = p1 > p ? p1 : p;
878
            if (val == 0)
879
              {
880
                (*info->fprintf_func) (info->stream, "#0");
881
                break;
882
              }
883
            if (*d == 'l')
884
              {
885
                register int newval = 0;
886
                for (regno = 0; regno < 16; ++regno)
887
                  if (val & (0x8000 >> regno))
888
                    newval |= 1 << regno;
889
                val = newval;
890
              }
891
            val &= 0xffff;
892
            doneany = 0;
893
            for (regno = 0; regno < 16; ++regno)
894
              if (val & (1 << regno))
895
                {
896
                  int first_regno;
897
                  if (doneany)
898
                    (*info->fprintf_func) (info->stream, "/");
899
                  doneany = 1;
900
                  (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
901
                  first_regno = regno;
902
                  while (val & (1 << (regno + 1)))
903
                    ++regno;
904
                  if (regno > first_regno)
905
                    (*info->fprintf_func) (info->stream, "-%s",
906
                                           reg_names[regno]);
907
                }
908
          }
909
        else if (place == '3')
910
          {
911
            /* `fmovem' insn.  */
912
            char doneany;
913
            val = fetch_arg (buffer, place, 8, info);
914
            if (val == 0)
915
              {
916
                (*info->fprintf_func) (info->stream, "#0");
917
                break;
918
              }
919
            if (*d == 'l')
920
              {
921
                register int newval = 0;
922
                for (regno = 0; regno < 8; ++regno)
923
                  if (val & (0x80 >> regno))
924
                    newval |= 1 << regno;
925
                val = newval;
926
              }
927
            val &= 0xff;
928
            doneany = 0;
929
            for (regno = 0; regno < 8; ++regno)
930
              if (val & (1 << regno))
931
                {
932
                  int first_regno;
933
                  if (doneany)
934
                    (*info->fprintf_func) (info->stream, "/");
935
                  doneany = 1;
936
                  (*info->fprintf_func) (info->stream, "%%fp%d", regno);
937
                  first_regno = regno;
938
                  while (val & (1 << (regno + 1)))
939
                    ++regno;
940
                  if (regno > first_regno)
941
                    (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
942
                }
943
          }
944
        else if (place == '8')
945
          {
946
            /* fmoveml for FP status registers */
947
            (*info->fprintf_func) (info->stream, "%s",
948
                                   fpcr_names[fetch_arg (buffer, place, 3,
949
                                                         info)]);
950
          }
951
        else
952
          return -2;
953
      break;
954
 
955
    case 'X':
956
      place = '8';
957
    case 'Y':
958
    case 'Z':
959
    case 'W':
960
    case '0':
961
    case '1':
962
    case '2':
963
    case '3':
964
      {
965
        int val = fetch_arg (buffer, place, 5, info);
966
        char *name = 0;
967
        switch (val)
968
          {
969
          case 2: name = "%tt0"; break;
970
          case 3: name = "%tt1"; break;
971
          case 0x10: name = "%tc"; break;
972
          case 0x11: name = "%drp"; break;
973
          case 0x12: name = "%srp"; break;
974
          case 0x13: name = "%crp"; break;
975
          case 0x14: name = "%cal"; break;
976
          case 0x15: name = "%val"; break;
977
          case 0x16: name = "%scc"; break;
978
          case 0x17: name = "%ac"; break;
979
          case 0x18: name = "%psr"; break;
980
          case 0x19: name = "%pcsr"; break;
981
          case 0x1c:
982
          case 0x1d:
983
            {
984
              int break_reg = ((buffer[3] >> 2) & 7);
985
              (*info->fprintf_func)
986
                (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
987
                 break_reg);
988
            }
989
            break;
990
          default:
991
            (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
992
          }
993
        if (name)
994
          (*info->fprintf_func) (info->stream, "%s", name);
995
      }
996
      break;
997
 
998
    case 'f':
999
      {
1000
        int fc = fetch_arg (buffer, place, 5, info);
1001
        if (fc == 1)
1002
          (*info->fprintf_func) (info->stream, "%%dfc");
1003
        else if (fc == 0)
1004
          (*info->fprintf_func) (info->stream, "%%sfc");
1005
        else
1006
          /* xgettext:c-format */
1007
          (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
1008
      }
1009
      break;
1010
 
1011
    case 'V':
1012
      (*info->fprintf_func) (info->stream, "%%val");
1013
      break;
1014
 
1015
    case 't':
1016
      {
1017
        int level = fetch_arg (buffer, place, 3, info);
1018
        (*info->fprintf_func) (info->stream, "%d", level);
1019
      }
1020
      break;
1021
 
1022
    case 'u':
1023
      {
1024
        short is_upper = 0;
1025
        int reg = fetch_arg (buffer, place, 5, info);
1026
 
1027
        if (reg & 0x10)
1028
          {
1029
            is_upper = 1;
1030
            reg &= 0xf;
1031
          }
1032
        (*info->fprintf_func) (info->stream, "%s%s",
1033
                               reg_names[reg],
1034
                               is_upper ? "u" : "l");
1035
      }
1036
      break;
1037
 
1038
    default:
1039
      return -2;
1040
    }
1041
 
1042
  return p - p0;
1043
}
1044
 
1045
/* Fetch BITS bits from a position in the instruction specified by CODE.
1046
   CODE is a "place to put an argument", or 'x' for a destination
1047
   that is a general address (mode and register).
1048
   BUFFER contains the instruction.  */
1049
 
1050
static int
1051
fetch_arg (buffer, code, bits, info)
1052
     unsigned char *buffer;
1053
     int code;
1054
     int bits;
1055
     disassemble_info *info;
1056
{
1057
  register int val = 0;
1058
  switch (code)
1059
    {
1060
    case 's':
1061
      val = buffer[1];
1062
      break;
1063
 
1064
    case 'd':                   /* Destination, for register or quick.  */
1065
      val = (buffer[0] << 8) + buffer[1];
1066
      val >>= 9;
1067
      break;
1068
 
1069
    case 'x':                   /* Destination, for general arg */
1070
      val = (buffer[0] << 8) + buffer[1];
1071
      val >>= 6;
1072
      break;
1073
 
1074
    case 'k':
1075
      FETCH_DATA (info, buffer + 3);
1076
      val = (buffer[3] >> 4);
1077
      break;
1078
 
1079
    case 'C':
1080
      FETCH_DATA (info, buffer + 3);
1081
      val = buffer[3];
1082
      break;
1083
 
1084
    case '1':
1085
      FETCH_DATA (info, buffer + 3);
1086
      val = (buffer[2] << 8) + buffer[3];
1087
      val >>= 12;
1088
      break;
1089
 
1090
    case '2':
1091
      FETCH_DATA (info, buffer + 3);
1092
      val = (buffer[2] << 8) + buffer[3];
1093
      val >>= 6;
1094
      break;
1095
 
1096
    case '3':
1097
    case 'j':
1098
      FETCH_DATA (info, buffer + 3);
1099
      val = (buffer[2] << 8) + buffer[3];
1100
      break;
1101
 
1102
    case '4':
1103
      FETCH_DATA (info, buffer + 5);
1104
      val = (buffer[4] << 8) + buffer[5];
1105
      val >>= 12;
1106
      break;
1107
 
1108
    case '5':
1109
      FETCH_DATA (info, buffer + 5);
1110
      val = (buffer[4] << 8) + buffer[5];
1111
      val >>= 6;
1112
      break;
1113
 
1114
    case '6':
1115
      FETCH_DATA (info, buffer + 5);
1116
      val = (buffer[4] << 8) + buffer[5];
1117
      break;
1118
 
1119
    case '7':
1120
      FETCH_DATA (info, buffer + 3);
1121
      val = (buffer[2] << 8) + buffer[3];
1122
      val >>= 7;
1123
      break;
1124
 
1125
    case '8':
1126
      FETCH_DATA (info, buffer + 3);
1127
      val = (buffer[2] << 8) + buffer[3];
1128
      val >>= 10;
1129
      break;
1130
 
1131
    case '9':
1132
      FETCH_DATA (info, buffer + 3);
1133
      val = (buffer[2] << 8) + buffer[3];
1134
      val >>= 5;
1135
      break;
1136
 
1137
    case 'e':
1138
      val = (buffer[1] >> 6);
1139
      break;
1140
 
1141
    case 'm':
1142
      val = (buffer[1] & 0x40 ? 0x8 : 0)
1143
        | ((buffer[0] >> 1) & 0x7)
1144
        | (buffer[3] & 0x80 ? 0x10 : 0);
1145
      break;
1146
 
1147
    case 'n':
1148
      val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
1149
      break;
1150
 
1151
    case 'o':
1152
      val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
1153
      break;
1154
 
1155
    case 'M':
1156
      val = buffer[1] | (buffer[3] & 0x40 ? 0x10 : 0);
1157
      break;
1158
 
1159
    case 'N':
1160
      val = buffer[3] | (buffer[3] & 0x40 ? 0x10 : 0);
1161
      break;
1162
 
1163
    case 'h':
1164
      val = buffer[2] >> 2;
1165
      break;
1166
 
1167
    default:
1168
      abort ();
1169
    }
1170
 
1171
  switch (bits)
1172
    {
1173
    case 1:
1174
      return val & 1;
1175
    case 2:
1176
      return val & 3;
1177
    case 3:
1178
      return val & 7;
1179
    case 4:
1180
      return val & 017;
1181
    case 5:
1182
      return val & 037;
1183
    case 6:
1184
      return val & 077;
1185
    case 7:
1186
      return val & 0177;
1187
    case 8:
1188
      return val & 0377;
1189
    case 12:
1190
      return val & 07777;
1191
    default:
1192
      abort ();
1193
    }
1194
}
1195
 
1196
/* Print an indexed argument.  The base register is BASEREG (-1 for pc).
1197
   P points to extension word, in buffer.
1198
   ADDR is the nominal core address of that extension word.  */
1199
 
1200
static unsigned char *
1201
print_indexed (basereg, p, addr, info)
1202
     int basereg;
1203
     unsigned char *p;
1204
     bfd_vma addr;
1205
     disassemble_info *info;
1206
{
1207
  register int word;
1208
  static char *const scales[] = { "", ":2", ":4", ":8" };
1209
  bfd_vma base_disp;
1210
  bfd_vma outer_disp;
1211
  char buf[40];
1212
  char vmabuf[50];
1213
 
1214
  word = NEXTWORD (p);
1215
 
1216
  /* Generate the text for the index register.
1217
     Where this will be output is not yet determined.  */
1218
  sprintf (buf, "%s:%c%s",
1219
           reg_names[(word >> 12) & 0xf],
1220
           (word & 0x800) ? 'l' : 'w',
1221
           scales[(word >> 9) & 3]);
1222
 
1223
  /* Handle the 68000 style of indexing.  */
1224
 
1225
  if ((word & 0x100) == 0)
1226
    {
1227
      base_disp = word & 0xff;
1228
      if ((base_disp & 0x80) != 0)
1229
        base_disp -= 0x100;
1230
      if (basereg == -1)
1231
        base_disp += addr;
1232
      print_base (basereg, base_disp, info);
1233
      (*info->fprintf_func) (info->stream, ",%s)", buf);
1234
      return p;
1235
    }
1236
 
1237
  /* Handle the generalized kind.  */
1238
  /* First, compute the displacement to add to the base register.  */
1239
 
1240
  if (word & 0200)
1241
    {
1242
      if (basereg == -1)
1243
        basereg = -3;
1244
      else
1245
        basereg = -2;
1246
    }
1247
  if (word & 0100)
1248
    buf[0] = '\0';
1249
  base_disp = 0;
1250
  switch ((word >> 4) & 3)
1251
    {
1252
    case 2:
1253
      base_disp = NEXTWORD (p);
1254
      break;
1255
    case 3:
1256
      base_disp = NEXTLONG (p);
1257
    }
1258
  if (basereg == -1)
1259
    base_disp += addr;
1260
 
1261
  /* Handle single-level case (not indirect) */
1262
 
1263
  if ((word & 7) == 0)
1264
    {
1265
      print_base (basereg, base_disp, info);
1266
      if (buf[0] != '\0')
1267
        (*info->fprintf_func) (info->stream, ",%s", buf);
1268
      (*info->fprintf_func) (info->stream, ")");
1269
      return p;
1270
    }
1271
 
1272
  /* Two level.  Compute displacement to add after indirection.  */
1273
 
1274
  outer_disp = 0;
1275
  switch (word & 3)
1276
    {
1277
    case 2:
1278
      outer_disp = NEXTWORD (p);
1279
      break;
1280
    case 3:
1281
      outer_disp = NEXTLONG (p);
1282
    }
1283
 
1284
  print_base (basereg, base_disp, info);
1285
  if ((word & 4) == 0 && buf[0] != '\0')
1286
    {
1287
      (*info->fprintf_func) (info->stream, ",%s", buf);
1288
      buf[0] = '\0';
1289
    }
1290
  sprintf_vma (vmabuf, outer_disp);
1291
  (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
1292
  if (buf[0] != '\0')
1293
    (*info->fprintf_func) (info->stream, ",%s", buf);
1294
  (*info->fprintf_func) (info->stream, ")");
1295
 
1296
  return p;
1297
}
1298
 
1299
/* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1300
   REGNO = -1 for pc, -2 for none (suppressed).  */
1301
 
1302
static void
1303
print_base (regno, disp, info)
1304
     int regno;
1305
     bfd_vma disp;
1306
     disassemble_info *info;
1307
{
1308
  if (regno == -1)
1309
    {
1310
      (*info->fprintf_func) (info->stream, "%%pc@(");
1311
      (*info->print_address_func) (disp, info);
1312
    }
1313
  else
1314
    {
1315
      char buf[50];
1316
 
1317
      if (regno == -2)
1318
        (*info->fprintf_func) (info->stream, "@(");
1319
      else if (regno == -3)
1320
        (*info->fprintf_func) (info->stream, "%%zpc@(");
1321
      else
1322
        (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
1323
 
1324
      sprintf_vma (buf, disp);
1325
      (*info->fprintf_func) (info->stream, "%s", buf);
1326
    }
1327
}

powered by: WebSVN 2.1.0

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