Coverage Report

Created: 2026-04-04 08:16

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