Coverage Report

Created: 2026-09-14 08:07

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