Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/opcodes/msp430-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* Disassemble MSP430 instructions.
2
   Copyright (C) 2002-2023 Free Software Foundation, Inc.
3
4
   Contributed by Dmitry Diky <diwil@mail.ru>
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 <stdio.h>
25
#include <ctype.h>
26
#include <sys/types.h>
27
#include <errno.h>
28
29
#include "disassemble.h"
30
#include "opintl.h"
31
#include "libiberty.h"
32
33
#define DASM_SECTION
34
#include "opcode/msp430.h"
35
#undef DASM_SECTION
36
37
38
97.0k
#define PS(x)   (0xffff & (x))
39
40
static bool
41
msp430dis_read_two_bytes (bfd_vma            addr,
42
        disassemble_info * info,
43
        bfd_byte *         buffer,
44
        char *             comm)
45
383k
{
46
383k
  int status;
47
48
383k
  status = info->read_memory_func (addr, buffer, 2, info);
49
383k
  if (status == 0)
50
383k
    return true;
51
52
  /* PR 20150: A status of EIO means that there were no more bytes left
53
     to read in the current section.  This can happen when disassembling
54
     interrupt vectors for example.  Avoid cluttering the output with
55
     unhelpful error messages in this case.  */
56
155
  if (status == EIO)
57
155
    {
58
155
      if (comm)
59
87
  sprintf (comm, _("Warning: disassembly unreliable - not enough bytes available"));
60
155
    }
61
0
  else
62
0
    {
63
0
      info->memory_error_func (status, addr, info);
64
0
      if (comm)
65
0
  sprintf (comm, _("Error: read from memory failed"));
66
0
    }
67
68
155
  return false;
69
383k
}
70
71
static bool
72
msp430dis_opcode_unsigned (bfd_vma            addr,
73
         disassemble_info * info,
74
         unsigned short *   return_val,
75
         char *             comm)
76
279k
{
77
279k
  bfd_byte buffer[2];
78
79
279k
  if (msp430dis_read_two_bytes (addr, info, buffer, comm))
80
279k
    {
81
279k
      * return_val = bfd_getl16 (buffer);
82
279k
      return true;
83
279k
    }
84
82
  else
85
82
    {
86
82
      * return_val = 0;
87
82
      return false;
88
82
    }
89
279k
}
90
91
static bool
92
msp430dis_opcode_signed (bfd_vma            addr,
93
       disassemble_info * info,
94
       signed int *       return_val,
95
       char *             comm)
96
103k
{
97
103k
  bfd_byte buffer[2];
98
99
103k
  if (msp430dis_read_two_bytes (addr, info, buffer, comm))
100
103k
    {
101
103k
      int status;
102
103
103k
      status = bfd_getl_signed_16 (buffer);
104
103k
      if (status & 0x8000)
105
54.2k
  status |= -1U << 16;
106
103k
      * return_val = status;
107
103k
      return true;
108
103k
    }
109
73
  else
110
73
    {
111
73
      * return_val = 0;
112
73
      return false;
113
73
    }
114
103k
}
115
116
static int
117
msp430_nooperands (struct msp430_opcode_s *opcode,
118
       bfd_vma addr ATTRIBUTE_UNUSED,
119
       unsigned short insn ATTRIBUTE_UNUSED,
120
       char *comm,
121
       int *cycles)
122
31.7k
{
123
  /* Pop with constant.  */
124
31.7k
  if (insn == 0x43b2)
125
0
    return 0;
126
31.7k
  if (insn == opcode->bin_opcode)
127
30.9k
    return 2;
128
129
789
  if (opcode->fmt == 0)
130
422
    {
131
422
      if ((insn & 0x0f00) != 0x0300 || (insn & 0x0f00) != 0x0200)
132
422
  return 0;
133
134
0
      strcpy (comm, "emulated...");
135
0
      *cycles = 1;
136
0
    }
137
367
  else
138
367
    {
139
367
      strcpy (comm, "return from interupt");
140
367
      *cycles = 5;
141
367
    }
142
143
367
  return 2;
144
789
}
145
146
static int
147
print_as2_reg_name (int regno, char * op1, char * comm1,
148
        int c2, int c3, int cd)
149
24.7k
{
150
24.7k
  switch (regno)
151
24.7k
    {
152
2.16k
    case 2:
153
2.16k
      sprintf (op1, "#4");
154
2.16k
      sprintf (comm1, "r2 As==10");
155
2.16k
      return c2;
156
157
3.49k
    case 3:
158
3.49k
      sprintf (op1, "#2");
159
3.49k
      sprintf (comm1, "r3 As==10");
160
3.49k
      return c3;
161
162
19.1k
    default:
163
      /* Indexed register mode @Rn.  */
164
19.1k
      sprintf (op1, "@r%d", regno);
165
19.1k
      return cd;
166
24.7k
    }
167
24.7k
}
168
169
static int
170
print_as3_reg_name (int regno, char * op1, char * comm1,
171
        int c2, int c3, int cd)
172
36.4k
{
173
36.4k
  switch (regno)
174
36.4k
    {
175
3.09k
    case 2:
176
3.09k
      sprintf (op1, "#8");
177
3.09k
      sprintf (comm1, "r2 As==11");
178
3.09k
      return c2;
179
180
1.69k
    case 3:
181
1.69k
      sprintf (op1, "#-1");
182
1.69k
      sprintf (comm1, "r3 As==11");
183
1.69k
      return c3;
184
185
31.6k
    default:
186
      /* Post incremented @Rn+.  */
187
31.6k
      sprintf (op1, "@r%d+", regno);
188
31.6k
      return cd;
189
36.4k
    }
190
36.4k
}
191
192
static int
193
msp430_singleoperand (disassemble_info *info,
194
          struct msp430_opcode_s *opcode,
195
          bfd_vma addr,
196
          unsigned short insn,
197
          char *op,
198
          char *comm,
199
          unsigned short extension_word,
200
          int *cycles)
