~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/opcodes/m10300-dis.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Disassemble MN10300 instructions.
 
2
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2007, 2012
 
3
   Free Software Foundation, Inc.
 
4
 
 
5
   This file is part of the GNU opcodes library.
 
6
 
 
7
   This library is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3, or (at your option)
 
10
   any later version.
 
11
 
 
12
   It is distributed in the hope that it will be useful, but WITHOUT
 
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 
15
   License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software
 
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
 
20
   MA 02110-1301, USA.  */
 
21
 
 
22
#include "sysdep.h"
 
23
#include <stdio.h>
 
24
#include "opcode/mn10300.h"
 
25
#include "dis-asm.h"
 
26
#include "opintl.h"
 
27
 
 
28
#define HAVE_AM33_2 (info->mach == AM33_2)
 
29
#define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)
 
30
#define HAVE_AM30   (info->mach == AM30)
 
31
 
 
32
static void
 
33
disassemble (bfd_vma memaddr,
 
34
             struct disassemble_info *info,
 
35
             unsigned long insn,
 
36
             unsigned int size)
 
37
{
 
38
  struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
 
39
  const struct mn10300_operand *operand;
 
40
  bfd_byte buffer[4];
 
41
  unsigned long extension = 0;
 
42
  int status, match = 0;
 
43
 
 
44
  /* Find the opcode.  */
 
45
  while (op->name)
 
46
    {
 
47
      int mysize, extra_shift;
 
48
 
 
49
      if (op->format == FMT_S0)
 
50
        mysize = 1;
 
51
      else if (op->format == FMT_S1
 
52
               || op->format == FMT_D0)
 
53
        mysize = 2;
 
54
      else if (op->format == FMT_S2
 
55
               || op->format == FMT_D1)
 
56
        mysize = 3;
 
57
      else if (op->format == FMT_S4)
 
58
        mysize = 5;
 
59
      else if (op->format == FMT_D2)
 
60
        mysize = 4;
 
61
      else if (op->format == FMT_D3)
 
62
        mysize = 5;
 
63
      else if (op->format == FMT_D4)
 
64
        mysize = 6;
 
65
      else if (op->format == FMT_D6)
 
66
        mysize = 3;
 
67
      else if (op->format == FMT_D7 || op->format == FMT_D10)
 
68
        mysize = 4;
 
69
      else if (op->format == FMT_D8)
 
70
        mysize = 6;
 
71
      else if (op->format == FMT_D9)
 
72
        mysize = 7;
 
73
      else
 
74
        mysize = 7;
 
75
 
 
76
      if ((op->mask & insn) == op->opcode
 
77
          && size == (unsigned int) mysize
 
78
          && (op->machine == 0
 
79
              || (op->machine == AM33_2 && HAVE_AM33_2)
 
80
              || (op->machine == AM33 && HAVE_AM33)
 
81
              || (op->machine == AM30 && HAVE_AM30)))
 
82
        {
 
83
          const unsigned char *opindex_ptr;
 
84
          unsigned int nocomma;
 
85
          int paren = 0;
 
86
 
 
87
          if (op->format == FMT_D1 || op->format == FMT_S1)
 
88
            extra_shift = 8;
 
89
          else if (op->format == FMT_D2 || op->format == FMT_D4
 
90
                   || op->format == FMT_S2 || op->format == FMT_S4
 
91
                   || op->format == FMT_S6 || op->format == FMT_D5)
 
92
            extra_shift = 16;
 
93
          else if (op->format == FMT_D7
 
94
                   || op->format == FMT_D8
 
95
                   || op->format == FMT_D9)
 
96
            extra_shift = 8;
 
97
          else
 
98
            extra_shift = 0;
 
99
 
 
100
          if (size == 1 || size == 2)
 
101
            extension = 0;
 
102
 
 
103
          else if (size == 3
 
104
                   && (op->format == FMT_D1
 
105
                       || op->opcode == 0xdf0000
 
106
                       || op->opcode == 0xde0000))
 
107
            extension = 0;
 
108
 
 
109
          else if (size == 3
 
110
                   && op->format == FMT_D6)
 
111
            extension = 0;
 
112
 
 
113
          else if (size == 3)
 
114
            {
 
115
              insn &= 0xff0000;
 
116
              status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
 
117
              if (status != 0)
 
118
                {
 
119
                  (*info->memory_error_func) (status, memaddr, info);
 
120
                  return;
 
121
                }
 
122
 
 
123
              insn |= bfd_getl16 (buffer);
 
124
              extension = 0;
 
125
            }
 
126
          else if (size == 4
 
127
                   && (op->opcode == 0xfaf80000
 
128
                       || op->opcode == 0xfaf00000
 
129
                       || op->opcode == 0xfaf40000))
 
130
            extension = 0;
 
131
 
 
132
          else if (size == 4
 
133
                   && (op->format == FMT_D7
 
134
                       || op->format == FMT_D10))
 
135
            extension = 0;
 
136
 
 
137
          else if (size == 4)
 
138
            {
 
139
              insn &= 0xffff0000;
 
140
              status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
 
141
              if (status != 0)
 
142
                {
 
143
                  (*info->memory_error_func) (status, memaddr, info);
 
144
                  return;
 
145
                }
 
146
 
 
147
              insn |= bfd_getl16 (buffer);
 
148
              extension = 0;
 
149
            }
 
150
          else if (size == 5 && op->opcode == 0xdc000000)
 
151
            {
 
152
              unsigned long temp = 0;
 
153
 
 
154
              status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
 
155
              if (status != 0)
 
156
                {
 
157
                  (*info->memory_error_func) (status, memaddr, info);
 
158
                  return;
 
159
                }
 
160
              temp |= bfd_getl32 (buffer);
 
161
 
 
162
              insn &= 0xff000000;
 
163
              insn |= (temp & 0xffffff00) >> 8;
 
164
              extension = temp & 0xff;
 
165
            }
 
166
          else if (size == 5 && op->format == FMT_D3)
 
167
            {
 
168
              status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
 
169
              if (status != 0)
 
170
                {
 
171
                  (*info->memory_error_func) (status, memaddr, info);
 
172
                  return;
 
173
                }
 
174
              insn &= 0xffff0000;
 
175
              insn |= bfd_getl16 (buffer);
 
176
 
 
177
              status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
 
178
              if (status != 0)
 
179
                {
 
180
                  (*info->memory_error_func) (status, memaddr, info);
 
181
                  return;
 
182
                }
 
183
              extension = *(unsigned char *) buffer;
 
184
            }
 
185
          else if (size == 5)
 
186
            {
 
187
              unsigned long temp = 0;
 
188
 
 
189
              status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
 
190
              if (status != 0)
 
191
                {
 
192
                  (*info->memory_error_func) (status, memaddr, info);
 
193
                  return;
 
194
                }
 
195
              temp |= bfd_getl16 (buffer);
 
196
 
 
197
              insn &= 0xff0000ff;
 
198
              insn |= temp << 8;
 
199
 
 
200
              status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
 
201
              if (status != 0)
 
202
                {
 
203
                  (*info->memory_error_func) (status, memaddr, info);
 
204
                  return;
 
205
                }
 
206
              extension = *(unsigned char *) buffer;
 
207
            }
 
208
          else if (size == 6 && op->format == FMT_D8)
 
209
            {
 
210
              insn &= 0xffffff00;
 
211
              status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
 
212
              if (status != 0)
 
213
                {
 
214
                  (*info->memory_error_func) (status, memaddr, info);
 
215
                  return;
 
216
                }
 
217
              insn |= *(unsigned char *) buffer;
 
218
 
 
219
              status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
 
220
              if (status != 0)
 
221
                {
 
222
                  (*info->memory_error_func) (status, memaddr, info);
 
223
                  return;
 
224
                }
 
225
              extension = bfd_getl16 (buffer);
 
226
            }
 
227
          else if (size == 6)
 
228
            {
 
229
              unsigned long temp = 0;
 
230
 
 
231
              status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
 
232
              if (status != 0)
 
233
                {
 
234
                  (*info->memory_error_func) (status, memaddr, info);
 
235
                  return;
 
236
                }
 
237
              temp |= bfd_getl32 (buffer);
 
238
 
 
239
              insn &= 0xffff0000;
 
240
              insn |= (temp >> 16) & 0xffff;
 
241
              extension = temp & 0xffff;
 
242
            }
 
243
          else if (size == 7 && op->format == FMT_D9)
 
244
            {
 
245
              insn &= 0xffffff00;
 
246
              status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
 
247
              if (status != 0)
 
248
                {
 
249
                  (*info->memory_error_func) (status, memaddr, info);
 
250
                  return;
 
251
                }
 
252
              extension = bfd_getl32 (buffer);
 
253
              insn |= (extension & 0xff000000) >> 24;
 
254
              extension &= 0xffffff;
 
255
            }
 
256
          else if (size == 7 && op->opcode == 0xdd000000)
 
257
            {
 
258
              unsigned long temp = 0;
 
259
 
 
260
              status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
 
261
              if (status != 0)
 
262
                {
 
263
                  (*info->memory_error_func) (status, memaddr, info);
 
264
                  return;
 
265
                }
 
266
              temp |= bfd_getl32 (buffer);
 
267
 
 
268
              insn &= 0xff000000;
 
269
              insn |= (temp >> 8) & 0xffffff;
 
270
              extension = (temp & 0xff) << 16;
 
271
 
 
272
              status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
 
273
              if (status != 0)
 
274
                {
 
275
                  (*info->memory_error_func) (status, memaddr, info);
 
276
                  return;
 
277
                }
 
278
              extension |= bfd_getb16 (buffer);
 
279
            }
 
280
          else if (size == 7)
 
281
            {
 
282
              unsigned long temp = 0;
 
283
 
 
284
              status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
 
285
              if (status != 0)
 
286
                {
 
287
                  (*info->memory_error_func) (status, memaddr, info);
 
288
                  return;
 
289
                }
 
290
              temp |= bfd_getl32 (buffer);
 
291
 
 
292
              insn &= 0xffff0000;
 
293
              insn |= (temp >> 16) & 0xffff;
 
294
              extension = (temp & 0xffff) << 8;
 
295
 
 
296
              status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
 
297
              if (status != 0)
 
298
                {
 
299
                  (*info->memory_error_func) (status, memaddr, info);
 
300
                  return;
 
301
                }
 
302
              extension |= *(unsigned char *) buffer;
 
303
            }
 
304
 
 
305
          match = 1;
 
306
          (*info->fprintf_func) (info->stream, "%s\t", op->name);
 
307
 
 
308
          /* Now print the operands.  */
 
309
          for (opindex_ptr = op->operands, nocomma = 1;
 
310
               *opindex_ptr != 0;
 
311
               opindex_ptr++)
 
312
            {
 
313
              unsigned long value;
 
314
 
 
315
              operand = &mn10300_operands[*opindex_ptr];
 
316
 
 
317
              /* If this operand is a PLUS (autoincrement), then do not emit
 
318
                 a comma before emitting the plus.  */
 
319
              if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
 
320
                nocomma = 1;
 
321
 
 
322
              if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
 
323
                {
 
324
                  unsigned long temp;
 
325
 
 
326
                  value = insn & ((1 << operand->bits) - 1);
 
327
                  value <<= (32 - operand->bits);
 
328
                  temp = extension >> operand->shift;
 
329
                  temp &= ((1 << (32 - operand->bits)) - 1);
 
330
                  value |= temp;
 
331
                  value = ((value ^ (((unsigned long) 1) << 31))
 
332
                           - (((unsigned long) 1) << 31));
 
333
                }
 
334
              else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
 
335
                {
 
336
                  unsigned long temp;
 
337
 
 
338
                  value = insn & ((1 << operand->bits) - 1);
 
339
                  value <<= (24 - operand->bits);
 
340
                  temp = extension >> operand->shift;
 
341
                  temp &= ((1 << (24 - operand->bits)) - 1);
 
342
                  value |= temp;
 
343
                  if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
 
344
                    value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
 
345
                }
 
346
              else if ((operand->flags & (MN10300_OPERAND_FSREG
 
347
                                          | MN10300_OPERAND_FDREG)))
 
348
                {
 
349
                  /* See m10300-opc.c just before #define FSM0 for an
 
350
                     explanation of these variables.  Note that
 
351
                     FMT-implied shifts are not taken into account for
 
352
                     FP registers.  */
 
353
                  unsigned long mask_low, mask_high;
 
354
                  int shl_low, shr_high, shl_high;
 
355
 
 
356
                  switch (operand->bits)
 
357
                    {
 
358
                    case 5:
 
359
                      /* Handle regular FP registers.  */
 
360
                      if (operand->shift >= 0)
 
361
                        {
 
362
                          /* This is an `m' register.  */
 
363
                          shl_low = operand->shift;
 
364
                          shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
 
365
                        }
 
366
                      else
 
367
                        {
 
368
                          /* This is an `n' register.  */
 
369
                          shl_low = -operand->shift;
 
370
                          shl_high = shl_low / 4;
 
371
                        }
 
372
                      mask_low = 0x0f;
 
373
                      mask_high = 0x10;
 
374
                      shr_high = 4;
 
375
                      break;
 
376
 
 
377
                    case 3:
 
378
                      /* Handle accumulators.  */
 
379
                      shl_low = -operand->shift;
 
380
                      shl_high = 0;
 
381
                      mask_low = 0x03;
 
382
                      mask_high = 0x04;
 
383
                      shr_high = 2;
 
384
                      break;
 
385
 
 
386
                    default:
 
387
                      abort ();
 
388
                    }
 
389
                  value = ((((insn >> shl_high) << shr_high) & mask_high)
 
390
                           | ((insn >> shl_low) & mask_low));
 
391
                }
 
392
              else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
 
393
                value = ((extension >> (operand->shift))
 
394
                         & ((1 << operand->bits) - 1));
 
395
 
 
396
              else
 
397
                value = ((insn >> (operand->shift))
 
398
                         & ((1 << operand->bits) - 1));
 
399
 
 
400
              if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
 
401
                  /* These are properly extended by the code above.  */
 
402
                  && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
 
403
                value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
 
404
                         - (((unsigned long) 1) << (operand->bits - 1)));
 
405
 
 
406
              if (!nocomma
 
407
                  && (!paren
 
408
                      || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
 
409
                (*info->fprintf_func) (info->stream, ",");
 
410
 
 
411
              nocomma = 0;
 
412
 
 
413
              if ((operand->flags & MN10300_OPERAND_DREG) != 0)
 
414
                {
 
415
                  value = ((insn >> (operand->shift + extra_shift))
 
416
                           & ((1 << operand->bits) - 1));
 
417
                  (*info->fprintf_func) (info->stream, "d%d", (int) value);
 
418
                }
 
419
 
 
420
              else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
 
421
                {
 
422
                  value = ((insn >> (operand->shift + extra_shift))
 
423
                           & ((1 << operand->bits) - 1));
 
424
                  (*info->fprintf_func) (info->stream, "a%d", (int) value);
 
425
                }
 
426
 
 
427
              else if ((operand->flags & MN10300_OPERAND_SP) != 0)
 
428
                (*info->fprintf_func) (info->stream, "sp");
 
429
 
 
430
              else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
 
431
                (*info->fprintf_func) (info->stream, "psw");
 
432
 
 
433
              else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
 
434
                (*info->fprintf_func) (info->stream, "mdr");
 
435
 
 
436
              else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
 
437
                {
 
438
                  value = ((insn >> (operand->shift + extra_shift))
 
439
                           & ((1 << operand->bits) - 1));
 
440
                  if (value < 8)
 
441
                    (*info->fprintf_func) (info->stream, "r%d", (int) value);
 
442
                  else if (value < 12)
 
443
                    (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
 
444
                  else
 
445
                    (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
 
446
                }
 
447
 
 
448
              else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
 
449
                {
 
450
                  value = ((insn >> (operand->shift + extra_shift))
 
451
                           & ((1 << operand->bits) - 1));
 
452
                  if (value == 0)
 
453
                    (*info->fprintf_func) (info->stream, "sp");
 
454
                  else
 
455
                    (*info->fprintf_func) (info->stream, "xr%d", (int) value);
 
456
                }
 
457
 
 
458
              else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
 
459
                (*info->fprintf_func) (info->stream, "fs%d", (int) value);
 
460
 
 
461
              else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
 
462
                (*info->fprintf_func) (info->stream, "fd%d", (int) value);
 
463
 
 
464
              else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
 
465
                (*info->fprintf_func) (info->stream, "fpcr");
 
466
 
 
467
              else if ((operand->flags & MN10300_OPERAND_USP) != 0)
 
468
                (*info->fprintf_func) (info->stream, "usp");
 
469
 
 
470
              else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
 
471
                (*info->fprintf_func) (info->stream, "ssp");
 
472
 
 
473
              else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
 
474
                (*info->fprintf_func) (info->stream, "msp");
 
475
 
 
476
              else if ((operand->flags & MN10300_OPERAND_PC) != 0)
 
477
                (*info->fprintf_func) (info->stream, "pc");
 
478
 
 
479
              else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
 
480
                (*info->fprintf_func) (info->stream, "epsw");
 
481
 
 
482
              else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
 
483
                (*info->fprintf_func) (info->stream, "+");
 
484
 
 
485
              else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
 
486
                {
 
487
                  if (paren)
 
488
                    (*info->fprintf_func) (info->stream, ")");
 
489
                  else
 
490
                    {
 
491
                      (*info->fprintf_func) (info->stream, "(");
 
492
                      nocomma = 1;
 
493
                    }
 
494
                  paren = !paren;
 
495
                }
 
496
 
 
497
              else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
 
498
                (*info->print_address_func) ((long) value + memaddr, info);
 
499
 
 
500
              else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
 
501
                (*info->print_address_func) (value, info);
 
502
 
 
503
              else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
 
504
                {
 
505
                  int comma = 0;
 
506
 
 
507
                  (*info->fprintf_func) (info->stream, "[");
 
508
                  if (value & 0x80)
 
509
                    {
 
510
                      (*info->fprintf_func) (info->stream, "d2");
 
511
                      comma = 1;
 
512
                    }
 
513
 
 
514
                  if (value & 0x40)
 
515
                    {
 
516
                      if (comma)
 
517
                        (*info->fprintf_func) (info->stream, ",");
 
518
                      (*info->fprintf_func) (info->stream, "d3");
 
519
                      comma = 1;
 
520
                    }
 
521
 
 
522
                  if (value & 0x20)
 
523
                    {
 
524
                      if (comma)
 
525
                        (*info->fprintf_func) (info->stream, ",");
 
526
                      (*info->fprintf_func) (info->stream, "a2");
 
527
                      comma = 1;
 
528
                    }
 
529
 
 
530
                  if (value & 0x10)
 
531
                    {
 
532
                      if (comma)
 
533
                        (*info->fprintf_func) (info->stream, ",");
 
534
                      (*info->fprintf_func) (info->stream, "a3");
 
535
                      comma = 1;
 
536
                    }
 
537
 
 
538
                  if (value & 0x08)
 
539
                    {
 
540
                      if (comma)
 
541
                        (*info->fprintf_func) (info->stream, ",");
 
542
                      (*info->fprintf_func) (info->stream, "other");
 
543
                      comma = 1;
 
544
                    }
 
545
 
 
546
                  if (value & 0x04)
 
547
                    {
 
548
                      if (comma)
 
549
                        (*info->fprintf_func) (info->stream, ",");
 
550
                      (*info->fprintf_func) (info->stream, "exreg0");
 
551
                      comma = 1;
 
552
                    }
 
553
                  if (value & 0x02)
 
554
                    {
 
555
                      if (comma)
 
556
                        (*info->fprintf_func) (info->stream, ",");
 
557
                      (*info->fprintf_func) (info->stream, "exreg1");
 
558
                      comma = 1;
 
559
                    }
 
560
                  if (value & 0x01)
 
561
                    {
 
562
                      if (comma)
 
563
                        (*info->fprintf_func) (info->stream, ",");
 
564
                      (*info->fprintf_func) (info->stream, "exother");
 
565
                      comma = 1;
 
566
                    }
 
567
                  (*info->fprintf_func) (info->stream, "]");
 
568
                }
 
569
 
 
570
              else
 
571
                (*info->fprintf_func) (info->stream, "%ld", (long) value);
 
572
            }
 
573
          /* All done. */
 
574
          break;
 
575
        }
 
576
      op++;
 
577
    }
 
578
 
 
579
  if (!match)
 
580
    /* xgettext:c-format */
 
581
    (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
 
582
}
 
583
 
 
584
int
 
585
print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
 
586
{
 
587
  int status;
 
588
  bfd_byte buffer[4];
 
589
  unsigned long insn;
 
590
  unsigned int consume;
 
591
 
 
592
  /* First figure out how big the opcode is.  */
 
593
  status = (*info->read_memory_func) (memaddr, buffer, 1, info);
 
594
  if (status != 0)
 
595
    {
 
596
      (*info->memory_error_func) (status, memaddr, info);
 
597
      return -1;
 
598
    }
 
599
  insn = *(unsigned char *) buffer;
 
600
 
 
601
  /* These are one byte insns.  */
 
602
  if ((insn & 0xf3) == 0x00
 
603
      || (insn & 0xf0) == 0x10
 
604
      || (insn & 0xfc) == 0x3c
 
605
      || (insn & 0xf3) == 0x41
 
606
      || (insn & 0xf3) == 0x40
 
607
      || (insn & 0xfc) == 0x50
 
608
      || (insn & 0xfc) == 0x54
 
609
      || (insn & 0xf0) == 0x60
 
610
      || (insn & 0xf0) == 0x70
 
611
      || ((insn & 0xf0) == 0x80
 
612
          && (insn & 0x0c) >> 2 != (insn & 0x03))
 
613
      || ((insn & 0xf0) == 0x90
 
614
          && (insn & 0x0c) >> 2 != (insn & 0x03))
 
615
      || ((insn & 0xf0) == 0xa0
 
616
          && (insn & 0x0c) >> 2 != (insn & 0x03))
 
617
      || ((insn & 0xf0) == 0xb0
 
618
          && (insn & 0x0c) >> 2 != (insn & 0x03))
 
619
      || (insn & 0xff) == 0xcb
 
620
      || (insn & 0xfc) == 0xd0
 
621
      || (insn & 0xfc) == 0xd4
 
622
      || (insn & 0xfc) == 0xd8
 
623
      || (insn & 0xf0) == 0xe0
 
624
      || (insn & 0xff) == 0xff)
 
625
    {
 
626
      consume = 1;
 
627
    }
 
628
 
 
629
  /* These are two byte insns.  */
 
630
  else if ((insn & 0xf0) == 0x80
 
631
           || (insn & 0xf0) == 0x90
 
632
           || (insn & 0xf0) == 0xa0
 
633
           || (insn & 0xf0) == 0xb0
 
634
           || (insn & 0xfc) == 0x20
 
635
           || (insn & 0xfc) == 0x28
 
636
           || (insn & 0xf3) == 0x43
 
637
           || (insn & 0xf3) == 0x42
 
638
           || (insn & 0xfc) == 0x58
 
639
           || (insn & 0xfc) == 0x5c
 
640
           || ((insn & 0xf0) == 0xc0
 
641
               && (insn & 0xff) != 0xcb
 
642
               && (insn & 0xff) != 0xcc
 
643
               && (insn & 0xff) != 0xcd)
 
644
           || (insn & 0xff) == 0xf0
 
645
           || (insn & 0xff) == 0xf1
 
646
           || (insn & 0xff) == 0xf2
 
647
           || (insn & 0xff) == 0xf3
 
648
           || (insn & 0xff) == 0xf4
 
649
           || (insn & 0xff) == 0xf5
 
650
           || (insn & 0xff) == 0xf6)
 
651
    {
 
652
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
 
653
      if (status != 0)
 
654
        {
 
655
          (*info->memory_error_func) (status, memaddr, info);
 
656
          return -1;
 
657
        }
 
658
      insn = bfd_getb16 (buffer);
 
659
      consume = 2;
 
660
    }
 
661
 
 
662
  /* These are three byte insns.  */
 
663
  else if ((insn & 0xff) == 0xf8
 
664
           || (insn & 0xff) == 0xcc
 
665
           || (insn & 0xff) == 0xf9
 
666
           || (insn & 0xf3) == 0x01
 
667
           || (insn & 0xf3) == 0x02
 
668
           || (insn & 0xf3) == 0x03
 
669
           || (insn & 0xfc) == 0x24
 
670
           || (insn & 0xfc) == 0x2c
 
671
           || (insn & 0xfc) == 0x30
 
672
           || (insn & 0xfc) == 0x34
 
673
           || (insn & 0xfc) == 0x38
 
674
           || (insn & 0xff) == 0xde
 
675
           || (insn & 0xff) == 0xdf
 
676
           || (insn & 0xff) == 0xf9
 
677
           || (insn & 0xff) == 0xcc)
 
678
    {
 
679
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
 
680
      if (status != 0)
 
681
        {
 
682
          (*info->memory_error_func) (status, memaddr, info);
 
683
          return -1;
 
684
        }
 
685
      insn = bfd_getb16 (buffer);
 
686
      insn <<= 8;
 
687
      status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
 
688
      if (status != 0)
 
689
        {
 
690
          (*info->memory_error_func) (status, memaddr, info);
 
691
          return -1;
 
692
        }
 
693
      insn |= *(unsigned char *) buffer;
 
694
      consume = 3;
 
695
    }
 
696
 
 
697
  /* These are four byte insns.  */
 
698
  else if ((insn & 0xff) == 0xfa
 
699
           || (insn & 0xff) == 0xf7
 
700
           || (insn & 0xff) == 0xfb)
 
701
    {
 
702
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
 
703
      if (status != 0)
 
704
        {
 
705
          (*info->memory_error_func) (status, memaddr, info);
 
706
          return -1;
 
707
        }
 
708
      insn = bfd_getb32 (buffer);
 
709
      consume = 4;
 
710
    }
 
711
 
 
712
  /* These are five byte insns.  */
 
713
  else if ((insn & 0xff) == 0xcd
 
714
           || (insn & 0xff) == 0xdc)
 
715
    {
 
716
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
 
717
      if (status != 0)
 
718
        {
 
719
          (*info->memory_error_func) (status, memaddr, info);
 
720
          return -1;
 
721
        }
 
722
      insn = bfd_getb32 (buffer);
 
723
      consume = 5;
 
724
    }
 
725
 
 
726
  /* These are six byte insns.  */
 
727
  else if ((insn & 0xff) == 0xfd
 
728
           || (insn & 0xff) == 0xfc)
 
729
    {
 
730
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
 
731
      if (status != 0)
 
732
        {
 
733
          (*info->memory_error_func) (status, memaddr, info);
 
734
          return -1;
 
735
        }
 
736
 
 
737
      insn = bfd_getb32 (buffer);
 
738
      consume = 6;
 
739
    }
 
740
 
 
741
  /* Else its a seven byte insns (in theory).  */
 
742
  else
 
743
    {
 
744
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
 
745
      if (status != 0)
 
746
        {
 
747
          (*info->memory_error_func) (status, memaddr, info);
 
748
          return -1;
 
749
        }
 
750
 
 
751
      insn = bfd_getb32 (buffer);
 
752
      consume = 7;
 
753
      /* Handle the 5-byte extended instruction codes.  */
 
754
      if ((insn & 0xfff80000) == 0xfe800000)
 
755
        consume = 5;
 
756
    }
 
757
 
 
758
  disassemble (memaddr, info, insn, consume);
 
759
 
 
760
  return consume;
 
761
}