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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [opcodes/] [m68k-dis.c] - Blame information for rev 1765

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

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

powered by: WebSVN 2.1.0

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