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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [opcodes/] [m68k-dis.c] - Blame information for rev 826

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

Line No. Rev Author Line
1 24 jeremybenn
/* Print Motorola 68k instructions.
2
   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3 225 jeremybenn
   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 24 jeremybenn
   Free Software Foundation, Inc.
5
 
6
   This file is part of the GNU opcodes library.
7
 
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
#include "dis-asm.h"
25
#include "floatformat.h"
26
#include "libiberty.h"
27
#include "opintl.h"
28
 
29
#include "opcode/m68k.h"
30
 
31
/* Local function prototypes.  */
32
 
33
const char * const fpcr_names[] =
34
{
35
  "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
36
  "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
37
};
38
 
39
static char *const reg_names[] =
40
{
41
  "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
42
  "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
43
  "%ps", "%pc"
44
};
45
 
46
/* Name of register halves for MAC/EMAC.
47
   Seperate from reg_names since 'spu', 'fpl' look weird.  */
48
static char *const reg_half_names[] =
49
{
50
  "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
51
  "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
52
  "%ps", "%pc"
53
};
54
 
55
/* Sign-extend an (unsigned char).  */
56
#if __STDC__ == 1
57
#define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
58
#else
59
#define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
60
#endif
61
 
62
/* Get a 1 byte signed integer.  */
63 225 jeremybenn
#define NEXTBYTE(p, val)                        \
64
  do                                            \
65
    {                                           \
66
      p += 2;                                   \
67
      if (!FETCH_DATA (info, p))                \
68
        return -3;                              \
69
      val = COERCE_SIGNED_CHAR (p[-1]);         \
70
    }                                           \
71
  while (0)
72 24 jeremybenn
 
73
/* Get a 2 byte signed integer.  */
74
#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
75
 
76 225 jeremybenn
#define NEXTWORD(p, val, ret_val)               \
77
  do                                            \
78
    {                                           \
79
      p += 2;                                   \
80
      if (!FETCH_DATA (info, p))                \
81
        return ret_val;                         \
82
      val = COERCE16 ((p[-2] << 8) + p[-1]);    \
83
    }                                           \
84
  while (0)
85
 
86 24 jeremybenn
/* Get a 4 byte signed integer.  */
87
#define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
88
 
89 225 jeremybenn
#define NEXTLONG(p, val, ret_val)                                       \
90
  do                                                                    \
91
    {                                                                   \
92
      p += 4;                                                           \
93
      if (!FETCH_DATA (info, p))                                        \
94
        return ret_val;                                                 \
95
      val = COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]); \
96
    }                                                                   \
97
  while (0)
98
 
99 24 jeremybenn
/* Get a 4 byte unsigned integer.  */
100 225 jeremybenn
#define NEXTULONG(p, val)                                               \
101
  do                                                                    \
102
    {                                                                   \
103
      p += 4;                                                           \
104
      if (!FETCH_DATA (info, p))                                        \
105
        return -3;                                                      \
106
      val = (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]); \
107
    }                                                                   \
108
  while (0)
109 24 jeremybenn
 
110
/* Get a single precision float.  */
111 225 jeremybenn
#define NEXTSINGLE(val, p)                                      \
112
  do                                                            \
113
    {                                                           \
114
      p += 4;                                                   \
115
      if (!FETCH_DATA (info, p))                                \
116
        return -3;                                              \
117
      floatformat_to_double (& floatformat_ieee_single_big,     \
118
                             (char *) p - 4, & val);            \
119
    }                                                           \
120
  while (0)
121 24 jeremybenn
 
122
/* Get a double precision float.  */
123 225 jeremybenn
#define NEXTDOUBLE(val, p)                                      \
124
  do                                                            \
125
    {                                                           \
126
      p += 8;                                                   \
127
      if (!FETCH_DATA (info, p))                                \
128
        return -3;                                              \
129
      floatformat_to_double (& floatformat_ieee_double_big,     \
130
                             (char *) p - 8, & val);            \
131
    }                                                           \
132
  while (0)
133 24 jeremybenn
 
134
/* Get an extended precision float.  */
135 225 jeremybenn
#define NEXTEXTEND(val, p)                              \
136
  do                                                    \
137
    {                                                   \
138
      p += 12;                                          \
139
      if (!FETCH_DATA (info, p))                        \
140
        return -3;                                      \
141
      floatformat_to_double (& floatformat_m68881_ext,  \
142
                             (char *) p - 12, & val);   \
143
    }                                                   \
144
  while (0)
145 24 jeremybenn
 
146
/* Need a function to convert from packed to double
147
   precision.   Actually, it's easier to print a
148
   packed number than a double anyway, so maybe
149
   there should be a special case to handle this... */
150 225 jeremybenn
#define NEXTPACKED(p, val)                      \
151
  do                                            \
152
    {                                           \
153
      p += 12;                                  \
154
      if (!FETCH_DATA (info, p))                \
155
        return -3;                              \
156
      val = 0.0;                                \
157
    }                                           \
158
  while (0)
159
 
160 24 jeremybenn
 
161
/* Maximum length of an instruction.  */
162
#define MAXLEN 22
163
 
164
#include <setjmp.h>
165
 
166
struct private
167
{
168
  /* Points to first byte not fetched.  */
169
  bfd_byte *max_fetched;
170
  bfd_byte the_buffer[MAXLEN];
171
  bfd_vma insn_start;
172
};
173
 
174
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
175 225 jeremybenn
   to ADDR (exclusive) are valid.  Returns 1 for success, 0 on error.  */
176 24 jeremybenn
#define FETCH_DATA(info, addr) \
177
  ((addr) <= ((struct private *) (info->private_data))->max_fetched \
178
   ? 1 : fetch_data ((info), (addr)))
179
 
180
static int
181
fetch_data (struct disassemble_info *info, bfd_byte *addr)
182
{
183
  int status;
184
  struct private *priv = (struct private *)info->private_data;
185
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
186
 
187
  status = (*info->read_memory_func) (start,
188
                                      priv->max_fetched,
189
                                      addr - priv->max_fetched,
190
                                      info);
191
  if (status != 0)
192
    {
193
      (*info->memory_error_func) (status, start, info);
194 225 jeremybenn
      return 0;
195 24 jeremybenn
    }
196
  else
197
    priv->max_fetched = addr;
198
  return 1;
199
}
200
 
201
/* This function is used to print to the bit-bucket.  */
202
static int
203
dummy_printer (FILE *file ATTRIBUTE_UNUSED,
204
               const char *format ATTRIBUTE_UNUSED,
205
               ...)
206
{
207
  return 0;
208
}
209
 
210
static void
211
dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED,
212
                     struct disassemble_info *info ATTRIBUTE_UNUSED)
213
{
214
}
215
 