201
43.1k
{
202
43.1k
  int regs = 0, regd = 0;
203
43.1k
  int ad = 0, as = 0;
204
43.1k
  int where = 0;
205
43.1k
  int cmd_len = 2;
206
43.1k
  int dst = 0;
207
43.1k
  int fmt;
208
43.1k
  int extended_dst = extension_word & 0xf;
209
210
43.1k
  regd = insn & 0x0f;
211
43.1k
  regs = (insn & 0x0f00) >> 8;
212
43.1k
  as = (insn & 0x0030) >> 4;
213
43.1k
  ad = (insn & 0x0080) >> 7;
214
215
43.1k
  if (opcode->fmt < 0)
216
0
    fmt = (- opcode->fmt) - 1;
217
43.1k
  else
218
43.1k
    fmt = opcode->fmt;
219
220
43.1k
  switch (fmt)
221
43.1k
    {
222
1.47k
    case 0:     /* Emulated work with dst register.  */
223
1.47k
      if (regs != 2 && regs != 3 && regs != 1)
224
0
  return 0;
225
226
      /* Check if not clr insn.  */
227
1.47k
      if (opcode->bin_opcode == 0x4300 && (ad || as))
228
7
  return 0;
229
230
      /* Check if really inc, incd insns.  */
231
1.46k
      if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
232
0
  return 0;
233
234
1.46k
      if (ad == 0)
235
897
  {
236
897
    *cycles = 1;
237
238
    /* Register.  */
239
897
    if (regd == 0)
240
361
      {
241
361
        *cycles += 1;
242
361
        sprintf (op, "r0");
243
361
      }
244
536
    else if (regd == 1)
245
83
      sprintf (op, "r1");
246
247
453
    else if (regd == 2)
248
43
      sprintf (op, "r2");
249
250
410
    else
251
410
      sprintf (op, "r%d", regd);
252
897
  }
253
567
      else  /* ad == 1 msp430dis_opcode.  */
254
567
  {
255
567
    if (regd == 0)
256
66
      {
257
        /* PC relative.  */
258
66
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
259
66
    {
260
66
      cmd_len += 2;
261
66
      *cycles = 4;
262
66
      sprintf (op, "0x%04x", dst);
263
66
      sprintf (comm, "PC rel. abs addr 0x%04x",
264
66
         PS ((short) (addr + 2) + dst));
265
66
      if (extended_dst)
266
0
        {
267
0
          dst |= extended_dst << 16;
268
0
          sprintf (op, "0x%05x", dst);
269
0
          sprintf (comm, "PC rel. abs addr 0x%05lx",
270
0
             (long)((addr + 2 + dst) & 0xfffff));
271
0
        }
272
66
    }
273
0
        else
274
0
    return -1;
275
66
      }
276
501
    else if (regd == 2)
277
82
      {
278
        /* Absolute.  */
279
82
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
280
82
    {
281
82
      cmd_len += 2;
282
82
      *cycles = 4;
283
82
      sprintf (op, "&0x%04x", PS (dst));
284
82
      if (extended_dst)
285
0
        {
286
0
          dst |= extended_dst << 16;
287
0
          sprintf (op, "&0x%05x", dst & 0xfffff);
288
0
        }
289
82
    }
290
0
        else
291
0
    return -1;
292
82
      }
293
419
    else
294
419
      {
295
419
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
296
418
    {
297
418
      cmd_len += 2;
298
418
      *cycles = 4;
299
418
      if (extended_dst)
300
14
        {
301
14
          dst |= extended_dst << 16;
302
14
          if (dst & 0x80000)
303
13
      dst |= -1U << 20;
304
14
        }
305
418
      sprintf (op, "%d(r%d)", dst, regd);
306
418
    }
307
1
        else
308
1
    return -1;
309
419
      }
310
567
  }
311
1.46k
      break;
312
313
11.1k
    case 2: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc...  */
314
11.1k
      if (as == 0)
315
2.21k
  {
316
2.21k
    if (regd == 3)
317
65
      {
318
        /* Constsnts.  */
319
65
        sprintf (op, "#0");
320
65
        sprintf (comm, "r3 As==00");
321
65
      }
322
2.15k
    else
323
2.15k
      {
324
        /* Register.  */
325
2.15k
        sprintf (op, "r%d", regd);
326
2.15k
      }
327
2.21k
    *cycles = 1;
328
2.21k
  }
329
8.90k
      else if (as == 2)
330
719
  {
331
719
    * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
332
719
  }
333
8.18k
      else if (as == 3)
334
2.64k
  {
335
2.64k
    if (regd == 0)
336
1.02k
      {
337
1.02k
        *cycles = 3;
338
        /* absolute. @pc+ */
339
1.02k
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
340
1.02k
    {
341
1.02k
      cmd_len += 2;
342
1.02k
      sprintf (op, "#%d", dst);
343
1.02k
      if (dst > 9 || dst < 0)
344
840
        sprintf (comm, "#0x%04x", PS (dst));
345
1.02k
      if (extended_dst)
346
193
        {
347
193
          dst |= extended_dst << 16;
348
193
          if (dst & 0x80000)
349
117
      dst |= -1U << 20;
350
193
          sprintf (op, "#%d", dst);
351
193
          if (dst > 9 || dst < 0)
352
193
      sprintf (comm, "#0x%05x", dst);
353
193
        }
354
1.02k
    }
355
1
        else
356
1
    return -1;
357
1.02k
      }
358
1.62k
    else
359
1.62k
      * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
360
2.64k
  }
361
5.53k
      else if (as == 1)
362
5.53k
  {
363
5.53k
    *cycles = 4;
364
5.53k
    if (regd == 0)
365
923
      {
366
        /* PC relative.  */
367
923
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
368
922
    {
369
922
      cmd_len += 2;
370
922
      sprintf (op, "0x%04x", PS (dst));
371
922
      sprintf (comm, "PC rel. 0x%04x",
372
922
         PS ((short) addr + 2 + dst));
373
922
      if (extended_dst)
374
745
        {
375
745
          dst |= extended_dst << 16;
376
745
          sprintf (op, "0x%05x", dst & 0xffff);
377
745
          sprintf (comm, "PC rel. 0x%05lx",
378
745
             (long)((addr + 2 + dst) & 0xfffff));
379
745
        }
380
922
    }
381
1
        else
382
1
    return -1;
383
923
      }
384
4.61k
    else if (regd == 2)
385
330
      {
386
        /* Absolute.  */
387
330
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
388
329
    {
389
329
      cmd_len += 2;
390
329
      sprintf (op, "&0x%04x", PS (dst));
391
329
      if (extended_dst)
392
41
        {
393
41
          dst |= extended_dst << 16;
394
41
          sprintf (op, "&0x%05x", dst & 0xfffff);
395
41
        }
396
329
    }
397
1
        else
398
1
    return -1;
399
330
      }
400
4.28k
    else if (regd == 3)
401
1.06k
      {
402
1.06k
        *cycles = 1;
403
1.06k
        sprintf (op, "#1");
404
1.06k
        sprintf (comm, "r3 As==01");
405
1.06k
      }
406
3.21k
    else
407
3.21k
      {
408
        /* Indexed.  */
409
3.21k
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
410
3.20k
    {
411
3.20k
      cmd_len += 2;
412
3.20k
      if (extended_dst)
413
201
        {
414
201
          dst |= extended_dst << 16;
415
201
          if (dst & 0x80000)
416
196
      dst |= -1U << 20;
417
201
        }
418
3.20k
      sprintf (op, "%d(r%d)", dst, regd);
419
3.20k
      if (dst > 9 || dst < 0)
420
3.09k
        sprintf (comm, "%05x", dst);
421
3.20k
    }
422
8
        else
423
8
    return -1;
424
3.21k
      }
425
5.53k
  }
426
11.1k
      break;
427
428
30.5k
    case 3:     /* Jumps.  */
429
30.5k
      where = insn & 0x03ff;
430
30.5k
      if (where & 0x200)
431
17.1k
  where |= ~0x03ff;
432
30.5k
      if (where > 512 || where < -511)
433
796
  return 0;
434
435
29.7k
      where *= 2;
436
29.7k
      sprintf (op, "$%+-8d", where + 2);
437
29.7k
      sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
438
29.7k
      *cycles = 2;
439
29.7k
      return 2;
440
0
      break;
441
442
0
    default:
443
0
      cmd_len = 0;
444
43.1k
    }
445
446
12.5k
  return cmd_len;
447
43.1k
}
448
449
static int
450
msp430_doubleoperand (disassemble_info *info,
451
          struct msp430_opcode_s *opcode,
452
          bfd_vma addr,
453
          unsigned short insn,
454
          char *op1,
455
          char *op2,
456
          char *comm1,
457
          char *comm2,
458
          unsigned short extension_word,
459
          int *cycles)
