Coverage Report

Created: 2023-08-28 06:23

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