216
/* Fetch BITS bits from a position in the instruction specified by CODE.
217
   CODE is a "place to put an argument", or 'x' for a destination
218
   that is a general address (mode and register).
219 225 jeremybenn
   BUFFER contains the instruction.
220
   Returns -1 on failure.  */
221 24 jeremybenn
 
222
static int
223
fetch_arg (unsigned char *buffer,
224
           int code,
225
           int bits,
226
           disassemble_info *info)
227
{
228
  int val = 0;
229
 
230
  switch (code)
231
    {
232
    case '/': /* MAC/EMAC mask bit.  */
233
      val = buffer[3] >> 5;
234
      break;
235
 
236
    case 'G': /* EMAC ACC load.  */
237
      val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
238
      break;
239
 
240
    case 'H': /* EMAC ACC !load.  */
241
      val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
242
      break;
243
 
244
    case ']': /* EMAC ACCEXT bit.  */
245
      val = buffer[0] >> 2;
246
      break;
247
 
248
    case 'I': /* MAC/EMAC scale factor.  */
249
      val = buffer[2] >> 1;
250
      break;
251
 
252
    case 'F': /* EMAC ACCx.  */
253
      val = buffer[0] >> 1;
254
      break;
255
 
256
    case 'f':
257
      val = buffer[1];
258
      break;
259
 
260
    case 's':
261
      val = buffer[1];
262
      break;
263
 
264
    case 'd':                   /* Destination, for register or quick.  */
265
      val = (buffer[0] << 8) + buffer[1];
266
      val >>= 9;
267
      break;
268
 
269
    case 'x':                   /* Destination, for general arg.  */
270
      val = (buffer[0] << 8) + buffer[1];
271
      val >>= 6;
272
      break;
273
 
274
    case 'k':
275 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
276
        return -1;
277 24 jeremybenn
      val = (buffer[3] >> 4);
278
      break;
279
 
280
    case 'C':
281 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
282
        return -1;
283 24 jeremybenn
      val = buffer[3];
284
      break;
285
 
286
    case '1':
287 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
288
        return -1;
289 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
290
      val >>= 12;
291
      break;
292
 
293
    case '2':
294 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
295
        return -1;
296 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
297
      val >>= 6;
298
      break;
299
 
300
    case '3':
301
    case 'j':
302 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
303
        return -1;
304 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
305
      break;
306
 
307
    case '4':
308 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 5))
309
        return -1;
310 24 jeremybenn
      val = (buffer[4] << 8) + buffer[5];
311
      val >>= 12;
312
      break;
313
 
314
    case '5':
315 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 5))
316
        return -1;
317 24 jeremybenn
      val = (buffer[4] << 8) + buffer[5];
318
      val >>= 6;
319
      break;
320
 
321
    case '6':
322 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 5))
323
        return -1;
324 24 jeremybenn
      val = (buffer[4] << 8) + buffer[5];
325
      break;
326
 
327
    case '7':
328 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
329
        return -1;
330 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
331
      val >>= 7;
332
      break;
333
 
334
    case '8':
335 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
336
        return -1;
337 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
338
      val >>= 10;
339
      break;
340
 
341
    case '9':
342 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
343
        return -1;
344 24 jeremybenn
      val = (buffer[2] << 8) + buffer[3];
345
      val >>= 5;
346
      break;
347
 
348
    case 'e':
349
      val = (buffer[1] >> 6);
350
      break;
351
 
352
    case 'E':
353 225 jeremybenn
      if (! FETCH_DATA (info, buffer + 3))
354
        return -1;
355 24 jeremybenn
      val = (buffer[2] >> 1);
356
      break;
357
 
358
    case 'm':
359
      val = (buffer[1] & 0x40 ? 0x8 : 0)
360
        | ((buffer[0] >> 1) & 0x7)
361
        | (buffer[3] & 0x80 ? 0x10 : 0);
362
      break;
363
 
364
    case 'n':
365
      val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
366
      break;
367
 
368
    case 'o':
369
      val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
370
      break;
371
 
372
    case 'M':
373
      val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
374
      break;
375
 
376
    case 'N':
377
      val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
378
      break;
379
 
380
    case 'h':
381
      val = buffer[2] >> 2;
382
      break;
383
 
384
    default:
385
      abort ();
386
    }
387
 
388
  /* bits is never too big.  */
389
  return val & ((1 << bits) - 1);
390
}
391
 
392
/* Check if an EA is valid for a particular code.  This is required
393
   for the EMAC instructions since the type of source address determines
394
   if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
395
   is a non-load EMAC instruction and the bits mean register Ry.
396
   A similar case exists for the movem instructions where the register
397
   mask is interpreted differently for different EAs.  */
398
 