460
150k
{
461
150k
  int regs = 0, regd = 0;
462
150k
  int ad = 0, as = 0;
463
150k
  int cmd_len = 2;
464
150k
  int dst = 0;
465
150k
  int fmt;
466
150k
  int extended_dst = extension_word & 0xf;
467
150k
  int extended_src = (extension_word >> 7) & 0xf;
468
469
150k
  regd = insn & 0x0f;
470
150k
  regs = (insn & 0x0f00) >> 8;
471
150k
  as = (insn & 0x0030) >> 4;
472
150k
  ad = (insn & 0x0080) >> 7;
473
474
150k
  if (opcode->fmt < 0)
475
0
    fmt = (- opcode->fmt) - 1;
476
150k
  else
477
150k
    fmt = opcode->fmt;
478
479
150k
  if (fmt == 0)
480
24.6k
    {
481
      /* Special case: rla and rlc are the only 2 emulated instructions that
482
   fall into two operand instructions.  */
483
      /* With dst, there are only:
484
   Rm         Register,
485
         x(Rm)      Indexed,
486
         0xXXXX     Relative,
487
         &0xXXXX      Absolute
488
         emulated_ins   dst
489
         basic_ins      dst, dst.  */
490
491
24.6k
      if (regd != regs || as != ad)
492
23.2k
  return 0;    /* May be 'data' section.  */
493
494
1.33k
      if (ad == 0)
495
392
  {
496
    /* Register mode.  */
497
392
    if (regd == 3)
498
1
      {
499
1
        strcpy (comm1, _("Warning: illegal as emulation instr"));
500
1
        return -1;
501
1
      }
502
503
391
    sprintf (op1, "r%d", regd);
504
391
    *cycles = 1;
505
391
  }
506
942
      else      /* ad == 1 */
507
942
  {
508
942
    if (regd == 0)
509
206
      {
510
        /* PC relative, Symbolic.  */
511
206
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
512
206
    {
513
206
      cmd_len += 4;
514
206
      *cycles = 6;
515
206
      sprintf (op1, "0x%04x", PS (dst));
516
206
      sprintf (comm1, "PC rel. 0x%04x",
517
206
         PS ((short) addr + 2 + dst));
518
206
      if (extension_word)
519
169
        {
520
169
          dst |= extended_dst << 16;
521
169
          if (dst & 0x80000)
522
17
      dst |= -1U << 20;
523
169
          sprintf (op1, "0x%05x", dst & 0xfffff);
524
169
          sprintf (comm1, "PC rel. 0x%05lx",
525
169
             (long)((addr + 2 + dst) & 0xfffff));
526
169
        }
527
206
    }
528
0
        else
529
0
    return -1;
530
206
      }
531
736
    else if (regd == 2)
532
583
      {
533
        /* Absolute.  */
534
583
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
535
583
    {
536
583
      int src;
537
538
      /* If the 'src' field is not the same as the dst
539
         then this is not an rla instruction.  */
540
583
      if (msp430dis_opcode_signed (addr + 4, info, &src, comm2))
541
583
        {
542
583
          if (src != dst)
543
354
      return 0;
544
583
        }
545
0
      else
546
0
        return -1;
547
229
      cmd_len += 4;
548
229
      *cycles = 6;
549
229
      sprintf (op1, "&0x%04x", PS (dst));
550
229
      if (extension_word)
551
152
        {
552
152
          dst |= extended_dst << 16;
553
152
          sprintf (op1, "&0x%05x", dst & 0xfffff);
554
152
        }
555
229
    }
556
0
        else
557
0
    return -1;
558
583
      }
559
153
    else
560
153
      {
561
        /* Indexed.  */
562
153
        if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
563
153
    {
564
153
      if (extension_word)
565
30
        {
566
30
          dst |= extended_dst << 16;
567
30
          if (dst & 0x80000)
568
3
      dst |= -1U << 20;
569
30
        }
570
153
      cmd_len += 4;
571
153
      *cycles = 6;
572
153
      sprintf (op1, "%d(r%d)", dst, regd);
573
153
      if (dst > 9 || dst < -9)
574
138
        sprintf (comm1, "#0x%05x", dst);
575
153
    }
576
0
        else
577
0
    return -1;
578
153
      }
579
942
  }
580
581
979
      *op2 = 0;
582
979
      *comm2 = 0;
583
584
979
      return cmd_len;
585
1.33k
    }
586
587
  /* Two operands exactly.  */
588
125k
  if (ad == 0 && regd == 3)
589
100
    {
590
      /* R2/R3 are illegal as dest: may be data section.  */
591
100
      strcpy (comm1, _("Warning: illegal as 2-op instr"));
592
100
      return -1;
593
100
    }
594
595
  /* Source.  */
596
125k
  if (as == 0)
597
33.0k
    {
598
33.0k
      *cycles = 1;
599
33.0k
      if (regs == 3)
600
2.15k
  {
601
    /* Constants.  */
602
2.15k
    sprintf (op1, "#0");
603
2.15k
    sprintf (comm1, "r3 As==00");
604
2.15k
  }
605
30.9k
      else
606
30.9k
  {
607
    /* Register.  */
608
30.9k
    sprintf (op1, "r%d", regs);
609
30.9k
  }
610
33.0k
    }
611
92.6k
  else if (as == 2)
612
23.8k
    {
613
23.8k
      * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
614
23.8k
    }
615
68.8k
  else if (as == 3)
616
36.4k
    {
617
36.4k
      if (regs == 0)
618
2.26k
  {
619
2.26k
    *cycles = 3;
620
    /* Absolute. @pc+.  */
621
2.26k
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
622
2.25k
      {
623
2.25k
        cmd_len += 2;
624
2.25k
        sprintf (op1, "#%d", dst);
625
2.25k
        if (dst > 9 || dst < 0)
626
1.96k
    sprintf (comm1, "#0x%04x", PS (dst));
627
2.25k
        if (extension_word)
628
393
    {
629
393
      dst &= 0xffff;
630
393
      dst |= extended_src << 16;
631
393
      if (dst & 0x80000)
632
20
        dst |= -1U << 20;
633
393
      sprintf (op1, "#%d", dst);
634
393
      if (dst > 9 || dst < 0)
635
116
        sprintf (comm1, "0x%05x", dst & 0xfffff);
636
393
    }
637
2.25k
      }
638
1
    else
639
1
      return -1;
640
2.26k
  }
641
34.2k
      else
642
34.2k
  * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
643
36.4k
    }
644
32.3k
  else if (as == 1)
645
32.3k
    {
646
32.3k
      if (regs == 0)
647
5.70k
  {
648
5.70k
    *cycles = 4;
649
    /* PC relative.  */
650
5.70k
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
651
5.70k
      {
652
5.70k
        cmd_len += 2;
653
5.70k
        sprintf (op1, "0x%04x", PS (dst));
654
5.70k
        sprintf (comm1, "PC rel. 0x%04x",
655
5.70k
           PS ((short) addr + 2 + dst));
656
5.70k
        if (extension_word)
657
657
    {
658
657
      dst &= 0xffff;
659
657
      dst |= extended_src << 16;
660
657
      if (dst & 0x80000)
661
90
        dst |= -1U << 20;
662
657
      sprintf (op1, "0x%05x", dst & 0xfffff);
663
657
      sprintf (comm1, "PC rel. 0x%05lx",
664
657
         (long) ((addr + 2 + dst) & 0xfffff));
665
657
    }
666
5.70k
      }
667
2
    else
668
2
      return -1;
669
5.70k
  }
670
26.6k
      else if (regs == 2)
671
4.99k
  {
672
4.99k
    *cycles = 2;
673
    /* Absolute.  */
674
4.99k
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
675
4.98k
      {
676
4.98k
        cmd_len += 2;
677
4.98k
        sprintf (op1, "&0x%04x", PS (dst));
678
4.98k
        sprintf (comm1, "0x%04x", PS (dst));
679
4.98k
        if (extension_word)
680
837
    {
681
837
      dst &= 0xffff;
682
837
      dst |= extended_src << 16;
683
837
      sprintf (op1, "&0x%05x", dst & 0xfffff);
684
837
      * comm1 = 0;
685
837
    }
686
4.98k
      }
687
10
    else
688
10
      return -1;
689
4.99k
  }
690
21.6k
      else if (regs == 3)
691
1.63k
  {
692
1.63k
    *cycles = 1;
693
1.63k
    sprintf (op1, "#1");
694
1.63k
    sprintf (comm1, "r3 As==01");
695
1.63k
  }
696
19.9k
      else
697
19.9k
  {
698
19.9k
    *cycles = 3;
699
    /* Indexed.  */
700
19.9k
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
701
19.9k
      {
702
19.9k
        cmd_len += 2;
703
19.9k
        if (extension_word)
704
2.15k
    {
705
2.15k
      dst &= 0xffff;
706
2.15k
      dst |= extended_src << 16;
707
2.15k
      if (dst & 0x80000)
708
344
        dst |= -1U << 20;
709
2.15k
    }
710
19.9k
        sprintf (op1, "%d(r%d)", dst, regs);
711
19.9k
        if (dst > 9 || dst < -9)
712
19.3k
    sprintf (comm1, "0x%05x", dst);
713
19.9k
      }
714
10
    else
715
10
      return -1;
716
19.9k
  }
717
32.3k
    }
718
719
  /* Destination. Special care needed on addr + XXXX.  */
720
721
125k
  if (ad == 0)
722
65.9k
    {
723
      /* Register.  */
724
65.9k
      if (regd == 0)
725
15.5k
  {
726
15.5k
    *cycles += 1;
727
15.5k
    sprintf (op2, "r0");
728
15.5k
  }
729
50.4k
      else if (regd == 1)
730
7.41k
  sprintf (op2, "r1");
731
732
43.0k
      else if (regd == 2)
733
5.77k
  sprintf (op2, "r2");
734
735
37.2k
      else
736
37.2k
  sprintf (op2, "r%d", regd);
737
65.9k
    }
738
59.7k
  else  /* ad == 1.  */
739
59.7k
    {
740
59.7k
      * cycles += 3;
741
742
59.7k
      if (regd == 0)
743
3.36k
  {
744
    /* PC relative.  */
745
3.36k
    *cycles += 1;
746
3.36k
    if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
747
3.36k
      {
748
3.36k
        sprintf (op2, "0x%04x", PS (dst));
749
3.36k
        sprintf (comm2, "PC rel. 0x%04x",
750
3.36k
           PS ((short) addr + cmd_len + dst));
751
3.36k
        if (extension_word)
752
118
    {
753
118
      dst |= extended_dst << 16;
754
118
      if (dst & 0x80000)
755
59
        dst |= -1U << 20;
756
118
      sprintf (op2, "0x%05x", dst & 0xfffff);
757
118
      sprintf (comm2, "PC rel. 0x%05lx",
758
118
         (long)((addr + cmd_len + dst) & 0xfffff));
759
118
    }
760
3.36k
      }
761
4
    else
762
4
      return -1;
763
3.36k
    cmd_len += 2;
764
3.36k
  }
765
56.3k
      else if (regd == 2)
766
5.10k
  {
767
    /* Absolute.  */
768
5.10k
    if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
769
5.10k
      {
770
5.10k
        cmd_len += 2;
771
5.10k
        sprintf (op2, "&0x%04x", PS (dst));
772
5.10k
        if (extension_word)
773
793
    {
774
793
      dst |= extended_dst << 16;
775
793
      sprintf (op2, "&0x%05x", dst & 0xfffff);
776
793
    }
777
5.10k
      }
778
8
    else
779
8
      return -1;
780
5.10k
  }
781
51.2k
      else
782
51.2k
  {
783
51.2k
    if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
784
51.2k
      {
785
51.2k
        cmd_len += 2;
786
51.2k
        if (dst > 9 || dst < 0)
787
49.6k
    sprintf (comm2, "0x%04x", PS (dst));
788
51.2k
        if (extension_word)
789
1.74k
    {
790
1.74k
      dst |= extended_dst << 16;
791
1.74k
      if (dst & 0x80000)
792
1.51k
        dst |= -1U << 20;
793
1.74k
      if (dst > 9 || dst < 0)
794
1.67k
        sprintf (comm2, "0x%05x", dst & 0xfffff);
795
1.74k
    }
796
51.2k
        sprintf (op2, "%d(r%d)", dst, regd);
797
51.2k
      }
798
18
    else
799
18
      return -1;
800
51.2k
  }
801
59.7k
    }
802
803
125k
  return cmd_len;
804
125k
}
805
806
static int
807
msp430_branchinstr (disassemble_info *info,
808
        struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED,
809
        bfd_vma addr ATTRIBUTE_UNUSED,
810
        unsigned short insn,
811
        char *op1,
812
        char *comm1,
813
        int *cycles)
