Re-add support for lbarx, lharx, stbcx. and sthcx. insns back to the E6500 cpu.
[binutils-gdb.git] / opcodes / msp430-dis.c
blobc057c9bde7ec1eb2a1338c943be8884d448e0a53
1 /* Disassemble MSP430 instructions.
2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
4 Contributed by Dmitry Diky <diwil@mail.ru>
6 This file is part of the GNU opcodes library.
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.
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.
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. */
23 #include "sysdep.h"
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <sys/types.h>
27 #include <errno.h>
29 #include "dis-asm.h"
30 #include "opintl.h"
31 #include "libiberty.h"
33 #define DASM_SECTION
34 #include "opcode/msp430.h"
35 #undef DASM_SECTION
38 #define PS(x) (0xffff & (x))
40 static bfd_boolean
41 msp430dis_read_two_bytes (bfd_vma addr,
42 disassemble_info * info,
43 bfd_byte * buffer,
44 char * comm)
46 int status;
48 status = info->read_memory_func (addr, buffer, 2, info);
49 if (status == 0)
50 return TRUE;
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)
58 if (comm)
59 sprintf (comm, _("Warning: disassembly unreliable - not enough bytes available"));
61 else
63 info->memory_error_func (status, addr, info);
64 if (comm)
65 sprintf (comm, _("Error: read from memory failed"));
68 return FALSE;
71 static bfd_boolean
72 msp430dis_opcode_unsigned (bfd_vma addr,
73 disassemble_info * info,
74 unsigned short * return_val,
75 char * comm)
77 bfd_byte buffer[2];
79 if (msp430dis_read_two_bytes (addr, info, buffer, comm))
81 * return_val = bfd_getl16 (buffer);
82 return TRUE;
84 else
86 * return_val = 0;
87 return FALSE;
91 static bfd_boolean
92 msp430dis_opcode_signed (bfd_vma addr,
93 disassemble_info * info,
94 signed int * return_val,
95 char * comm)
97 bfd_byte buffer[2];
99 if (msp430dis_read_two_bytes (addr, info, buffer, comm))
101 int status;
103 status = bfd_getl_signed_16 (buffer);
104 if (status & 0x8000)
105 status |= -1U << 16;
106 * return_val = status;
107 return TRUE;
109 else
111 * return_val = 0;
112 return FALSE;
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)
123 /* Pop with constant. */
124 if (insn == 0x43b2)
125 return 0;
126 if (insn == opcode->bin_opcode)
127 return 2;
129 if (opcode->fmt == 0)
131 if ((insn & 0x0f00) != 0x0300 || (insn & 0x0f00) != 0x0200)
132 return 0;
134 strcpy (comm, "emulated...");
135 *cycles = 1;
137 else
139 strcpy (comm, "return from interupt");
140 *cycles = 5;
143 return 2;
146 static int
147 print_as2_reg_name (int regno, char * op1, char * comm1,
148 int c2, int c3, int cd)
150 switch (regno)
152 case 2:
153 sprintf (op1, "#4");
154 sprintf (comm1, "r2 As==10");
155 return c2;
157 case 3:
158 sprintf (op1, "#2");
159 sprintf (comm1, "r3 As==10");
160 return c3;
162 default:
163 /* Indexed register mode @Rn. */
164 sprintf (op1, "@r%d", regno);
165 return cd;
169 static int
170 print_as3_reg_name (int regno, char * op1, char * comm1,
171 int c2, int c3, int cd)
173 switch (regno)
175 case 2:
176 sprintf (op1, "#8");
177 sprintf (comm1, "r2 As==11");
178 return c2;
180 case 3:
181 sprintf (op1, "#-1");
182 sprintf (comm1, "r3 As==11");
183 return c3;
185 default:
186 /* Post incremented @Rn+. */
187 sprintf (op1, "@r%d+", regno);
188 return cd;
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)
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;
210 regd = insn & 0x0f;
211 regs = (insn & 0x0f00) >> 8;
212 as = (insn & 0x0030) >> 4;
213 ad = (insn & 0x0080) >> 7;
215 if (opcode->fmt < 0)
216 fmt = (- opcode->fmt) - 1;
217 else
218 fmt = opcode->fmt;
220 switch (fmt)
222 case 0: /* Emulated work with dst register. */
223 if (regs != 2 && regs != 3 && regs != 1)
224 return 0;
226 /* Check if not clr insn. */
227 if (opcode->bin_opcode == 0x4300 && (ad || as))
228 return 0;
230 /* Check if really inc, incd insns. */
231 if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
232 return 0;
234 if (ad == 0)
236 *cycles = 1;
238 /* Register. */
239 if (regd == 0)
241 *cycles += 1;
242 sprintf (op, "r0");
244 else if (regd == 1)
245 sprintf (op, "r1");
247 else if (regd == 2)
248 sprintf (op, "r2");
250 else
251 sprintf (op, "r%d", regd);
253 else /* ad == 1 msp430dis_opcode. */
255 if (regd == 0)
257 /* PC relative. */
258 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
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)
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));
274 else if (regd == 2)
276 /* Absolute. */
277 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
279 cmd_len += 2;
280 *cycles = 4;
281 sprintf (op, "&0x%04x", PS (dst));
282 if (extended_dst)
284 dst |= extended_dst << 16;
285 sprintf (op, "&0x%05x", dst & 0xfffff);
289 else
291 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
293 cmd_len += 2;
294 *cycles = 4;
295 if (extended_dst)
297 dst |= extended_dst << 16;
298 if (dst & 0x80000)
299 dst |= -1U << 20;
301 sprintf (op, "%d(r%d)", dst, regd);
305 break;
307 case 2: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */
308 if (as == 0)
310 if (regd == 3)
312 /* Constsnts. */
313 sprintf (op, "#0");
314 sprintf (comm, "r3 As==00");
316 else
318 /* Register. */
319 sprintf (op, "r%d", regd);
321 *cycles = 1;
323 else if (as == 2)
325 * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
327 else if (as == 3)
329 if (regd == 0)
331 *cycles = 3;
332 /* absolute. @pc+ */
333 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
335 cmd_len += 2;
336 sprintf (op, "#%d", dst);
337 if (dst > 9 || dst < 0)
338 sprintf (comm, "#0x%04x", PS (dst));
339 if (extended_dst)
341 dst |= extended_dst << 16;
342 if (dst & 0x80000)
343 dst |= -1U << 20;
344 sprintf (op, "#%d", dst);
345 if (dst > 9 || dst < 0)
346 sprintf (comm, "#0x%05x", dst);
350 else
351 * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
353 else if (as == 1)
355 *cycles = 4;
356 if (regd == 0)
358 /* PC relative. */
359 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
361 cmd_len += 2;
362 sprintf (op, "0x%04x", PS (dst));
363 sprintf (comm, "PC rel. 0x%04x",
364 PS ((short) addr + 2 + dst));
365 if (extended_dst)
367 dst |= extended_dst << 16;
368 sprintf (op, "0x%05x", dst & 0xffff);
369 sprintf (comm, "PC rel. 0x%05lx",
370 (long)((addr + 2 + dst) & 0xfffff));
374 else if (regd == 2)
376 /* Absolute. */
377 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
379 cmd_len += 2;
380 sprintf (op, "&0x%04x", PS (dst));
381 if (extended_dst)
383 dst |= extended_dst << 16;
384 sprintf (op, "&0x%05x", dst & 0xfffff);
388 else if (regd == 3)
390 *cycles = 1;
391 sprintf (op, "#1");
392 sprintf (comm, "r3 As==01");
394 else
396 /* Indexed. */
397 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
399 cmd_len += 2;
400 if (extended_dst)
402 dst |= extended_dst << 16;
403 if (dst & 0x80000)
404 dst |= -1U << 20;
406 sprintf (op, "%d(r%d)", dst, regd);
407 if (dst > 9 || dst < 0)
408 sprintf (comm, "%05x", dst);
412 break;
414 case 3: /* Jumps. */
415 where = insn & 0x03ff;
416 if (where & 0x200)
417 where |= ~0x03ff;
418 if (where > 512 || where < -511)
419 return 0;
421 where *= 2;
422 sprintf (op, "$%+-8d", where + 2);
423 sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
424 *cycles = 2;
425 return 2;
426 break;
428 default:
429 cmd_len = 0;
432 return cmd_len;
435 static int
436 msp430_doubleoperand (disassemble_info *info,
437 struct msp430_opcode_s *opcode,
438 bfd_vma addr,
439 unsigned short insn,
440 char *op1,
441 char *op2,
442 char *comm1,
443 char *comm2,
444 unsigned short extension_word,
445 int *cycles)
447 int regs = 0, regd = 0;
448 int ad = 0, as = 0;
449 int cmd_len = 2;
450 int dst = 0;
451 int fmt;
452 int extended_dst = extension_word & 0xf;
453 int extended_src = (extension_word >> 7) & 0xf;
455 regd = insn & 0x0f;
456 regs = (insn & 0x0f00) >> 8;
457 as = (insn & 0x0030) >> 4;
458 ad = (insn & 0x0080) >> 7;
460 if (opcode->fmt < 0)
461 fmt = (- opcode->fmt) - 1;
462 else
463 fmt = opcode->fmt;
465 if (fmt == 0)
467 /* Special case: rla and rlc are the only 2 emulated instructions that
468 fall into two operand instructions. */
469 /* With dst, there are only:
470 Rm Register,
471 x(Rm) Indexed,
472 0xXXXX Relative,
473 &0xXXXX Absolute
474 emulated_ins dst
475 basic_ins dst, dst. */
477 if (regd != regs || as != ad)
478 return 0; /* May be 'data' section. */
480 if (ad == 0)
482 /* Register mode. */
483 if (regd == 3)
485 strcpy (comm1, _("Warning: illegal as emulation instr"));
486 return -1;
489 sprintf (op1, "r%d", regd);
490 *cycles = 1;
492 else /* ad == 1 */
494 if (regd == 0)
496 /* PC relative, Symbolic. */
497 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
499 cmd_len += 4;
500 *cycles = 6;
501 sprintf (op1, "0x%04x", PS (dst));
502 sprintf (comm1, "PC rel. 0x%04x",
503 PS ((short) addr + 2 + dst));
504 if (extension_word)
506 dst |= extended_dst << 16;
507 if (dst & 0x80000)
508 dst |= -1U << 20;
509 sprintf (op1, "0x%05x", dst & 0xfffff);
510 sprintf (comm1, "PC rel. 0x%05lx",
511 (long)((addr + 2 + dst) & 0xfffff));
515 else if (regd == 2)
517 /* Absolute. */
518 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
520 int src;
522 /* If the 'src' field is not the same as the dst
523 then this is not an rla instruction. */
524 if (msp430dis_opcode_signed (addr + 4, info, &src, comm2))
526 if (src != dst)
527 return 0;
529 cmd_len += 4;
530 *cycles = 6;
531 sprintf (op1, "&0x%04x", PS (dst));
532 if (extension_word)
534 dst |= extended_dst << 16;
535 sprintf (op1, "&0x%05x", dst & 0xfffff);
539 else
541 /* Indexed. */
542 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
544 if (extension_word)
546 dst |= extended_dst << 16;
547 if (dst & 0x80000)
548 dst |= -1U << 20;
550 cmd_len += 4;
551 *cycles = 6;
552 sprintf (op1, "%d(r%d)", dst, regd);
553 if (dst > 9 || dst < -9)
554 sprintf (comm1, "#0x%05x", dst);
559 *op2 = 0;
560 *comm2 = 0;
562 return cmd_len;
565 /* Two operands exactly. */
566 if (ad == 0 && regd == 3)
568 /* R2/R3 are illegal as dest: may be data section. */
569 strcpy (comm1, _("Warning: illegal as 2-op instr"));
570 return -1;
573 /* Source. */
574 if (as == 0)
576 *cycles = 1;
577 if (regs == 3)
579 /* Constants. */
580 sprintf (op1, "#0");
581 sprintf (comm1, "r3 As==00");
583 else
585 /* Register. */
586 sprintf (op1, "r%d", regs);
589 else if (as == 2)
591 * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
593 else if (as == 3)
595 if (regs == 0)
597 *cycles = 3;
598 /* Absolute. @pc+. */
599 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
601 cmd_len += 2;
602 sprintf (op1, "#%d", dst);
603 if (dst > 9 || dst < 0)
604 sprintf (comm1, "#0x%04x", PS (dst));
605 if (extension_word)
607 dst &= 0xffff;
608 dst |= extended_src << 16;
609 if (dst & 0x80000)
610 dst |= -1U << 20;
611 sprintf (op1, "#%d", dst);
612 if (dst > 9 || dst < 0)
613 sprintf (comm1, "0x%05x", dst & 0xfffff);
617 else
618 * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
620 else if (as == 1)
622 if (regs == 0)
624 *cycles = 4;
625 /* PC relative. */
626 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
628 cmd_len += 2;
629 sprintf (op1, "0x%04x", PS (dst));
630 sprintf (comm1, "PC rel. 0x%04x",
631 PS ((short) addr + 2 + dst));
632 if (extension_word)
634 dst &= 0xffff;
635 dst |= extended_src << 16;
636 if (dst & 0x80000)
637 dst |= -1U << 20;
638 sprintf (op1, "0x%05x", dst & 0xfffff);
639 sprintf (comm1, "PC rel. 0x%05lx",
640 (long) ((addr + 2 + dst) & 0xfffff));
644 else if (regs == 2)
646 *cycles = 2;
647 /* Absolute. */
648 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
650 cmd_len += 2;
651 sprintf (op1, "&0x%04x", PS (dst));
652 sprintf (comm1, "0x%04x", PS (dst));
653 if (extension_word)
655 dst &= 0xffff;
656 dst |= extended_src << 16;
657 sprintf (op1, "&0x%05x", dst & 0xfffff);
658 * comm1 = 0;
662 else if (regs == 3)
664 *cycles = 1;
665 sprintf (op1, "#1");
666 sprintf (comm1, "r3 As==01");
668 else
670 *cycles = 3;
671 /* Indexed. */
672 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
674 cmd_len += 2;
675 if (extension_word)
677 dst &= 0xffff;
678 dst |= extended_src << 16;
679 if (dst & 0x80000)
680 dst |= -1U << 20;
682 sprintf (op1, "%d(r%d)", dst, regs);
683 if (dst > 9 || dst < -9)
684 sprintf (comm1, "0x%05x", dst);
689 /* Destination. Special care needed on addr + XXXX. */
691 if (ad == 0)
693 /* Register. */
694 if (regd == 0)
696 *cycles += 1;
697 sprintf (op2, "r0");
699 else if (regd == 1)
700 sprintf (op2, "r1");
702 else if (regd == 2)
703 sprintf (op2, "r2");
705 else
706 sprintf (op2, "r%d", regd);
708 else /* ad == 1. */
710 * cycles += 3;
712 if (regd == 0)
714 /* PC relative. */
715 *cycles += 1;
716 if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
718 sprintf (op2, "0x%04x", PS (dst));
719 sprintf (comm2, "PC rel. 0x%04x",
720 PS ((short) addr + cmd_len + dst));
721 if (extension_word)
723 dst |= extended_dst << 16;
724 if (dst & 0x80000)
725 dst |= -1U << 20;
726 sprintf (op2, "0x%05x", dst & 0xfffff);
727 sprintf (comm2, "PC rel. 0x%05lx",
728 (long)((addr + cmd_len + dst) & 0xfffff));
731 cmd_len += 2;
733 else if (regd == 2)
735 /* Absolute. */
736 if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
738 cmd_len += 2;
739 sprintf (op2, "&0x%04x", PS (dst));
740 if (extension_word)
742 dst |= extended_dst << 16;
743 sprintf (op2, "&0x%05x", dst & 0xfffff);
747 else
749 if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
751 cmd_len += 2;
752 if (dst > 9 || dst < 0)
753 sprintf (comm2, "0x%04x", PS (dst));
754 if (extension_word)
756 dst |= extended_dst << 16;
757 if (dst & 0x80000)
758 dst |= -1U << 20;
759 if (dst > 9 || dst < 0)
760 sprintf (comm2, "0x%05x", dst & 0xfffff);
762 sprintf (op2, "%d(r%d)", dst, regd);
767 return cmd_len;
770 static int
771 msp430_branchinstr (disassemble_info *info,
772 struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED,
773 bfd_vma addr ATTRIBUTE_UNUSED,
774 unsigned short insn,
775 char *op1,
776 char *comm1,
777 int *cycles)
779 int regs = 0, regd = 0;
780 int as = 0;
781 int cmd_len = 2;
782 int dst = 0;
783 unsigned short udst = 0;
785 regd = insn & 0x0f;
786 regs = (insn & 0x0f00) >> 8;
787 as = (insn & 0x0030) >> 4;
789 if (regd != 0) /* Destination register is not a PC. */
790 return 0;
792 /* dst is a source register. */
793 if (as == 0)
795 /* Constants. */
796 if (regs == 3)
798 *cycles = 1;
799 sprintf (op1, "#0");
800 sprintf (comm1, "r3 As==00");
802 else
804 /* Register. */
805 *cycles = 1;
806 sprintf (op1, "r%d", regs);
809 else if (as == 2)
811 * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
813 else if (as == 3)
815 if (regs == 0)
817 /* Absolute. @pc+ */
818 *cycles = 3;
819 if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
821 cmd_len += 2;
822 sprintf (op1, "#0x%04x", PS (udst));
825 else
826 * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
828 else if (as == 1)
830 * cycles = 3;
832 if (regs == 0)
834 /* PC relative. */
835 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
837 cmd_len += 2;
838 (*cycles)++;
839 sprintf (op1, "0x%04x", PS (dst));
840 sprintf (comm1, "PC rel. 0x%04x",
841 PS ((short) addr + 2 + dst));
844 else if (regs == 2)
846 /* Absolute. */
847 if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
849 cmd_len += 2;
850 sprintf (op1, "&0x%04x", PS (udst));
853 else if (regs == 3)
855 (*cycles)--;
856 sprintf (op1, "#1");
857 sprintf (comm1, "r3 As==01");
859 else
861 /* Indexed. */
862 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
864 cmd_len += 2;
865 sprintf (op1, "%d(r%d)", dst, regs);
870 return cmd_len;
873 static int
874 msp430x_calla_instr (disassemble_info * info,
875 bfd_vma addr,
876 unsigned short insn,
877 char * op1,
878 char * comm1,
879 int * cycles)
881 unsigned int ureg = insn & 0xf;
882 int reg = insn & 0xf;
883 int am = (insn & 0xf0) >> 4;
884 int cmd_len = 2;
885 unsigned short udst = 0;
886 int dst = 0;
888 switch (am)
890 case 4: /* CALLA Rdst */
891 *cycles = 1;
892 sprintf (op1, "r%d", reg);
893 break;
895 case 5: /* CALLA x(Rdst) */
896 *cycles = 3;
897 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
899 cmd_len += 2;
900 sprintf (op1, "%d(r%d)", dst, reg);
901 if (reg == 0)
902 sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst));
903 else
904 sprintf (comm1, "0x%05x", dst);
906 break;
908 case 6: /* CALLA @Rdst */
909 *cycles = 2;
910 sprintf (op1, "@r%d", reg);
911 break;
913 case 7: /* CALLA @Rdst+ */
914 *cycles = 2;
915 sprintf (op1, "@r%d+", reg);
916 break;
918 case 8: /* CALLA &abs20 */
919 if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
921 cmd_len += 2;
922 *cycles = 4;
923 sprintf (op1, "&%d", (ureg << 16) + udst);
924 sprintf (comm1, "0x%05x", (ureg << 16) + udst);
926 break;
928 case 9: /* CALLA pcrel-sym */
929 if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
931 cmd_len += 2;
932 *cycles = 4;
933 sprintf (op1, "%d(PC)", (reg << 16) + dst);
934 sprintf (comm1, "PC rel. 0x%05lx",
935 (long) (addr + 2 + dst + (reg << 16)));
937 break;
939 case 11: /* CALLA #imm20 */
940 if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
942 cmd_len += 2;
943 *cycles = 4;
944 sprintf (op1, "#%d", (ureg << 16) + udst);
945 sprintf (comm1, "0x%05x", (ureg << 16) + udst);
947 break;
949 default:
950 strcpy (comm1, _("Warning: unrecognised CALLA addressing mode"));
951 return -1;
954 return cmd_len;
958 print_insn_msp430 (bfd_vma addr, disassemble_info *info)
960 void *stream = info->stream;
961 fprintf_ftype prin = info->fprintf_func;
962 struct msp430_opcode_s *opcode;
963 char op1[32], op2[32], comm1[64], comm2[64];
964 int cmd_len = 0;
965 unsigned short insn;
966 int cycles = 0;
967 char *bc = "";
968 unsigned short extension_word = 0;
969 unsigned short bits;
971 if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
973 prin (stream, ".word 0xffff; ????");
974 return 2;
977 if (((int) addr & 0xffff) > 0xffdf)
979 (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
980 return 2;
983 *comm1 = 0;
984 *comm2 = 0;
986 /* Check for an extension word. */
987 if ((insn & 0xf800) == 0x1800)
989 extension_word = insn;
990 addr += 2;
991 if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
993 prin (stream, ".word 0x%04x, 0xffff; ????",
994 extension_word);
995 return 4;
999 for (opcode = msp430_opcodes; opcode->name; opcode++)
1001 if ((insn & opcode->bin_mask) == opcode->bin_opcode
1002 && opcode->bin_opcode != 0x9300)
1004 *op1 = 0;
1005 *op2 = 0;
1006 *comm1 = 0;
1007 *comm2 = 0;
1009 /* r0 as destination. Ad should be zero. */
1010 if (opcode->insn_opnumb == 3
1011 && (insn & 0x000f) == 0
1012 && (insn & 0x0080) == 0)
1014 cmd_len +=
1015 msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
1016 &cycles);
1017 if (cmd_len)
1018 break;
1021 switch (opcode->insn_opnumb)
1023 int n;
1024 int reg;
1026 case 4:
1027 cmd_len += msp430x_calla_instr (info, addr, insn,
1028 op1, comm1, & cycles);
1029 break;
1031 case 5: /* PUSHM/POPM */
1032 n = (insn & 0xf0) >> 4;
1033 reg = (insn & 0xf);
1035 sprintf (op1, "#%d", n + 1);
1036 if (opcode->bin_opcode == 0x1400)
1037 /* PUSHM */
1038 sprintf (op2, "r%d", reg);
1039 else
1040 /* POPM */
1041 sprintf (op2, "r%d", reg + n);
1042 if (insn & 0x100)
1043 sprintf (comm1, "16-bit words");
1044 else
1046 sprintf (comm1, "20-bit words");
1047 bc =".a";
1050 cycles = 2; /*FIXME*/
1051 cmd_len = 2;
1052 break;
1054 case 6: /* RRAM, RRCM, RRUM, RLAM. */
1055 n = ((insn >> 10) & 0x3) + 1;
1056 reg = (insn & 0xf);
1057 if ((insn & 0x10) == 0)
1058 bc =".a";
1059 sprintf (op1, "#%d", n);
1060 sprintf (op2, "r%d", reg);
1061 cycles = 2; /*FIXME*/
1062 cmd_len = 2;
1063 break;
1065 case 8: /* ADDA, CMPA, SUBA. */
1066 reg = (insn & 0xf);
1067 n = (insn >> 8) & 0xf;
1068 if (insn & 0x40)
1070 sprintf (op1, "r%d", n);
1071 cmd_len = 2;
1073 else
1075 n <<= 16;
1076 if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1078 n |= bits;
1079 sprintf (op1, "#%d", n);
1080 if (n > 9 || n < 0)
1081 sprintf (comm1, "0x%05x", n);
1083 cmd_len = 4;
1085 sprintf (op2, "r%d", reg);
1086 cycles = 2; /*FIXME*/
1087 break;
1089 case 9: /* MOVA */
1090 reg = (insn & 0xf);
1091 n = (insn >> 8) & 0xf;
1092 switch ((insn >> 4) & 0xf)
1094 case 0: /* MOVA @Rsrc, Rdst */
1095 cmd_len = 2;
1096 sprintf (op1, "@r%d", n);
1097 if (strcmp (opcode->name, "bra") != 0)
1098 sprintf (op2, "r%d", reg);
1099 break;
1101 case 1: /* MOVA @Rsrc+, Rdst */
1102 cmd_len = 2;
1103 if (strcmp (opcode->name, "reta") != 0)
1105 sprintf (op1, "@r%d+", n);
1106 if (strcmp (opcode->name, "bra") != 0)
1107 sprintf (op2, "r%d", reg);
1109 break;
1111 case 2: /* MOVA &abs20, Rdst */
1112 cmd_len = 4;
1113 n <<= 16;
1114 if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1116 n |= bits;
1117 sprintf (op1, "&%d", n);
1118 if (n > 9 || n < 0)
1119 sprintf (comm1, "0x%05x", n);
1120 if (strcmp (opcode->name, "bra") != 0)
1121 sprintf (op2, "r%d", reg);
1123 break;
1125 case 3: /* MOVA x(Rsrc), Rdst */
1126 cmd_len = 4;
1127 if (strcmp (opcode->name, "bra") != 0)
1128 sprintf (op2, "r%d", reg);
1129 reg = n;
1130 if (msp430dis_opcode_signed (addr + 2, info, &n, comm1))
1132 sprintf (op1, "%d(r%d)", n, reg);
1133 if (n > 9 || n < 0)
1135 if (reg == 0)
1136 sprintf (comm1, "PC rel. 0x%05lx",
1137 (long) (addr + 2 + n));
1138 else
1139 sprintf (comm1, "0x%05x", n);
1142 break;
1144 case 6: /* MOVA Rsrc, &abs20 */
1145 cmd_len = 4;
1146 reg <<= 16;
1147 if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2))
1149 reg |= bits;
1150 sprintf (op1, "r%d", n);
1151 sprintf (op2, "&%d", reg);
1152 if (reg > 9 || reg < 0)
1153 sprintf (comm2, "0x%05x", reg);
1155 break;
1157 case 7: /* MOVA Rsrc, x(Rdst) */
1158 cmd_len = 4;
1159 sprintf (op1, "r%d", n);
1160 if (msp430dis_opcode_signed (addr + 2, info, &n, comm2))
1162 sprintf (op2, "%d(r%d)", n, reg);
1163 if (n > 9 || n < 0)
1165 if (reg == 0)
1166 sprintf (comm2, "PC rel. 0x%05lx",
1167 (long) (addr + 2 + n));
1168 else
1169 sprintf (comm2, "0x%05x", n);
1172 break;
1174 case 8: /* MOVA #imm20, Rdst */
1175 cmd_len = 4;
1176 n <<= 16;
1177 if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
1179 n |= bits;
1180 if (n & 0x80000)
1181 n |= -1U << 20;
1182 sprintf (op1, "#%d", n);
1183 if (n > 9 || n < 0)
1184 sprintf (comm1, "0x%05x", n);
1185 if (strcmp (opcode->name, "bra") != 0)
1186 sprintf (op2, "r%d", reg);
1188 break;
1190 case 12: /* MOVA Rsrc, Rdst */
1191 cmd_len = 2;
1192 sprintf (op1, "r%d", n);
1193 if (strcmp (opcode->name, "bra") != 0)
1194 sprintf (op2, "r%d", reg);
1195 break;
1197 default:
1198 break;
1200 cycles = 2; /* FIXME */
1201 break;
1204 if (cmd_len)
1205 break;
1207 switch (opcode->insn_opnumb)
1209 case 0:
1210 cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
1211 break;
1212 case 2:
1213 cmd_len +=
1214 msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
1215 comm1, comm2,
1216 extension_word,
1217 &cycles);
1218 if (insn & BYTE_OPERATION)
1220 if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1221 bc = ".a";
1222 else
1223 bc = ".b";
1225 else if (extension_word)
1227 if (extension_word & BYTE_OPERATION)
1228 bc = ".w";
1229 else
1231 bc = ".?";
1232 sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1236 break;
1237 case 1:
1238 cmd_len +=
1239 msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
1240 extension_word,
1241 &cycles);
1242 if (extension_word
1243 && (strcmp (opcode->name, "swpb") == 0
1244 || strcmp (opcode->name, "sxt") == 0))
1246 if (insn & BYTE_OPERATION)
1248 bc = ".?";
1249 sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1251 else if (extension_word & BYTE_OPERATION)
1252 bc = ".w";
1253 else
1254 bc = ".a";
1256 else if (insn & BYTE_OPERATION && opcode->fmt != 3)
1258 if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1259 bc = ".a";
1260 else
1261 bc = ".b";
1263 else if (extension_word)
1265 if (extension_word & (1 << 6))
1266 bc = ".w";
1267 else
1269 bc = ".?";
1270 sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1273 break;
1274 default:
1275 break;
1279 if (cmd_len)
1280 break;
1283 if (cmd_len < 1)
1285 /* Unknown opcode, or invalid combination of operands. */
1286 if (extension_word)
1288 prin (stream, ".word 0x%04x, 0x%04x; ????", extension_word, PS (insn));
1289 if (*comm1)
1290 prin (stream, "\t %s", comm1);
1291 return 4;
1293 (*prin) (stream, ".word 0x%04x; ????", PS (insn));
1294 return 2;
1297 /* Display the repeat count (if set) for extended register mode. */
1298 if (cmd_len == 2 && ((extension_word & 0xf) != 0))
1300 if (extension_word & (1 << 7))
1301 prin (stream, "rpt r%d { ", extension_word & 0xf);
1302 else
1303 prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1);
1306 /* Special case: RRC with an extension word and the ZC bit set is actually RRU. */
1307 if (extension_word
1308 && (extension_word & IGNORE_CARRY_BIT)
1309 && strcmp (opcode->name, "rrc") == 0)
1310 (*prin) (stream, "rrux%s", bc);
1311 else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x')
1312 (*prin) (stream, "%sx%s", opcode->name, bc);
1313 else
1314 (*prin) (stream, "%s%s", opcode->name, bc);
1316 if (*op1)
1317 (*prin) (stream, "\t%s", op1);
1318 if (*op2)
1319 (*prin) (stream, ",");
1321 if (strlen (op1) < 7)
1322 (*prin) (stream, "\t");
1323 if (!strlen (op1))
1324 (*prin) (stream, "\t");
1326 if (*op2)
1327 (*prin) (stream, "%s", op2);
1328 if (strlen (op2) < 8)
1329 (*prin) (stream, "\t");
1331 if (*comm1 || *comm2)
1332 (*prin) (stream, ";");
1333 else if (cycles)
1335 if (*op2)
1336 (*prin) (stream, ";");
1337 else
1339 if (strlen (op1) < 7)
1340 (*prin) (stream, ";");
1341 else
1342 (*prin) (stream, "\t;");
1345 if (*comm1)
1346 (*prin) (stream, "%s", comm1);
1347 if (*comm1 && *comm2)
1348 (*prin) (stream, ",");
1349 if (*comm2)
1350 (*prin) (stream, " %s", comm2);
1352 if (extension_word)
1353 cmd_len += 2;
1355 return cmd_len;