399
static bfd_boolean
400
m68k_valid_ea (char code, int val)
401
{
402
  int mode, mask;
403
#define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
404
  (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
405
   | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
406
 
407
  switch (code)
408
    {
409
    case '*':
410
      mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
411
      break;
412
    case '~':
413
      mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
414
      break;
415
    case '%':
416
      mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
417
      break;
418
    case ';':
419
      mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
420
      break;
421
    case '@':
422
      mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
423
      break;
424
    case '!':
425
      mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
426
      break;
427
    case '&':
428
      mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
429
      break;
430
    case '$':
431
      mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
432
      break;
433
    case '?':
434
      mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
435
      break;
436
    case '/':
437
      mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
438
      break;
439
    case '|':
440
      mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
441
      break;
442
    case '>':
443
      mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
444
      break;
445
    case '<':
446
      mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
447
      break;
448
    case 'm':
449
      mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
450
      break;
451
    case 'n':
452
      mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
453
      break;
454
    case 'o':
455
      mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
456
      break;
457
    case 'p':
458
      mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
459
      break;
460
    case 'q':
461
      mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
462
      break;
463
    case 'v':
464
      mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
465
      break;
466
    case 'b':
467
      mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
468
      break;
469
    case 'w':
470
      mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
471
      break;
472
    case 'y':
473
      mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
474
      break;
475
    case 'z':
476
      mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
477
      break;
478
    case '4':
479
      mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
480
      break;
481
    default:
482
      abort ();
483
    }
484
#undef M
485
 
486
  mode = (val >> 3) & 7;
487
  if (mode == 7)
488
    mode += val & 7;
489
  return (mask & (1 << mode)) != 0;
490
}
491
 
492
/* Print a base register REGNO and displacement DISP, on INFO->STREAM.
493
   REGNO = -1 for pc, -2 for none (suppressed).  */
494
 
495
static void
496
print_base (int regno, bfd_vma disp, disassemble_info *info)
497
{
498
  if (regno == -1)
499
    {
500
      (*info->fprintf_func) (info->stream, "%%pc@(");
501
      (*info->print_address_func) (disp, info);
502
    }
503
  else
504
    {
505
      char buf[50];
506
 
507
      if (regno == -2)
508
        (*info->fprintf_func) (info->stream, "@(");
509
      else if (regno == -3)
510
        (*info->fprintf_func) (info->stream, "%%zpc@(");
511
      else
512
        (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
513
 
514
      sprintf_vma (buf, disp);
515
      (*info->fprintf_func) (info->stream, "%s", buf);
516
    }
517
}
518
 
519
/* Print an indexed argument.  The base register is BASEREG (-1 for pc).
520
   P points to extension word, in buffer.
521 225 jeremybenn
   ADDR is the nominal core address of that extension word.
522
   Returns NULL upon error.  */
523 24 jeremybenn
 
524
static unsigned char *
525
print_indexed (int basereg,
526
               unsigned char *p,
527
               bfd_vma addr,
528
               disassemble_info *info)
529
{
530
  int word;
531
  static char *const scales[] = { "", ":2", ":4", ":8" };
532
  bfd_vma base_disp;
533
  bfd_vma outer_disp;
534
  char buf[40];
535
  char vmabuf[50];
536
 
537 225 jeremybenn
  NEXTWORD (p, word, NULL);
538 24 jeremybenn
 
539
  /* Generate the text for the index register.
540
     Where this will be output is not yet determined.  */
541
  sprintf (buf, "%s:%c%s",
542
           reg_names[(word >> 12) & 0xf],
543
           (word & 0x800) ? 'l' : 'w',
544
           scales[(word >> 9) & 3]);
545
 
546
  /* Handle the 68000 style of indexing.  */
547
 
548
  if ((word & 0x100) == 0)
549
    {
550
      base_disp = word & 0xff;
551
      if ((base_disp & 0x80) != 0)
552
        base_disp -= 0x100;
553
      if (basereg == -1)
554
        base_disp += addr;
555
      print_base (basereg, base_disp, info);
556
      (*info->fprintf_func) (info->stream, ",%s)", buf);
557
      return p;
558
    }
559
 
560
  /* Handle the generalized kind.  */
561
  /* First, compute the displacement to add to the base register.  */
562
  if (word & 0200)
563
    {
564
      if (basereg == -1)
565
        basereg = -3;
566
      else
567
        basereg = -2;
568
    }
569
  if (word & 0100)
570
    buf[0] = '\0';
571
  base_disp = 0;
572
  switch ((word >> 4) & 3)
573
    {
574
    case 2:
575 225 jeremybenn
      NEXTWORD (p, base_disp, NULL);
576 24 jeremybenn
      break;
577
    case 3:
578 225 jeremybenn
      NEXTLONG (p, base_disp, NULL);
579 24 jeremybenn
    }
580
  if (basereg == -1)
581
    base_disp += addr;
582
 
583
  /* Handle single-level case (not indirect).  */
584
  if ((word & 7) == 0)
585
    {
586
      print_base (basereg, base_disp, info);
587
      if (buf[0] != '\0')
588
        (*info->fprintf_func) (info->stream, ",%s", buf);
589
      (*info->fprintf_func) (info->stream, ")");
590
      return p;
591
    }
592
 
593
  /* Two level.  Compute displacement to add after indirection.  */
594
  outer_disp = 0;
595
  switch (word & 3)
596
    {
597
    case 2:
598 225 jeremybenn
      NEXTWORD (p, outer_disp, NULL);
599 24 jeremybenn
      break;
600
    case 3:
601 225 jeremybenn
      NEXTLONG (p, outer_disp, NULL);
602 24 jeremybenn
    }
603
 
604
  print_base (basereg, base_disp, info);
605
  if ((word & 4) == 0 && buf[0] != '\0')
606
    {
607
      (*info->fprintf_func) (info->stream, ",%s", buf);
608
      buf[0] = '\0';
609
    }
610
  sprintf_vma (vmabuf, outer_disp);
611
  (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
612
  if (buf[0] != '\0')
613
    (*info->fprintf_func) (info->stream, ",%s", buf);
614
  (*info->fprintf_func) (info->stream, ")");
615
 
616
  return p;
617
}
618
 
619 225 jeremybenn
#define FETCH_ARG(size, val)                            \
620
  do                                                    \
621
    {                                                   \
622
      val = fetch_arg (buffer, place, size, info);      \
623
      if (val < 0)                                       \
624
        return -3;                                      \
625
    }                                                   \
626
  while (0)
627
 
628 24 jeremybenn
/* Returns number of bytes "eaten" by the operand, or
629
   return -1 if an invalid operand was found, or -2 if
630 225 jeremybenn
   an opcode tabe error was found or -3 to simply abort.
631 24 jeremybenn
   ADDR is the pc for this arg to be relative to.  */
632
 
633
static int
634
print_insn_arg (const char *d,
635
                unsigned char *buffer,
636
                unsigned char *p0,
637
                bfd_vma addr,
638
                disassemble_info *info)
639
{
640
  int val = 0;
641
  int place = d[1];
642
  unsigned char *p = p0;
643
  int regno;
644
  const char *regname;
645
  unsigned char *p1;
646
  double flval;
647
  int flt_p;
648
  bfd_signed_vma disp;
649
  unsigned int uval;
650
 
651
  switch (*d)
652
    {
653
    case 'c':           /* Cache identifier.  */
654
      {
655
        static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
656 225 jeremybenn
        FETCH_ARG (2, val);
657
        (*info->fprintf_func) (info->stream, cacheFieldName[val]);
658 24 jeremybenn
        break;
659
      }
660
 
661
    case 'a':           /* Address register indirect only. Cf. case '+'.  */
662
      {
663 225 jeremybenn
        FETCH_ARG (3, val);
664
        (*info->fprintf_func) (info->stream, "%s@", reg_names[val + 8]);
665 24 jeremybenn
        break;
666
      }
667
 
668
    case '_':           /* 32-bit absolute address for move16.  */
669
      {
670 225 jeremybenn
        NEXTULONG (p, uval);
671 24 jeremybenn
        (*info->print_address_func) (uval, info);
672
        break;
673
      }
674
 
675
    case 'C':
676
      (*info->fprintf_func) (info->stream, "%%ccr");
677
      break;
678
 
679
    case 'S':
680
      (*info->fprintf_func) (info->stream, "%%sr");
681
      break;
682
 
683
    case 'U':
684
      (*info->fprintf_func) (info->stream, "%%usp");
685
      break;
686
 
687
    case 'E':
688
      (*info->fprintf_func) (info->stream, "%%acc");
689
      break;
690
 
691
    case 'G':
692
      (*info->fprintf_func) (info->stream, "%%macsr");
693
      break;
694
 
695
    case 'H':
696
      (*info->fprintf_func) (info->stream, "%%mask");
697
      break;
698
 
699
    case 'J':
700
      {
701
        /* FIXME: There's a problem here, different m68k processors call the
702 225 jeremybenn
           same address different names.  The tables below try to get it right
703
           using info->mach, but only for v4e.  */
704
        struct regname { char * name; int value; };
705
        static const struct regname names[] =
706
          {
707
            {"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
708
            {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
709
            {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
710
            {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
711
            {"%msp", 0x803}, {"%isp", 0x804},
712
            {"%pc", 0x80f},
713
            /* Reg c04 is sometimes called flashbar or rambar.
714
               Rec c05 is also sometimes called rambar.  */
715
            {"%rambar0", 0xc04}, {"%rambar1", 0xc05},
716 24 jeremybenn
 
717 225 jeremybenn
            {"%mbar", 0xc0f},
718 24 jeremybenn
 
719 225 jeremybenn
            /* Should we be calling this psr like we do in case 'Y'?  */
720
            {"%mmusr",0x805},
721 24 jeremybenn
 
722 225 jeremybenn
            {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808},
723 24 jeremybenn
 
724 225 jeremybenn
            /* Fido added these.  */
725
            {"%cac", 0xffe}, {"%mbo", 0xfff}
726
        };
727
        /* Alternate names for v4e (MCF5407/5445x/MCF547x/MCF548x), at least.  */
728
        static const struct regname names_v4e[] =
729
          {
730
            {"%asid",0x003}, {"%acr0",0x004}, {"%acr1",0x005},
731
            {"%acr2",0x006}, {"%acr3",0x007}, {"%mmubar",0x008},
732
          };
733
        unsigned int arch_mask;
734
 
735
        arch_mask = bfd_m68k_mach_to_features (info->mach);
736
        FETCH_ARG (12, val);
737
        if (arch_mask & (mcfisa_b | mcfisa_c))
738
          {
739
            for (regno = ARRAY_SIZE (names_v4e); --regno >= 0;)
740
              if (names_v4e[regno].value == val)
741
                {
742
                  (*info->fprintf_func) (info->stream, "%s", names_v4e[regno].name);
743
                  break;
744
                }
745
            if (regno >= 0)
746
              break;
747
          }
748
        for (regno = ARRAY_SIZE (names) - 1; regno >= 0; regno--)
749 24 jeremybenn
          if (names[regno].value == val)
750
            {
751
              (*info->fprintf_func) (info->stream, "%s", names[regno].name);
752
              break;
753
            }
754
        if (regno < 0)
755 225 jeremybenn
          (*info->fprintf_func) (info->stream, "0x%x", val);
756 24 jeremybenn
      }
757
      break;
758
 
759
    case 'Q':
760 225 jeremybenn
      FETCH_ARG (3, val);
761 24 jeremybenn
      /* 0 means 8, except for the bkpt instruction... */
762
      if (val == 0 && d[1] != 's')
763
        val = 8;
764
      (*info->fprintf_func) (info->stream, "#%d", val);
765
      break;
766
 
767
    case 'x':
768 225 jeremybenn
      FETCH_ARG (3, val);
769 24 jeremybenn
      /* 0 means -1.  */
770
      if (val == 0)
771
        val = -1;
772
      (*info->fprintf_func) (info->stream, "#%d", val);
773
      break;
774
 
775
    case 'j':
776 225 jeremybenn
      FETCH_ARG (3, val);
777 24 jeremybenn
      (*info->fprintf_func) (info->stream, "#%d", val+1);
778
      break;
779
 
780
    case 'K':
781 225 jeremybenn
      FETCH_ARG (9, val);
782 24 jeremybenn
      (*info->fprintf_func) (info->stream, "#%d", val);
783
      break;
784
 
785
    case 'M':
786
      if (place == 'h')
787
        {
788
          static char *const scalefactor_name[] = { "<<", ">>" };
789 225 jeremybenn
 
790
          FETCH_ARG (1, val);
791 24 jeremybenn
          (*info->fprintf_func) (info->stream, scalefactor_name[val]);
792
        }
793
      else
794
        {
795 225 jeremybenn
          FETCH_ARG (8, val);
796 24 jeremybenn
          if (val & 0x80)
797
            val = val - 0x100;
798
          (*info->fprintf_func) (info->stream, "#%d", val);
799
        }
800
      break;
801
 
802
    case 'T':
803 225 jeremybenn
      FETCH_ARG (4, val);
804 24 jeremybenn
      (*info->fprintf_func) (info->stream, "#%d", val);
805
      break;
806
 
807
    case 'D':
808 225 jeremybenn
      FETCH_ARG (3, val);
809
      (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
810 24 jeremybenn
      break;
811
 
812
    case 'A':
813 225 jeremybenn
      FETCH_ARG (3, val);
814
      (*info->fprintf_func) (info->stream, "%s", reg_names[val + 010]);
815 24 jeremybenn
      break;
816
 
817
    case 'R':
818 225 jeremybenn
      FETCH_ARG (4, val);
819
      (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
820 24 jeremybenn
      break;
821
 
822
    case 'r':
823 225 jeremybenn
      FETCH_ARG (4, regno);
824 24 jeremybenn
      if (regno > 7)
825
        (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
826
      else
827
        (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
828
      break;
829
 
830
    case 'F':
831 225 jeremybenn
      FETCH_ARG (3, val);
832
      (*info->fprintf_func) (info->stream, "%%fp%d", val);
833 24 jeremybenn
      break;
834
 
835
    case 'O':
836 225 jeremybenn
      FETCH_ARG (6, val);
837 24 jeremybenn
      if (val & 0x20)
838
        (*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
839
      else
840
        (*info->fprintf_func) (info->stream, "%d", val);
841
      break;
842
 
843
    case '+':
844 225 jeremybenn
      FETCH_ARG (3, val);
845
      (*info->fprintf_func) (info->stream, "%s@+", reg_names[val + 8]);
846 24 jeremybenn
      break;
847
 
848
    case '-':
849 225 jeremybenn
      FETCH_ARG (3, val);
850
      (*info->fprintf_func) (info->stream, "%s@-", reg_names[val + 8]);
851 24 jeremybenn
      break;
852
 
853
    case 'k':
854
      if (place == 'k')
855 225 jeremybenn
        {
856
          FETCH_ARG (3, val);
857
          (*info->fprintf_func) (info->stream, "{%s}", reg_names[val]);
858
        }
859 24 jeremybenn
      else if (place == 'C')
860
        {
861 225 jeremybenn
          FETCH_ARG (7, val);
862 24 jeremybenn
          if (val > 63)         /* This is a signed constant.  */
863
            val -= 128;
864
          (*info->fprintf_func) (info->stream, "{#%d}", val);
865
        }
866
      else
867 225 jeremybenn
        return -1;
868 24 jeremybenn
      break;
869
 
870
    case '#':
871
    case '^':
872
      p1 = buffer + (*d == '#' ? 2 : 4);
873
      if (place == 's')
874 225 jeremybenn
        FETCH_ARG (4, val);
875 24 jeremybenn
      else if (place == 'C')
876 225 jeremybenn
        FETCH_ARG (7, val);
877 24 jeremybenn
      else if (place == '8')
878 225 jeremybenn
        FETCH_ARG (3, val);
879 24 jeremybenn
      else if (place == '3')
880 225 jeremybenn
        FETCH_ARG (8, val);
881 24 jeremybenn
      else if (place == 'b')
882 225 jeremybenn
        NEXTBYTE (p1, val);
883 24 jeremybenn
      else if (place == 'w' || place == 'W')
884 225 jeremybenn
        NEXTWORD (p1, val, -3);
885 24 jeremybenn
      else if (place == 'l')
886 225 jeremybenn
        NEXTLONG (p1, val, -3);
887 24 jeremybenn
      else
888
        return -2;
889 225 jeremybenn
 
890 24 jeremybenn
      (*info->fprintf_func) (info->stream, "#%d", val);
891
      break;
892
 
893
    case 'B':
894
      if (place == 'b')
895 225 jeremybenn
        NEXTBYTE (p, disp);
896 24 jeremybenn
      else if (place == 'B')
897
        disp = COERCE_SIGNED_CHAR (buffer[1]);
898
      else if (place == 'w' || place == 'W')
899 225 jeremybenn
        NEXTWORD (p, disp, -3);
900 24 jeremybenn
      else if (place == 'l' || place == 'L' || place == 'C')
901 225 jeremybenn
        NEXTLONG (p, disp, -3);
902 24 jeremybenn
      else if (place == 'g')
903
        {
904 225 jeremybenn
          NEXTBYTE (buffer, disp);
905 24 jeremybenn
          if (disp == 0)
906 225 jeremybenn
            NEXTWORD (p, disp, -3);
907 24 jeremybenn
          else if (disp == -1)
908 225 jeremybenn
            NEXTLONG (p, disp, -3);
909 24 jeremybenn
        }
910
      else if (place == 'c')
911
        {
912
          if (buffer[1] & 0x40)         /* If bit six is one, long offset.  */
913 225 jeremybenn
            NEXTLONG (p, disp, -3);
914 24 jeremybenn
          else
915 225 jeremybenn
            NEXTWORD (p, disp, -3);
916 24 jeremybenn
        }
917
      else
918
        return -2;
919
 
920
      (*info->print_address_func) (addr + disp, info);
921
      break;
922
 
923
    case 'd':
924 225 jeremybenn
      {
925
        int val1;
926 24 jeremybenn
 
927 225 jeremybenn
        NEXTWORD (p, val, -3);
928
        FETCH_ARG (3, val1);
929
        (*info->fprintf_func) (info->stream, "%s@(%d)", reg_names[val1 + 8], val);
930
        break;
931
      }
932
 
933 24 jeremybenn
    case 's':
934 225 jeremybenn
      FETCH_ARG (3, val);
935
      (*info->fprintf_func) (info->stream, "%s", fpcr_names[val]);
936 24 jeremybenn
      break;
937
 
938
    case 'e':
939 225 jeremybenn
      FETCH_ARG (2, val);
940 24 jeremybenn
      (*info->fprintf_func) (info->stream, "%%acc%d", val);
941
      break;
942
 
943
    case 'g':
944 225 jeremybenn
      FETCH_ARG (1, val);
945
      (*info->fprintf_func) (info->stream, "%%accext%s", val == 0 ? "01" : "23");
946 24 jeremybenn
      break;
947
 
948
    case 'i':
949 225 jeremybenn
      FETCH_ARG (2, val);
950 24 jeremybenn
      if (val == 1)
951
        (*info->fprintf_func) (info->stream, "<<");
952
      else if (val == 3)
953
        (*info->fprintf_func) (info->stream, ">>");
954
      else
955
        return -1;
956
      break;
957
 
958
    case 'I':
959
      /* Get coprocessor ID... */
960
      val = fetch_arg (buffer, 'd', 3, info);
961 225 jeremybenn
      if (val < 0)
962
        return -3;
963 24 jeremybenn
      if (val != 1)                             /* Unusual coprocessor ID?  */
964
        (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
965
      break;
966
 
967
    case '4':
968
    case '*':
969
    case '~':
970
    case '%':
971
    case ';':
972
    case '@':
973
    case '!':
974
    case '$':
975
    case '?':
976
    case '/':
977
    case '&':
978
    case '|':
979
    case '<':
980
    case '>':
981
    case 'm':
982
    case 'n':
983
    case 'o':
984
    case 'p':
985
    case 'q':
986
    case 'v':
987
    case 'b':
988
    case 'w':
989
    case 'y':
990
    case 'z':
991
      if (place == 'd')
992
        {
993
          val = fetch_arg (buffer, 'x', 6, info);
994 225 jeremybenn
          if (val < 0)
995
            return -3;
996 24 jeremybenn
          val = ((val & 7) << 3) + ((val >> 3) & 7);
997
        }
998
      else
999 225 jeremybenn
        {
1000
          val = fetch_arg (buffer, 's', 6, info);
1001
          if (val < 0)
1002
            return -3;
1003
        }
1004 24 jeremybenn
 
1005
      /* If the <ea> is invalid for *d, then reject this match.  */
1006
      if (!m68k_valid_ea (*d, val))
1007
        return -1;
1008
 
1009
      /* Get register number assuming address register.  */
1010
      regno = (val & 7) + 8;
1011
      regname = reg_names[regno];
1012
      switch (val >> 3)
1013
        {
1014
        case 0:
1015
          (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
1016
          break;
1017
 
1018
        case 1:
1019
          (*info->fprintf_func) (info->stream, "%s", regname);
1020
          break;
1021
 
1022
        case 2:
1023
          (*info->fprintf_func) (info->stream, "%s@", regname);
1024
          break;
1025
 
1026
        case 3:
1027
          (*info->fprintf_func) (info->stream, "%s@+", regname);
1028
          break;
1029
 
1030
        case 4:
1031
          (*info->fprintf_func) (info->stream, "%s@-", regname);
1032
          break;
1033
 
1034
        case 5:
1035 225 jeremybenn
          NEXTWORD (p, val, -3);
1036 24 jeremybenn
          (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
1037
          break;
1038
 
1039
        case 6:
1040
          p = print_indexed (regno, p, addr, info);
1041 225 jeremybenn
          if (p == NULL)
1042
            return -3;
1043 24 jeremybenn
          break;
1044
 
1045
        case 7:
1046
          switch (val & 7)
1047
            {
1048
            case 0:
1049 225 jeremybenn
              NEXTWORD (p, val, -3);
1050 24 jeremybenn
              (*info->print_address_func) (val, info);
1051
              break;
1052
 
1053
            case 1:
1054 225 jeremybenn
              NEXTULONG (p, uval);
1055 24 jeremybenn
              (*info->print_address_func) (uval, info);
1056
              break;
1057
 
1058
            case 2:
1059 225 jeremybenn
              NEXTWORD (p, val, -3);
1060 24 jeremybenn
              (*info->fprintf_func) (info->stream, "%%pc@(");
1061
              (*info->print_address_func) (addr + val, info);
1062
              (*info->fprintf_func) (info->stream, ")");
1063
              break;
1064
 
1065
            case 3:
1066
              p = print_indexed (-1, p, addr, info);
1067 225 jeremybenn
              if (p == NULL)
1068
                return -3;
1069 24 jeremybenn
              break;
1070
 
1071
            case 4:
1072
              flt_p = 1;        /* Assume it's a float... */
1073
              switch (place)
1074
              {
1075
                case 'b':
1076 225 jeremybenn
                  NEXTBYTE (p, val);
1077 24 jeremybenn
                  flt_p = 0;
1078
                  break;
1079
 
1080
                case 'w':
1081 225 jeremybenn
                  NEXTWORD (p, val, -3);
1082 24 jeremybenn
                  flt_p = 0;
1083
                  break;
1084
 
1085
                case 'l':
1086 225 jeremybenn
                  NEXTLONG (p, val, -3);
1087 24 jeremybenn
                  flt_p = 0;
1088
                  break;
1089
 
1090
                case 'f':
1091
                  NEXTSINGLE (flval, p);
1092
                  break;
1093
 
1094
                case 'F':
1095
                  NEXTDOUBLE (flval, p);
1096
                  break;
1097
 
1098
                case 'x':
1099
                  NEXTEXTEND (flval, p);
1100
                  break;
1101
 
1102
                case 'p':
1103 225 jeremybenn
                  NEXTPACKED (p, flval);
1104 24 jeremybenn
                  break;
1105
 
1106
                default:
1107
                  return -1;
1108
              }
1109
              if (flt_p)        /* Print a float? */
1110
                (*info->fprintf_func) (info->stream, "#%g", flval);
1111
              else
1112
                (*info->fprintf_func) (info->stream, "#%d", val);
1113
              break;
1114
 
1115
            default:
1116
              return -1;
1117
            }
1118
        }
1119
 
1120
      /* If place is '/', then this is the case of the mask bit for
1121
         mac/emac loads. Now that the arg has been printed, grab the
1122
         mask bit and if set, add a '&' to the arg.  */
1123
      if (place == '/')
1124
        {
1125 225 jeremybenn
          FETCH_ARG (1, val);
1126 24 jeremybenn
          if (val)
1127
            info->fprintf_func (info->stream, "&");
1128
        }
1129
      break;
1130
 
1131
    case 'L':
1132
    case 'l':
1133
        if (place == 'w')
1134
          {
1135
            char doneany;
1136
            p1 = buffer + 2;
1137 225 jeremybenn
            NEXTWORD (p1, val, -3);
1138 24 jeremybenn
            /* Move the pointer ahead if this point is farther ahead
1139
               than the last.  */
1140
            p = p1 > p ? p1 : p;
1141
            if (val == 0)
1142
              {
1143
                (*info->fprintf_func) (info->stream, "#0");
1144
                break;
1145
              }
1146
            if (*d == 'l')
1147
              {
1148
                int newval = 0;
1149
 
1150
                for (regno = 0; regno < 16; ++regno)
1151
                  if (val & (0x8000 >> regno))
1152
                    newval |= 1 << regno;
1153
                val = newval;
1154
              }
1155
            val &= 0xffff;
1156
            doneany = 0;
1157
            for (regno = 0; regno < 16; ++regno)
1158
              if (val & (1 << regno))
1159
                {
1160
                  int first_regno;
1161
 
1162
                  if (doneany)
1163
                    (*info->fprintf_func) (info->stream, "/");
1164
                  doneany = 1;
1165
                  (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
1166
                  first_regno = regno;
1167
                  while (val & (1 << (regno + 1)))
1168
                    ++regno;
1169
                  if (regno > first_regno)
1170
                    (*info->fprintf_func) (info->stream, "-%s",
1171
                                           reg_names[regno]);
1172
                }
1173
          }
1174
        else if (place == '3')
1175
          {
1176
            /* `fmovem' insn.  */
1177
            char doneany;
1178 225 jeremybenn
 
1179
            FETCH_ARG (8, val);
1180 24 jeremybenn
            if (val == 0)
1181
              {
1182
                (*info->fprintf_func) (info->stream, "#0");
1183
                break;
1184
              }
1185
            if (*d == 'l')
1186
              {
1187
                int newval = 0;
1188
 
1189
                for (regno = 0; regno < 8; ++regno)
1190
                  if (val & (0x80 >> regno))
1191
                    newval |= 1 << regno;
1192
                val = newval;
1193
              }
1194
            val &= 0xff;
1195
            doneany = 0;
1196
            for (regno = 0; regno < 8; ++regno)
1197
              if (val & (1 << regno))
1198
                {
1199
                  int first_regno;
1200
                  if (doneany)
1201
                    (*info->fprintf_func) (info->stream, "/");
1202
                  doneany = 1;
1203
                  (*info->fprintf_func) (info->stream, "%%fp%d", regno);
1204
                  first_regno = regno;
1205
                  while (val & (1 << (regno + 1)))
1206
                    ++regno;
1207
                  if (regno > first_regno)
1208
                    (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
1209
                }
1210
          }
1211
        else if (place == '8')
1212
          {
1213 225 jeremybenn
            FETCH_ARG (3, val);
1214 24 jeremybenn
            /* fmoveml for FP status registers.  */
1215 225 jeremybenn
            (*info->fprintf_func) (info->stream, "%s", fpcr_names[val]);
1216 24 jeremybenn
          }
1217
        else
1218
          return -2;
1219
      break;
1220
 
1221
    case 'X':
1222
      place = '8';
1223
    case 'Y':
1224
    case 'Z':
1225
    case 'W':
1226
    case '0':
1227
    case '1':
1228
    case '2':
1229
    case '3':
1230
      {
1231 225 jeremybenn
        int val;
1232 24 jeremybenn
        char *name = 0;
1233
 
1234 225 jeremybenn
        FETCH_ARG (5, val);
1235 24 jeremybenn
        switch (val)
1236
          {
1237
          case 2: name = "%tt0"; break;
1238
          case 3: name = "%tt1"; break;
1239
          case 0x10: name = "%tc"; break;
1240
          case 0x11: name = "%drp"; break;
1241
          case 0x12: name = "%srp"; break;
1242
          case 0x13: name = "%crp"; break;
1243
          case 0x14: name = "%cal"; break;
1244
          case 0x15: name = "%val"; break;
1245
          case 0x16: name = "%scc"; break;
1246
          case 0x17: name = "%ac"; break;
1247
          case 0x18: name = "%psr"; break;
1248
          case 0x19: name = "%pcsr"; break;
1249
          case 0x1c:
1250
          case 0x1d:
1251
            {
1252
              int break_reg = ((buffer[3] >> 2) & 7);
1253
 
1254
              (*info->fprintf_func)
1255
                (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
1256
                 break_reg);
1257
            }
1258
            break;
1259
          default:
1260
            (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
1261
          }
1262
        if (name)
1263
          (*info->fprintf_func) (info->stream, "%s", name);
1264
      }
1265
      break;
1266
 
1267
    case 'f':
1268
      {
1269 225 jeremybenn
        int fc;
1270 24 jeremybenn
 
1271 225 jeremybenn
        FETCH_ARG (5, fc);
1272 24 jeremybenn
        if (fc == 1)
1273
          (*info->fprintf_func) (info->stream, "%%dfc");
1274
        else if (fc == 0)
1275
          (*info->fprintf_func) (info->stream, "%%sfc");
1276
        else
1277
          /* xgettext:c-format */
1278
          (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
1279
      }
1280
      break;
1281
 
1282
    case 'V':
1283
      (*info->fprintf_func) (info->stream, "%%val");
1284
      break;
1285
 
1286
    case 't':
1287
      {
1288 225 jeremybenn
        int level;
1289 24 jeremybenn
 
1290 225 jeremybenn
        FETCH_ARG (3, level);
1291 24 jeremybenn
        (*info->fprintf_func) (info->stream, "%d", level);
1292
      }
1293
      break;
1294
 
1295
    case 'u':
1296
      {
1297
        short is_upper = 0;
1298 225 jeremybenn
        int reg;
1299 24 jeremybenn
 
1300 225 jeremybenn
        FETCH_ARG (5, reg);
1301 24 jeremybenn
        if (reg & 0x10)
1302
          {
1303
            is_upper = 1;
1304
            reg &= 0xf;
1305
          }
1306
        (*info->fprintf_func) (info->stream, "%s%s",
1307
                               reg_half_names[reg],
1308
                               is_upper ? "u" : "l");
1309
      }
1310
      break;
1311
 
1312
    default:
1313
      return -2;
1314
    }
1315
 
1316
  return p - p0;
1317
}
1318
 
1319
/* Try to match the current instruction to best and if so, return the
1320
   number of bytes consumed from the instruction stream, else zero.  */
1321
 
1322
static int
1323
match_insn_m68k (bfd_vma memaddr,
1324
                 disassemble_info * info,
1325
                 const struct m68k_opcode * best)
1326
{
1327
  unsigned char *save_p;
1328
  unsigned char *p;
1329
  const char *d;
1330
  const char *args = best->args;
1331
 
1332
  struct private *priv = (struct private *) info->private_data;
1333
  bfd_byte *buffer = priv->the_buffer;
1334
  fprintf_ftype save_printer = info->fprintf_func;
1335
  void (* save_print_address) (bfd_vma, struct disassemble_info *)
1336
    = info->print_address_func;
1337
 
1338
  if (*args == '.')
1339
    args++;
1340
 
1341
  /* Point at first word of argument data,
1342
     and at descriptor for first argument.  */
1343
  p = buffer + 2;
1344
 
1345
  /* Figure out how long the fixed-size portion of the instruction is.
1346
     The only place this is stored in the opcode table is
1347
     in the arguments--look for arguments which specify fields in the 2nd
1348
     or 3rd words of the instruction.  */
1349
  for (d = args; *d; d += 2)
1350
    {
1351
      /* I don't think it is necessary to be checking d[0] here;
1352
         I suspect all this could be moved to the case statement below.  */
1353
      if (d[0] == '#')
1354
        {
1355
          if (d[1] == 'l' && p - buffer < 6)
1356
            p = buffer + 6;
1357
          else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
1358
            p = buffer + 4;
1359
        }
1360
 
1361
      if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
1362
        p = buffer + 4;
1363
 
1364
      switch (d[1])
1365
        {
1366
        case '1':
1367
        case '2':
1368
        case '3':
1369
        case '7':
1370
        case '8':
1371
        case '9':
1372
        case 'i':
1373
          if (p - buffer < 4)
1374
            p = buffer + 4;
1375
          break;
1376
        case '4':
1377
        case '5':
1378
        case '6':
1379
          if (p - buffer < 6)
1380
            p = buffer + 6;
1381
          break;
1382
        default:
1383
          break;
1384
        }
1385
    }
1386
 
1387
  /* pflusha is an exceptions.  It takes no arguments but is two words
1388
     long.  Recognize it by looking at the lower 16 bits of the mask.  */
1389
  if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
1390
    p = buffer + 4;
1391
 
1392
  /* lpstop is another exception.  It takes a one word argument but is
1393
     three words long.  */
1394
  if (p - buffer < 6
1395
      && (best->match & 0xffff) == 0xffff
1396
      && args[0] == '#'
1397
      && args[1] == 'w')
1398
    {
1399
      /* Copy the one word argument into the usual location for a one
1400
         word argument, to simplify printing it.  We can get away with
1401
         this because we know exactly what the second word is, and we
1402
         aren't going to print anything based on it.  */
1403
      p = buffer + 6;
1404
      FETCH_DATA (info, p);
1405
      buffer[2] = buffer[4];
1406
      buffer[3] = buffer[5];
1407
    }
1408
 
1409
  FETCH_DATA (info, p);
1410
 
1411
  save_p = p;
1412
  info->print_address_func = dummy_print_address;
1413
  info->fprintf_func = (fprintf_ftype) dummy_printer;
1414
 
1415
  /* We scan the operands twice.  The first time we don't print anything,
1416
     but look for errors.  */
1417
  for (d = args; *d; d += 2)
1418
    {
1419
      int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1420
 
1421
      if (eaten >= 0)
1422
        p += eaten;
1423 225 jeremybenn
      else if (eaten == -1 || eaten == -3)
1424 24 jeremybenn
        {
1425
          info->fprintf_func = save_printer;
1426
          info->print_address_func = save_print_address;
1427
          return 0;
1428
        }
1429
      else
1430
        {
1431
          /* We must restore the print functions before trying to print the
1432
             error message.  */
1433
          info->fprintf_func = save_printer;
1434
          info->print_address_func = save_print_address;
1435
          info->fprintf_func (info->stream,
1436
                              /* xgettext:c-format */
1437
                              _("<internal error in opcode table: %s %s>\n"),
1438 225 jeremybenn
                              best->name, best->args);
1439 24 jeremybenn
          return 2;
1440
        }
1441
    }
1442
 
1443
  p = save_p;
1444
  info->fprintf_func = save_printer;
1445
  info->print_address_func = save_print_address;
1446
 
1447
  d = args;
1448
 
1449
  info->fprintf_func (info->stream, "%s", best->name);
1450
 
1451
  if (*d)
1452
    info->fprintf_func (info->stream, " ");
1453
 
1454
  while (*d)
1455
    {
1456
      p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1457
      d += 2;
1458
 
1459
      if (*d && *(d - 2) != 'I' && *d != 'k')
1460
        info->fprintf_func (info->stream, ",");
1461
    }
1462
 
1463
  return p - buffer;
1464
}
1465
 
1466
/* Try to interpret the instruction at address MEMADDR as one that
1467
   can execute on a processor with the features given by ARCH_MASK.
1468
   If successful, print the instruction to INFO->STREAM and return
1469
   its length in bytes.  Return 0 otherwise.  */
1470
 
1471
static int
1472
m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
1473
                unsigned int arch_mask)
1474
{
1475
  int i;
1476
  const char *d;
1477
  static const struct m68k_opcode **opcodes[16];
1478
  static int numopcodes[16];
1479
  int val;
1480
  int major_opcode;
1481
 
1482
  struct private *priv = (struct private *) info->private_data;
1483
  bfd_byte *buffer = priv->the_buffer;
1484
 
1485
  if (!opcodes[0])
1486
    {
1487
      /* Speed up the matching by sorting the opcode
1488
         table on the upper four bits of the opcode.  */
1489
      const struct m68k_opcode **opc_pointer[16];
1490
 
1491
      /* First count how many opcodes are in each of the sixteen buckets.  */
1492
      for (i = 0; i < m68k_numopcodes; i++)
1493
        numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
1494
 
1495
      /* Then create a sorted table of pointers
1496
         that point into the unsorted table.  */
1497
      opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
1498
                                * m68k_numopcodes);
1499
      opcodes[0] = opc_pointer[0];
1500
 
1501
      for (i = 1; i < 16; i++)
1502
        {
1503
          opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
1504
          opcodes[i] = opc_pointer[i];
1505
        }
1506
 
1507
      for (i = 0; i < m68k_numopcodes; i++)
1508
        *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
1509
    }
1510
 
1511
  FETCH_DATA (info, buffer + 2);
1512
  major_opcode = (buffer[0] >> 4) & 15;
1513
 
1514
  for (i = 0; i < numopcodes[major_opcode]; i++)
1515
    {
1516
      const struct m68k_opcode *opc = opcodes[major_opcode][i];
1517
      unsigned long opcode = opc->opcode;
1518
      unsigned long match = opc->match;
1519
      const char *args = opc->args;
1520
 
1521
      if (*args == '.')
1522
        args++;
1523
 
1524
      if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
1525
          && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
1526
          /* Only fetch the next two bytes if we need to.  */
1527
          && (((0xffff & match) == 0)
1528
              ||
1529
              (FETCH_DATA (info, buffer + 4)
1530
               && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
1531
               && ((0xff & buffer[3] & match) == (0xff & opcode)))
1532
              )
1533
          && (opc->arch & arch_mask) != 0)
1534
        {
1535
          /* Don't use for printout the variants of divul and divsl
1536
             that have the same register number in two places.
1537
             The more general variants will match instead.  */
1538
          for (d = args; *d; d += 2)
1539
            if (d[1] == 'D')
1540
              break;
1541
 
1542
          /* Don't use for printout the variants of most floating
1543
             point coprocessor instructions which use the same
1544
             register number in two places, as above.  */
1545
          if (*d == '\0')
1546
            for (d = args; *d; d += 2)
1547
              if (d[1] == 't')
1548
                break;
1549
 
1550
          /* Don't match fmovel with more than one register;
1551
             wait for fmoveml.  */
1552
          if (*d == '\0')
1553
            {
1554
              for (d = args; *d; d += 2)
1555
                {
1556
                  if (d[0] == 's' && d[1] == '8')
1557
                    {
1558
                      val = fetch_arg (buffer, d[1], 3, info);
1559 225 jeremybenn
                      if (val < 0)
1560
                        return 0;
1561 24 jeremybenn
                      if ((val & (val - 1)) != 0)
1562
                        break;
1563
                    }
1564
                }
1565
            }
1566
 
1567
          /* Don't match FPU insns with non-default coprocessor ID.  */
1568
          if (*d == '\0')
1569
            {
1570
              for (d = args; *d; d += 2)
1571
                {
1572
                  if (d[0] == 'I')
1573
                    {
1574
                      val = fetch_arg (buffer, 'd', 3, info);
1575
                      if (val != 1)
1576
                        break;
1577
                    }
1578
                }
1579
            }
1580
 
1581
          if (*d == '\0')
1582
            if ((val = match_insn_m68k (memaddr, info, opc)))
1583
              return val;
1584
        }
1585
    }
1586
  return 0;
1587
}
1588
 
1589
/* Print the m68k instruction at address MEMADDR in debugged memory,
1590
   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
1591
 
1592
int
1593
print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
1594
{
1595
  unsigned int arch_mask;
1596
  struct private priv;
1597
  int val;
1598
 
1599
  bfd_byte *buffer = priv.the_buffer;
1600
 
1601 225 jeremybenn
  info->private_data = & priv;
1602 24 jeremybenn
  /* Tell objdump to use two bytes per chunk
1603
     and six bytes per line for displaying raw data.  */
1604
  info->bytes_per_chunk = 2;
1605
  info->bytes_per_line = 6;
1606
  info->display_endian = BFD_ENDIAN_BIG;
1607
  priv.max_fetched = priv.the_buffer;
1608
  priv.insn_start = memaddr;
1609
 
1610
  arch_mask = bfd_m68k_mach_to_features (info->mach);
1611
  if (!arch_mask)
1612
    {
1613
      /* First try printing an m680x0 instruction.  Try printing a Coldfire
1614
         one if that fails.  */
1615
      val = m68k_scan_mask (memaddr, info, m68k_mask);
1616 225 jeremybenn
      if (val == 0)
1617
        val = m68k_scan_mask (memaddr, info, mcf_mask);
1618 24 jeremybenn
    }
1619
  else
1620
    {
1621
      val = m68k_scan_mask (memaddr, info, arch_mask);
1622
    }
1623
 
1624 225 jeremybenn
  if (val == 0)
1625
    /* Handle undefined instructions.  */
1626
    info->fprintf_func (info->stream, "0%o", (buffer[0] << 8) + buffer[1]);
1627
 
1628
  return val ? val : 2;
1629 24 jeremybenn
}

powered by: WebSVN 2.1.0

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