814
2.37k
{
815
2.37k
  int regs = 0, regd = 0;
816
2.37k
  int as = 0;
817
2.37k
  int cmd_len = 2;
818
2.37k
  int dst = 0;
819
2.37k
  unsigned short udst = 0;
820
821
2.37k
  regd = insn & 0x0f;
822
2.37k
  regs = (insn & 0x0f00) >> 8;
823
2.37k
  as = (insn & 0x0030) >> 4;
824
825
2.37k
  if (regd != 0)  /* Destination register is not a PC.  */
826
0
    return 0;
827
828
  /* dst is a source register.  */
829
2.37k
  if (as == 0)
830
1.17k
    {
831
      /* Constants.  */
832
1.17k
      if (regs == 3)
833
0
  {
834
0
    *cycles = 1;
835
0
    sprintf (op1, "#0");
836
0
    sprintf (comm1, "r3 As==00");
837
0
  }
838
1.17k
      else
839
1.17k
  {
840
    /* Register.  */
841
1.17k
    *cycles = 1;
842
1.17k
    sprintf (op1, "r%d", regs);
843
1.17k
  }
844
1.17k
    }
845
1.19k
  else if (as == 2)
846
208
    {
847
208
      * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
848
208
    }
849
988
  else if (as == 3)
850
604
    {
851
604
      if (regs == 0)
852
10
  {
853
    /* Absolute. @pc+  */
854
10
    *cycles = 3;
855
10
    if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
856
10
      {
857
10
        cmd_len += 2;
858
10
        sprintf (op1, "#0x%04x", PS (udst));
859
10
      }
860
0
    else
861
0
      return -1;
862
10
  }
863
594
      else
864
594
  * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
865
604
    }
866
384
  else if (as == 1)
867
384
    {
868
384
      * cycles = 3;
869
870
384
      if (regs == 0)
871
8
  {
872
    /* PC relative.  */
873
8
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
874
8
      {
875
8
        cmd_len += 2;
876
8
        (*cycles)++;
877
8
        sprintf (op1, "0x%04x", PS (dst));
878
8
        sprintf (comm1, "PC rel. 0x%04x",
879
8
           PS ((short) addr + 2 + dst));
880
8
      }
881
0
    else
882
0
      return -1;
883
8
  }
884
376
      else if (regs == 2)
885
3
  {
886
    /* Absolute.  */
887
3
    if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
888
3
      {
889
3
        cmd_len += 2;
890
3
        sprintf (op1, "&0x%04x", PS (udst));
891
3
      }
892
0
    else
893
0
      return -1;
894
3
  }
895
373
      else if (regs == 3)
896
21
  {
897
21
    (*cycles)--;
898
21
    sprintf (op1, "#1");
899
21
    sprintf (comm1, "r3 As==01");
900
21
  }
901
352
      else
902
352
  {
903
    /* Indexed.  */
904
352
    if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
905
352
      {
906
352
        cmd_len += 2;
907
352
        sprintf (op1, "%d(r%d)", dst, regs);
908
352
      }
909
0
    else
910
0
      return -1;
911
352
  }
912
384
    }
913
914
2.37k
  return cmd_len;
915
2.37k
}
916
917
static int
918
msp430x_calla_instr (disassemble_info * info,
919
         bfd_vma            addr,
920
         unsigned short     insn,
921
         char *             op1,
922
         char *             comm1,
923
         int *              cycles)
