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