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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [opcodes/] [m68k-dis.c] - Blame information for rev 1778

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

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

powered by: WebSVN 2.1.0

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