924
371
{
925
371
  unsigned int   ureg = insn & 0xf;
926
371
  int            reg = insn & 0xf;
927
371
  int            am = (insn & 0xf0) >> 4;
928
371
  int            cmd_len = 2;
929
371
  unsigned short udst = 0;
930
371
  int            dst = 0;
931
932
371
  switch (am)
933
371
    {
934
16
    case 4: /* CALLA Rdst */
935
16
      *cycles = 1;
936
16
      sprintf (op1, "r%d", reg);
937
16
      break;
938
939
11
    case 5: /* CALLA x(Rdst) */
940
11
      *cycles = 3;
941
11
      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
942
10
  {
943
10
    cmd_len += 2;
944
10
    sprintf (op1, "%d(r%d)", dst, reg);
945
10
    if (reg == 0)
946
6
      sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst));
947
4
    else
948
4
      sprintf (comm1, "0x%05x", dst);
949
10
  }
950
1
      else
951
1
  return -1;
952
10
      break;
953
954
32
    case 6: /* CALLA @Rdst */
955
32
      *cycles = 2;
956
32
      sprintf (op1, "@r%d", reg);
957
32
      break;
958
959
33
    case 7: /* CALLA @Rdst+ */
960
33
      *cycles = 2;
961
33
      sprintf (op1, "@r%d+", reg);
