Coverage Report

Created: 2024-05-21 06:29

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