Coverage Report

Created: 2026-03-10 08:46

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