962
33
      break;
963
964
22
    case 8: /* CALLA &abs20 */
965
22
      if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
966
21
  {
967
21
    cmd_len += 2;
968
21
    *cycles = 4;
969
21
    sprintf (op1, "&%d", (ureg << 16) + udst);
970
21
    sprintf (comm1, "0x%05x", (ureg << 16) + udst);
971
21
  }
972
1
      else
973
1
  return -1;
974
21
      break;
975
976
65
    case 9: /* CALLA pcrel-sym */
977
65
      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
978
61
  {
979
61
    cmd_len += 2;
980
61
    *cycles = 4;
981
61
    sprintf (op1, "%d(PC)", (reg << 16) + dst);
982
61
    sprintf (comm1, "PC rel. 0x%05lx",
983
61
       (long) (addr + 2 + dst + (reg << 16)));
984
61
  }
985
4
      else
986
4
  return -1;
987
61
      break;
988
989
191
    case 11: /* CALLA #imm20 */
990
191
      if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
991
190
  {
992
190
    cmd_len += 2;
993
190
    *cycles = 4;
994
190
    sprintf (op1, "#%d", (ureg << 16) + udst);
995
190
    sprintf (comm1, "0x%05x", (ureg << 16) + udst);
996
190
  }
997
1
      else
998
1
  return -1;
999
190
      break;
1000
1001
190
    default:
1002
1
      strcpy (comm1, _("Warning: unrecognised CALLA addressing mode"));
1003
1
      return -1;
1004
371
    }
1005
1006
363
  return cmd_len;
