Coverage Report

Created: 2025-06-24 06:45

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