Coverage Report

Created: 2026-05-11 07:54

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