1007
371
}
1008
1009
int
1010
print_insn_msp430 (bfd_vma addr, disassemble_info *info)
1011
251k
{
1012
251k
  void *stream = info->stream;
1013
251k
  fprintf_ftype prin = info->fprintf_func;
1014
251k
  struct msp430_opcode_s *opcode;
1015
251k
  char op1[32], op2[32], comm1[64], comm2[64];
1016
251k
  int cmd_len = 0;
1017
251k
  unsigned short insn;
1018
251k
  int cycles = 0;
1019
251k
  char *bc = "";
1020
251k
  unsigned short extension_word = 0;
1021
251k
  unsigned short bits;
1022
1023
251k
  if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
1024
53
    return -1;
1025
1026
251k
  if (((int) addr & 0xffff) > 0xffdf)
1027
0
    {
1028
0
      (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
1029
0
      return 2;
1030
0
    }
1031
1032
251k
  *comm1 = 0;
1033
251k
  *comm2 = 0;
1034
1035
  /* Check for an extension word.  */
1036
251k
  if ((insn & 0xf800) == 0x1800)
1037
19.3k
    {
1038
19.3k
      extension_word = insn;
1039
19.3k
      addr += 2;
1040
19.3k
      if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
1041
15
  return -1;
1042
19.3k
   }
1043
1044
11.1M
  for (opcode = msp430_opcodes; opcode->name; opcode++)
1045
11.1M
    {
1046
11.1M
      if ((insn & opcode->bin_mask) == opcode->bin_opcode
1047
11.1M
    && opcode->bin_opcode != 0x9300)
1048
284k
  {
1049
284k
    *op1 = 0;
1050
284k
    *op2 = 0;
1051
284k
    *comm1 = 0;
1052
284k
    *comm2 = 0;
1053
1054
    /* r0 as destination. Ad should be zero.  */
1055
284k
    if (opcode->insn_opnumb == 3
1056
284k
        && (insn & 0x000f) == 0
1057
284k
        && (insn & 0x0080) == 0)
1058
2.37k
      {
1059
2.37k
        int ret =
1060
2.37k
    msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
1061
2.37k
            &cycles);
1062
1063
2.37k
        if (ret == -1)
1064
0
    return -1;
1065
2.37k
        cmd_len += ret;
1066
2.37k
        if (cmd_len)
1067
2.37k
    break;
1068
2.37k
      }
1069
1070
282k
    switch (opcode->insn_opnumb)
1071
282k
      {
1072
0
        int n;
1073
0
        int reg;
1074
0
        int ret;
1075
1076
371
      case 4:
1077
371
        ret = msp430x_calla_instr (info, addr, insn,
1078
371
           op1, comm1, & cycles);
1079
371
        if (ret == -1)
1080
8
    return -1;
1081
363
        cmd_len += ret;
1082
363
        break;
1083
1084
3.35k
      case 5: /* PUSHM/POPM */
1085
3.35k
        n = (insn & 0xf0) >> 4;
1086
3.35k
        reg = (insn & 0xf);
1087
1088
3.35k
        sprintf (op1, "#%d", n + 1);
1089
3.35k
        if (opcode->bin_opcode == 0x1400)
1090
    /* PUSHM */
1091
2.35k
    sprintf (op2, "r%d", reg);
1092
999
        else
1093
    /* POPM */
1094
999
    sprintf (op2, "r%d", reg + n);
1095
3.35k
        if (insn & 0x100)
1096
2.19k
    sprintf (comm1, "16-bit words");
1097
1.15k
        else
1098
1.15k
    {
1099
1.15k
      sprintf (comm1, "20-bit words");
1100
1.15k
      bc =".a";
1101
1.15k
    }
1102
1103
3.35k
        cycles = 2; /*FIXME*/
1104
3.35k
        cmd_len = 2;
1105
3.35k
        break;
1106
1107
2.30k
      case 6: /* RRAM, RRCM, RRUM, RLAM.  */
1108
2.30k
        n = ((insn >> 10) & 0x3) + 1;
1109
2.30k
        reg = (insn & 0xf);
1110
2.30k
        if ((insn & 0x10) == 0)
1111
1.13k
    bc =".a";
1112
2.30k
        sprintf (op1, "#%d", n);
1113
2.30k
        sprintf (op2, "r%d", reg);
1114
2.30k
        cycles = 2; /*FIXME*/
1115
2.30k
        cmd_len = 2;
1116
2.30k
        break;
1117
1118
7.95k
      case 8: /* ADDA, CMPA, SUBA.  */
1119
7.95k
        reg = (insn & 0xf);
1120
7.95k
        n = (insn >> 8) & 0xf;
1121
7.95k
        if (insn & 0x40)
1122
5.25k
    {
1123
5.25k
      sprintf (op1, "r%d", n);
1124
5.25k
      cmd_len = 2;
1125
5.25k
    }
1126
2.70k
        else
1127
2.70k
    {
1128
2.70k
      n <<= 16;
1129
2.70k
      if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1130
2.70k
        {
1131
2.70k
          n |= bits;
1132
2.70k
          sprintf (op1, "#%d", n);
1133
2.70k
          if (n > 9 || n < 0)
1134
2.25k
      sprintf (comm1, "0x%05x", n);
1135
2.70k
        }
1136
1
      else
1137
1
        return -1;
1138
2.70k
      cmd_len = 4;
1139
2.70k
    }
1140
7.95k
        sprintf (op2, "r%d", reg);
1141
7.95k
        cycles = 2; /*FIXME*/
1142
7.95k
        break;
1143
1144
26.1k
      case 9: /* MOVA */
1145
26.1k
        reg = (insn & 0xf);
1146
26.1k
        n = (insn >> 8) & 0xf;
1147
26.1k
        switch ((insn >> 4) & 0xf)
1148
26.1k
    {
1149
11.3k
    case 0: /* MOVA @Rsrc, Rdst */
1150
11.3k
      cmd_len = 2;
1151
11.3k
      sprintf (op1, "@r%d", n);
1152
11.3k
      if (strcmp (opcode->name, "bra") != 0)
1153
9.07k
        sprintf (op2, "r%d", reg);
1154
11.3k
      break;
1155
1156
4.80k
    case 1: /* MOVA @Rsrc+, Rdst */
1157
4.80k
      cmd_len = 2;
1158
4.80k
      if (strcmp (opcode->name, "reta") != 0)
1159
3.69k
        {
1160
3.69k
          sprintf (op1, "@r%d+", n);
1161
3.69k
          if (strcmp (opcode->name, "bra") != 0)
1162
2.56k
      sprintf (op2, "r%d", reg);
1163
3.69k
        }
1164
4.80k
      break;
1165
1166
2.60k
    case 2: /* MOVA &abs20, Rdst */
1167
2.60k
      cmd_len = 4;
1168
2.60k
      n <<= 16;
1169
2.60k
      if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1170
2.60k
        {
1171
2.60k
          n |= bits;
1172
2.60k
          sprintf (op1, "&%d", n);
1173
2.60k
          if (n > 9 || n < 0)
1174
2.24k
      sprintf (comm1, "0x%05x", n);
1175
2.60k
          if (strcmp (opcode->name, "bra") != 0)
1176
1.75k
      sprintf (op2, "r%d", reg);
1177
2.60k
        }
1178
1
      else
1179
1
        return -1;
1180
2.60k
      break;
1181
1182
2.60k
    case 3: /* MOVA x(Rsrc), Rdst */
1183
2.20k
      cmd_len = 4;
1184
2.20k
      if (strcmp (opcode->name, "bra") != 0)
1185
2.05k
        sprintf (op2, "r%d", reg);
1186
2.20k
      reg = n;
1187
2.20k
      if (msp430dis_opcode_signed (addr + 2, info, &n, comm1))
1188
2.20k
        {
1189
2.20k
          sprintf (op1, "%d(r%d)", n, reg);
1190
2.20k
          if (n > 9 || n < 0)
1191
1.74k
      {
1192
1.74k
        if (reg == 0)
1193
1.07k
          sprintf (comm1, "PC rel. 0x%05lx",
1194
1.07k
             (long) (addr + 2 + n));
1195
667
        else
1196
667
          sprintf (comm1, "0x%05x", n);
1197
1.74k
      }
1198
2.20k
        }
1199
1
      else
1200
1
        return -1;
1201
2.20k
      break;
1202
1203
2.42k
    case 6: /* MOVA Rsrc, &abs20 */
1204
2.42k
      cmd_len = 4;
1205
2.42k
      reg <<= 16;
1206
2.42k
      if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2))
1207
2.41k
        {
1208
2.41k
          reg |= bits;
1209
2.41k
          sprintf (op1, "r%d", n);
1210
2.41k
          sprintf (op2, "&%d", reg);
1211
2.41k
          if (reg > 9 || reg < 0)
1212
2.40k
      sprintf (comm2, "0x%05x", reg);
1213
2.41k
        }
1214
9
      else
1215
9
        return -1;
1216
2.41k
      break;
1217
1218
2.41k
    case 7: /* MOVA Rsrc, x(Rdst) */
1219
1.00k
      cmd_len = 4;
1220
1.00k
      sprintf (op1, "r%d", n);
1221
1.00k
      if (msp430dis_opcode_signed (addr + 2, info, &n, comm2))
1222
1.00k
        {
1223
1.00k
          sprintf (op2, "%d(r%d)", n, reg);
1224
1.00k
          if (n > 9 || n < 0)
1225
857
      {
1226
857
        if (reg == 0)
1227
83
          sprintf (comm2, "PC rel. 0x%05lx",
1228
83
             (long) (addr + 2 + n));
1229
774
        else
1230
774
          sprintf (comm2, "0x%05x", n);
1231
857
      }
1232
1.00k
        }
1233
2
      else
1234
2
        return -1;
1235
1.00k
      break;
1236
1237
1.12k
    case 8: /* MOVA #imm20, Rdst */
1238
1.12k
      cmd_len = 4;
1239
1.12k
      n <<= 16;
1240
1.12k
      if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1241
1.12k
        {
1242
1.12k
          n |= bits;
1243
1.12k
          if (n & 0x80000)
1244
155
      n |= -1U << 20;
1245
1.12k
          sprintf (op1, "#%d", n);
1246
1.12k
          if (n > 9 || n < 0)
1247
1.01k
      sprintf (comm1, "0x%05x", n);
1248
1.12k
          if (strcmp (opcode->name, "bra") != 0)
1249
1.12k
      sprintf (op2, "r%d", reg);
1250
1.12k
        }
1251
1
      else
1252
1
        return -1;
1253
1.12k
      break;
1254
1255
1.12k
    case 12: /* MOVA Rsrc, Rdst */
1256
645
      cmd_len = 2;
1257
645
      sprintf (op1, "r%d", n);
1258
645
      if (strcmp (opcode->name, "bra") != 0)
1259
645
        sprintf (op2, "r%d", reg);
1260
645
      break;
1261
1262
0
    default:
1263
0
      break;
1264
26.1k
    }
1265
26.1k
        cycles = 2; /* FIXME */
1266
26.1k
        break;
1267
282k
      }
1268
1269
282k
    if (cmd_len)
1270
40.1k
      break;
1271
1272
242k
    switch (opcode->insn_opnumb)
1273
242k
      {
1274
0
        int ret;
1275
1276
31.7k
      case 0:
1277
31.7k
        cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
1278
31.7k
        break;
1279
150k
      case 2:
1280
150k
        ret =
1281
150k
    msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
1282
150k
              comm1, comm2,
1283
150k
              extension_word,
1284
150k
              &cycles);
1285
1286
150k
        if (ret == -1)
1287
154
    return -1;
1288
150k
        cmd_len += ret;
1289
150k
        if (insn & BYTE_OPERATION)
1290
87.4k
    {
1291
87.4k
      if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1292
2.26k
        bc = ".a";
1293
85.1k
      else
1294
85.1k
        bc = ".b";
1295
87.4k
    }
1296
62.8k
        else if (extension_word)
1297
4.42k
    {
1298
4.42k
      if (extension_word & BYTE_OPERATION)
1299
1.57k
        bc = ".w";
1300
2.85k
      else
1301
2.85k
        {
1302
2.85k
          bc = ".?";
1303
2.85k
          sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1304
2.85k
        }
1305
4.42k
    }
1306
1307
150k
        break;
1308
43.1k
      case 1:
1309
43.1k
        ret =
1310
43.1k
    msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
1311
43.1k
              extension_word,
1312
43.1k
              &cycles);
