1 /* Disassemble MSP430 instructions.
2    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3 
4    Contributed by Dmitry Diky <diwil@mail.ru>
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <string.h>
23 #include <sys/types.h>
24 
25 #include "dis-asm.h"
26 #include "opintl.h"
27 #include "libiberty.h"
28 
29 #define DASM_SECTION
30 #include "opcode/msp430.h"
31 #undef DASM_SECTION
32 
33 
34 static unsigned short msp430dis_opcode
35   PARAMS ((bfd_vma, disassemble_info *));
36 int print_insn_msp430
37   PARAMS ((bfd_vma, disassemble_info *));
38 int msp430_nooperands
39   PARAMS ((struct msp430_opcode_s *, bfd_vma, unsigned short, char *, int *));
40 int msp430_singleoperand
41   PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
42 	   char *, char *, int *));
43 int msp430_doubleoperand
44   PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
45 	   char *, char *, char *, char *, int *));
46 int msp430_branchinstr
47   PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
48 	   char *, char *, int *));
49 
50 #define PS(x)   (0xffff & (x))
51 
52 static unsigned short
msp430dis_opcode(addr,info)53 msp430dis_opcode (addr, info)
54      bfd_vma addr;
55      disassemble_info *info;
56 {
57   bfd_byte buffer[2];
58   int status;
59 
60   status = info->read_memory_func (addr, buffer, 2, info);
61   if (status != 0)
62     {
63       info->memory_error_func (status, addr, info);
64       return -1;
65     }
66   return bfd_getl16 (buffer);
67 }
68 
69 int
print_insn_msp430(addr,info)70 print_insn_msp430 (addr, info)
71      bfd_vma addr;
72      disassemble_info *info;
73 {
74   void *stream = info->stream;
75   fprintf_ftype prin = info->fprintf_func;
76   struct msp430_opcode_s *opcode;
77   char op1[32], op2[32], comm1[64], comm2[64];
78   int cmd_len = 0;
79   unsigned short insn;
80   int cycles = 0;
81   char *bc = "";
82   char dinfo[32];		/* Debug purposes.  */
83 
84   insn = msp430dis_opcode (addr, info);
85   sprintf (dinfo, "0x%04x", insn);
86 
87   if (((int) addr & 0xffff) > 0xffdf)
88     {
89       (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
90       return 2;
91     }
92 
93   *comm1 = 0;
94   *comm2 = 0;
95 
96   for (opcode = msp430_opcodes; opcode->name; opcode++)
97     {
98       if ((insn & opcode->bin_mask) == opcode->bin_opcode
99 	  && opcode->bin_opcode != 0x9300)
100 	{
101 	  *op1 = 0;
102 	  *op2 = 0;
103 	  *comm1 = 0;
104 	  *comm2 = 0;
105 
106 	  /* r0 as destination. Ad should be zero.  */
107 	  if (opcode->insn_opnumb == 3 && (insn & 0x000f) == 0
108 	      && (0x0080 & insn) == 0)
109 	    {
110 	      cmd_len =
111 		msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
112 				    &cycles);
113 	      if (cmd_len)
114 		break;
115 	    }
116 
117 	  switch (opcode->insn_opnumb)
118 	    {
119 	    case 0:
120 	      cmd_len = msp430_nooperands (opcode, addr, insn, comm1, &cycles);
121 	      break;
122 	    case 2:
123 	      cmd_len =
124 		msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
125 				      comm1, comm2, &cycles);
126 	      if (insn & BYTE_OPERATION)
127 		bc = ".b";
128 	      break;
129 	    case 1:
130 	      cmd_len =
131 		msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
132 				      &cycles);
133 	      if (insn & BYTE_OPERATION && opcode->fmt != 3)
134 		bc = ".b";
135 	      break;
136 	    default:
137 	      break;
138 	    }
139 	}
140 
141       if (cmd_len)
142 	break;
143     }
144 
145   dinfo[5] = 0;
146 
147   if (cmd_len < 1)
148     {
149       /* Unknown opcode, or invalid combination of operands.  */
150       (*prin) (stream, ".word	0x%04x;	????", PS (insn));
151       return 2;
152     }
153 
154   (*prin) (stream, "%s%s", opcode->name, bc);
155 
156   if (*op1)
157     (*prin) (stream, "\t%s", op1);
158   if (*op2)
159     (*prin) (stream, ",");
160 
161   if (strlen (op1) < 7)
162     (*prin) (stream, "\t");
163   if (!strlen (op1))
164     (*prin) (stream, "\t");
165 
166   if (*op2)
167     (*prin) (stream, "%s", op2);
168   if (strlen (op2) < 8)
169     (*prin) (stream, "\t");
170 
171   if (*comm1 || *comm2)
172     (*prin) (stream, ";");
173   else if (cycles)
174     {
175       if (*op2)
176 	(*prin) (stream, ";");
177       else
178 	{
179 	  if (strlen (op1) < 7)
180 	    (*prin) (stream, ";");
181 	  else
182 	    (*prin) (stream, "\t;");
183 	}
184     }
185   if (*comm1)
186     (*prin) (stream, "%s", comm1);
187   if (*comm1 && *comm2)
188     (*prin) (stream, ",");
189   if (*comm2)
190     (*prin) (stream, " %s", comm2);
191   return cmd_len;
192 }
193 
194 int
msp430_nooperands(opcode,addr,insn,comm,cycles)195 msp430_nooperands (opcode, addr, insn, comm, cycles)
196      struct msp430_opcode_s *opcode;
197      bfd_vma addr ATTRIBUTE_UNUSED;
198      unsigned short insn ATTRIBUTE_UNUSED;
199      char *comm;
200      int *cycles;
201 {
202   /* Pop with constant.  */
203   if (insn == 0x43b2)
204     return 0;
205   if (insn == opcode->bin_opcode)
206     return 2;
207 
208   if (opcode->fmt == 0)
209     {
210       if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2)
211 	return 0;
212 
213       strcpy (comm, "emulated...");
214       *cycles = 1;
215     }
216   else
217     {
218       strcpy (comm, "return from interupt");
219       *cycles = 5;
220     }
221 
222   return 2;
223 }
224 
225 
226 int
msp430_singleoperand(info,opcode,addr,insn,op,comm,cycles)227 msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles)
228      disassemble_info *info;
229      struct msp430_opcode_s *opcode;
230      bfd_vma addr;
231      unsigned short insn;
232      char *op;
233      char *comm;
234      int *cycles;
235 {
236   int regs = 0, regd = 0;
237   int ad = 0, as = 0;
238   int where = 0;
239   int cmd_len = 2;
240   short dst = 0;
241 
242   regd = insn & 0x0f;
243   regs = (insn & 0x0f00) >> 8;
244   as = (insn & 0x0030) >> 4;
245   ad = (insn & 0x0080) >> 7;
246 
247   switch (opcode->fmt)
248     {
249     case 0:			/* Emulated work with dst register.  */
250       if (regs != 2 && regs != 3 && regs != 1)
251 	return 0;
252 
253       /* Check if not clr insn.  */
254       if (opcode->bin_opcode == 0x4300 && (ad || as))
255 	return 0;
256 
257       /* Check if really inc, incd insns.  */
258       if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
259 	return 0;
260 
261       if (ad == 0)
262 	{
263 	  *cycles = 1;
264 
265 	  /* Register.  */
266 	  if (regd == 0)
267 	    {
268 	      *cycles += 1;
269 	      sprintf (op, "r0");
270 	    }
271 	  else if (regd == 1)
272 	    sprintf (op, "r1");
273 
274 	  else if (regd == 2)
275 	    sprintf (op, "r2");
276 
277 	  else
278 	    sprintf (op, "r%d", regd);
279 	}
280       else			/* ad == 1 msp430dis_opcode.  */
281 	{
282 	  if (regd == 0)
283 	    {
284 	      /* PC relative.  */
285 	      dst = msp430dis_opcode (addr + 2, info);
286 	      cmd_len += 2;
287 	      *cycles = 4;
288 	      sprintf (op, "0x%04x", dst);
289 	      sprintf (comm, "PC rel. abs addr 0x%04x",
290 		       PS ((short) (addr + 2) + dst));
291 	    }
292 	  else if (regd == 2)
293 	    {
294 	      /* Absolute.  */
295 	      dst = msp430dis_opcode (addr + 2, info);
296 	      cmd_len += 2;
297 	      *cycles = 4;
298 	      sprintf (op, "&0x%04x", PS (dst));
299 	    }
300 	  else
301 	    {
302 	      dst = msp430dis_opcode (addr + 2, info);
303 	      cmd_len += 2;
304 	      *cycles = 4;
305 	      sprintf (op, "%d(r%d)", dst, regd);
306 	    }
307 	}
308       break;
309 
310     case 2:	/* rrc, push, call, swpb, rra, sxt, push, call, reti etc...  */
311 
312       if (as == 0)
313 	{
314 	  if (regd == 3)
315 	    {
316 	      /* Constsnts.  */
317 	      sprintf (op, "#0");
318 	      sprintf (comm, "r3 As==00");
319 	    }
320 	  else
321 	    {
322 	      /* Register.  */
323 	      sprintf (op, "r%d", regd);
324 	    }
325 	  *cycles = 1;
326 	}
327       else if (as == 2)
328 	{
329 	  *cycles = 1;
330 	  if (regd == 2)
331 	    {
332 	      sprintf (op, "#4");
333 	      sprintf (comm, "r2 As==10");
334 	    }
335 	  else if (regd == 3)
336 	    {
337 	      sprintf (op, "#2");
338 	      sprintf (comm, "r3 As==10");
339 	    }
340 	  else
341 	    {
342 	      *cycles = 3;
343 	      /* Indexed register mode @Rn.  */
344 	      sprintf (op, "@r%d", regd);
345 	    }
346 	}
347       else if (as == 3)
348 	{
349 	  *cycles = 1;
350 	  if (regd == 2)
351 	    {
352 	      sprintf (op, "#8");
353 	      sprintf (comm, "r2 As==11");
354 	    }
355 	  else if (regd == 3)
356 	    {
357 	      sprintf (op, "#-1");
358 	      sprintf (comm, "r3 As==11");
359 	    }
360 	  else if (regd == 0)
361 	    {
362 	      *cycles = 3;
363 	      /* absolute. @pc+ */
364 	      dst = msp430dis_opcode (addr + 2, info);
365 	      cmd_len += 2;
366 	      sprintf (op, "#%d", dst);
367 	      sprintf (comm, "#0x%04x", PS (dst));
368 	    }
369 	  else
370 	    {
371 	      *cycles = 3;
372 	      sprintf (op, "@r%d+", regd);
373 	    }
374 	}
375       else if (as == 1)
376 	{
377 	  *cycles = 4;
378 	  if (regd == 0)
379 	    {
380 	      /* PC relative.  */
381 	      dst = msp430dis_opcode (addr + 2, info);
382 	      cmd_len += 2;
383 	      sprintf (op, "0x%04x", PS (dst));
384 	      sprintf (comm, "PC rel. 0x%04x",
385 		       PS ((short) addr + 2 + dst));
386 	    }
387 	  else if (regd == 2)
388 	    {
389 	      /* Absolute.  */
390 	      dst = msp430dis_opcode (addr + 2, info);
391 	      cmd_len += 2;
392 	      sprintf (op, "&0x%04x", PS (dst));
393 	    }
394 	  else if (regd == 3)
395 	    {
396 	      *cycles = 1;
397 	      sprintf (op, "#1");
398 	      sprintf (comm, "r3 As==01");
399 	    }
400 	  else
401 	    {
402 	      /* Indexd.  */
403 	      dst = msp430dis_opcode (addr + 2, info);
404 	      cmd_len += 2;
405 	      sprintf (op, "%d(r%d)", dst, regd);
406 	    }
407 	}
408       break;
409 
410     case 3:			/* Jumps.  */
411       where = insn & 0x03ff;
412       if (where & 0x200)
413 	where |= ~0x03ff;
414       if (where > 512 || where < -511)
415 	return 0;
416 
417       where *= 2;
418       sprintf (op, "$%+-8d", where + 2);
419       sprintf (comm, "abs 0x%x", PS ((short) (addr) + 2 + where));
420       *cycles = 2;
421       return 2;
422       break;
423     default:
424       cmd_len = 0;
425     }
426 
427   return cmd_len;
428 }
429 
430 int
msp430_doubleoperand(info,opcode,addr,insn,op1,op2,comm1,comm2,cycles)431 msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles)
432      disassemble_info *info;
433      struct msp430_opcode_s *opcode;
434      bfd_vma addr;
435      unsigned short insn;
436      char *op1, *op2;
437      char *comm1, *comm2;
438      int *cycles;
439 {
440   int regs = 0, regd = 0;
441   int ad = 0, as = 0;
442   int cmd_len = 2;
443   short dst = 0;
444 
445   regd = insn & 0x0f;
446   regs = (insn & 0x0f00) >> 8;
447   as = (insn & 0x0030) >> 4;
448   ad = (insn & 0x0080) >> 7;
449 
450   if (opcode->fmt == 0)
451     {
452       /* Special case: rla and rlc are the only 2 emulated instructions that
453 	 fall into two operand instructions.  */
454       /* With dst, there are only:
455 	 Rm       	Register,
456          x(Rm)     	Indexed,
457          0xXXXX    	Relative,
458          &0xXXXX    	Absolute
459          emulated_ins   dst
460          basic_ins      dst, dst.  */
461 
462       if (regd != regs || as != ad)
463 	return 0;		/* May be 'data' section.  */
464 
465       if (ad == 0)
466 	{
467 	  /* Register mode.  */
468 	  if (regd == 3)
469 	    {
470 	      strcpy (comm1, "Illegal as emulation instr");
471 	      return -1;
472 	    }
473 
474 	  sprintf (op1, "r%d", regd);
475 	  *cycles = 1;
476 	}
477       else			/* ad == 1 */
478 	{
479 	  if (regd == 0)
480 	    {
481 	      /* PC relative, Symbolic.  */
482 	      dst = msp430dis_opcode (addr + 2, info);
483 	      cmd_len += 4;
484 	      *cycles = 6;
485 	      sprintf (op1, "0x%04x", PS (dst));
486 	      sprintf (comm1, "PC rel. 0x%04x",
487 		       PS ((short) addr + 2 + dst));
488 
489 	    }
490 	  else if (regd == 2)
491 	    {
492 	      /* Absolute.  */
493 	      dst = msp430dis_opcode (addr + 2, info);
494 	      /* If the 'src' field is not the same as the dst
495 		 then this is not an rla instruction.  */
496 	      if (dst != msp430dis_opcode (addr + 4, info))
497 		return 0;
498 	      cmd_len += 4;
499 	      *cycles = 6;
500 	      sprintf (op1, "&0x%04x", PS (dst));
501 	    }
502 	  else
503 	    {
504 	      /* Indexed.  */
505 	      dst = msp430dis_opcode (addr + 2, info);
506 	      cmd_len += 4;
507 	      *cycles = 6;
508 	      sprintf (op1, "%d(r%d)", dst, regd);
509 	    }
510 	}
511 
512       *op2 = 0;
513       *comm2 = 0;
514       return cmd_len;
515     }
516 
517   /* Two operands exactly.  */
518   if (ad == 0 && regd == 3)
519     {
520       /* R2/R3 are illegal as dest: may be data section.  */
521       strcpy (comm1, "Illegal as 2-op instr");
522       return -1;
523     }
524 
525   /* Source.  */
526   if (as == 0)
527     {
528       *cycles = 1;
529       if (regs == 3)
530 	{
531 	  /* Constsnts.  */
532 	  sprintf (op1, "#0");
533 	  sprintf (comm1, "r3 As==00");
534 	}
535       else
536 	{
537 	  /* Register.  */
538 	  sprintf (op1, "r%d", regs);
539 	}
540     }
541   else if (as == 2)
542     {
543       *cycles = 1;
544 
545       if (regs == 2)
546 	{
547 	  sprintf (op1, "#4");
548 	  sprintf (comm1, "r2 As==10");
549 	}
550       else if (regs == 3)
551 	{
552 	  sprintf (op1, "#2");
553 	  sprintf (comm1, "r3 As==10");
554 	}
555       else
556 	{
557 	  *cycles = 2;
558 
559 	  /* Indexed register mode @Rn.  */
560 	  sprintf (op1, "@r%d", regs);
561 	}
562       if (!regs)
563 	*cycles = 3;
564     }
565   else if (as == 3)
566     {
567       if (regs == 2)
568 	{
569 	  sprintf (op1, "#8");
570 	  sprintf (comm1, "r2 As==11");
571 	  *cycles = 1;
572 	}
573       else if (regs == 3)
574 	{
575 	  sprintf (op1, "#-1");
576 	  sprintf (comm1, "r3 As==11");
577 	  *cycles = 1;
578 	}
579       else if (regs == 0)
580 	{
581 	  *cycles = 3;
582 	  /* Absolute. @pc+  */
583 	  dst = msp430dis_opcode (addr + 2, info);
584 	  cmd_len += 2;
585 	  sprintf (op1, "#%d", dst);
586 	  sprintf (comm1, "#0x%04x", PS (dst));
587 	}
588       else
589 	{
590 	  *cycles = 2;
591 	  sprintf (op1, "@r%d+", regs);
592 	}
593     }
594   else if (as == 1)
595     {
596       if (regs == 0)
597 	{
598 	  *cycles = 4;
599 	  /* PC relative.  */
600 	  dst = msp430dis_opcode (addr + 2, info);
601 	  cmd_len += 2;
602 	  sprintf (op1, "0x%04x", PS (dst));
603 	  sprintf (comm1, "PC rel. 0x%04x",
604 		   PS ((short) addr + 2 + dst));
605 	}
606       else if (regs == 2)
607 	{
608 	  *cycles = 2;
609 	  /* Absolute.  */
610 	  dst = msp430dis_opcode (addr + 2, info);
611 	  cmd_len += 2;
612 	  sprintf (op1, "&0x%04x", PS (dst));
613 	  sprintf (comm1, "0x%04x", PS (dst));
614 	}
615       else if (regs == 3)
616 	{
617 	  *cycles = 1;
618 	  sprintf (op1, "#1");
619 	  sprintf (comm1, "r3 As==01");
620 	}
621       else
622 	{
623 	  *cycles = 3;
624 	  /* Indexed.  */
625 	  dst = msp430dis_opcode (addr + 2, info);
626 	  cmd_len += 2;
627 	  sprintf (op1, "%d(r%d)", dst, regs);
628 	}
629     }
630 
631   /* Destination. Special care needed on addr + XXXX.  */
632 
633   if (ad == 0)
634     {
635       /* Register.  */
636       if (regd == 0)
637 	{
638 	  *cycles += 1;
639 	  sprintf (op2, "r0");
640 	}
641       else if (regd == 1)
642 	sprintf (op2, "r1");
643 
644       else if (regd == 2)
645 	sprintf (op2, "r2");
646 
647       else
648 	sprintf (op2, "r%d", regd);
649     }
650   else				/* ad == 1.  */
651     {
652       * cycles += 3;
653 
654       if (regd == 0)
655 	{
656 	  /* PC relative.  */
657 	  *cycles += 1;
658 	  dst = msp430dis_opcode (addr + cmd_len, info);
659 	  sprintf (op2, "0x%04x", PS (dst));
660 	  sprintf (comm2, "PC rel. 0x%04x",
661 		   PS ((short) addr + cmd_len + dst));
662 	  cmd_len += 2;
663 	}
664       else if (regd == 2)
665 	{
666 	  /* Absolute.  */
667 	  dst = msp430dis_opcode (addr + cmd_len, info);
668 	  cmd_len += 2;
669 	  sprintf (op2, "&0x%04x", PS (dst));
670 	}
671       else
672 	{
673 	  dst = msp430dis_opcode (addr + cmd_len, info);
674 	  cmd_len += 2;
675 	  sprintf (op2, "%d(r%d)", dst, regd);
676 	}
677     }
678 
679   return cmd_len;
680 }
681 
682 
683 int
msp430_branchinstr(info,opcode,addr,insn,op1,comm1,cycles)684 msp430_branchinstr (info, opcode, addr, insn, op1, comm1, cycles)
685      disassemble_info *info;
686      struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED;
687      bfd_vma addr ATTRIBUTE_UNUSED;
688      unsigned short insn;
689      char *op1;
690      char *comm1;
691      int *cycles;
692 {
693   int regs = 0, regd = 0;
694   int ad = 0, as = 0;
695   int cmd_len = 2;
696   short dst = 0;
697 
698   regd = insn & 0x0f;
699   regs = (insn & 0x0f00) >> 8;
700   as = (insn & 0x0030) >> 4;
701   ad = (insn & 0x0080) >> 7;
702 
703   if (regd != 0)	/* Destination register is not a PC.  */
704     return 0;
705 
706   /* dst is a source register.  */
707   if (as == 0)
708     {
709       /* Constants.  */
710       if (regs == 3)
711 	{
712 	  *cycles = 1;
713 	  sprintf (op1, "#0");
714 	  sprintf (comm1, "r3 As==00");
715 	}
716       else
717 	{
718 	  /* Register.  */
719 	  *cycles = 1;
720 	  sprintf (op1, "r%d", regs);
721 	}
722     }
723   else if (as == 2)
724     {
725       if (regs == 2)
726 	{
727 	  *cycles = 2;
728 	  sprintf (op1, "#4");
729 	  sprintf (comm1, "r2 As==10");
730 	}
731       else if (regs == 3)
732 	{
733 	  *cycles = 1;
734 	  sprintf (op1, "#2");
735 	  sprintf (comm1, "r3 As==10");
736 	}
737       else
738 	{
739 	  /* Indexed register mode @Rn.  */
740 	  *cycles = 2;
741 	  sprintf (op1, "@r%d", regs);
742 	}
743     }
744   else if (as == 3)
745     {
746       if (regs == 2)
747 	{
748 	  *cycles = 1;
749 	  sprintf (op1, "#8");
750 	  sprintf (comm1, "r2 As==11");
751 	}
752       else if (regs == 3)
753 	{
754 	  *cycles = 1;
755 	  sprintf (op1, "#-1");
756 	  sprintf (comm1, "r3 As==11");
757 	}
758       else if (regs == 0)
759 	{
760 	  /* Absolute. @pc+  */
761 	  *cycles = 3;
762 	  dst = msp430dis_opcode (addr + 2, info);
763 	  cmd_len += 2;
764 	  sprintf (op1, "#0x%04x", PS (dst));
765 	}
766       else
767 	{
768 	  *cycles = 2;
769 	  sprintf (op1, "@r%d+", regs);
770 	}
771     }
772   else if (as == 1)
773     {
774       * cycles = 3;
775 
776       if (regs == 0)
777 	{
778 	  /* PC relative.  */
779 	  dst = msp430dis_opcode (addr + 2, info);
780 	  cmd_len += 2;
781 	  (*cycles)++;
782 	  sprintf (op1, "0x%04x", PS (dst));
783 	  sprintf (comm1, "PC rel. 0x%04x",
784 		   PS ((short) addr + 2 + dst));
785 	}
786       else if (regs == 2)
787 	{
788 	  /* Absolute.  */
789 	  dst = msp430dis_opcode (addr + 2, info);
790 	  cmd_len += 2;
791 	  sprintf (op1, "&0x%04x", PS (dst));
792 	}
793       else if (regs == 3)
794 	{
795 	  (*cycles)--;
796 	  sprintf (op1, "#1");
797 	  sprintf (comm1, "r3 As==01");
798 	}
799       else
800 	{
801 	  /* Indexd.  */
802 	  dst = msp430dis_opcode (addr + 2, info);
803 	  cmd_len += 2;
804 	  sprintf (op1, "%d(r%d)", dst, regs);
805 	}
806     }
807 
808   return cmd_len;
809 }
810