1313
1314
43.1k
        if (ret == -1)
1315
12
    return -1;
1316
43.1k
        cmd_len += ret;
1317
43.1k
        if (extension_word
1318
43.1k
      && (strcmp (opcode->name, "swpb") == 0
1319
2.86k
          || strcmp (opcode->name, "sxt") == 0))
1320
917
    {
1321
917
      if (insn & BYTE_OPERATION)
1322
0
        {
1323
0
          bc = ".?";
1324
0
          sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1325
0
        }
1326
917
      else if (extension_word & BYTE_OPERATION)
1327
897
        bc = ".w";
1328
20
      else
1329
20
        bc = ".a";
1330
917
    }
1331
42.2k
        else if (insn & BYTE_OPERATION && opcode->fmt != 3)
1332
2.76k
    {
1333
2.76k
      if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1334
58
        bc = ".a";
1335
2.70k
      else
1336
2.70k
        bc = ".b";
1337
2.76k
    }
1338
39.4k
        else if (extension_word)
1339
1.47k
    {
1340
1.47k
      if (extension_word & (1 << 6))
1341
227
        bc = ".w";
1342
1.24k
      else
1343
1.24k
        {
1344
1.24k
          bc = ".?";
1345
1.24k
          sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1346
1.24k
        }
1347
1.47k
    }
1348
43.1k
        break;
1349
16.8k
      default:
1350
16.8k
        break;
1351
242k
      }
1352
242k
  }
1353
1354
11.0M
      if (cmd_len)
1355
200k
  break;
1356
11.0M
    }
1357
1358
251k
  if (cmd_len < 1)
1359
8.38k
    {
1360
      /* Unknown opcode, or invalid combination of operands.  */
1361
8.38k
      if (extension_word)
1362
6.83k
  {
1363
6.83k
    prin (stream, ".word  0x%04x, 0x%04x; ????", extension_word, PS (insn));
1364
6.83k
    if (*comm1)
1365
0
      prin (stream, "\t %s", comm1);
1366
6.83k
    return 4;
1367
6.83k
  }
1368
1.55k
      (*prin) (stream, ".word 0x%04x; ????", PS (insn));
1369
1.55k
      return 2;
1370
8.38k
    }
1371
1372
  /* Display the repeat count (if set) for extended register mode.  */
1373
242k
  if (cmd_len == 2 && ((extension_word & 0xf) != 0))
1374
3.66k
    {
1375
3.66k
      if (extension_word & (1 << 7))
1376
778
  prin (stream, "rpt r%d { ", extension_word & 0xf);
1377
2.89k
      else
1378
2.89k
  prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1);
1379
3.66k
    }
1380
1381
  /* Special case:  RRC with an extension word and the ZC bit set is actually RRU.  */
1382
242k
  if (extension_word
1383
242k
      && (extension_word & IGNORE_CARRY_BIT)
1384
242k
      && strcmp (opcode->name, "rrc") == 0)
1385
172
    (*prin) (stream, "rrux%s", bc);
1386
242k
  else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x')
1387
12.2k
    (*prin) (stream, "%sx%s", opcode->name, bc);
1388
230k
  else
1389
230k
    (*prin) (stream, "%s%s", opcode->name, bc);
1390
1391
242k
  if (*op1)
1392
210k
    (*prin) (stream, "\t%s", op1);
1393
242k
  if (*op2)
1394
159k
    (*prin) (stream, ",");
1395
1396
242k
  if (strlen (op1) < 7)
1397
178k
    (*prin) (stream, "\t");
1398
242k
  if (!strlen (op1))
1399
32.4k
    (*prin) (stream, "\t");
1400
1401
242k
  if (*op2)
1402
159k
    (*prin) (stream, "%s", op2);
1403
242k
  if (strlen (op2) < 8)
1404
204k
    (*prin) (stream, "\t");
1405
1406
242k
  if (*comm1 || *comm2)
1407
133k
    (*prin) (stream, ";");
1408
109k
  else if (cycles)
1409
78.2k
    {
1410
78.2k
      if (*op2)
1411
65.8k
  (*prin) (stream, ";");
1412
12.3k
      else
1413
12.3k
  {
1414
12.3k
    if (strlen (op1) < 7)
1415
11.0k
      (*prin) (stream, ";");
1416
1.38k
    else
1417
1.38k
      (*prin) (stream, "\t;");
1418
12.3k
  }
1419
78.2k
    }
1420
242k
  if (*comm1)
1421
92.8k
    (*prin) (stream, "%s", comm1);
1422
242k
  if (*comm1 && *comm2)
1423
19.2k
    (*prin) (stream, ",");
1424
242k
  if (*comm2)
1425
60.0k
    (*prin) (stream, " %s", comm2);
1426
1427
242k
  if (extension_word)
1428
12.4k
    cmd_len += 2;
1429
1430
242k
  return cmd_len;
1431
251k
}