msp430-dis.c revision 1.1 1 1.1 christos /* Disassemble MSP430 instructions.
2 1.1 christos Copyright (C) 2002-2013 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Contributed by Dmitry Diky <diwil (at) mail.ru>
5 1.1 christos
6 1.1 christos This file is part of the GNU opcodes library.
7 1.1 christos
8 1.1 christos This library is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3, or (at your option)
11 1.1 christos any later version.
12 1.1 christos
13 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
14 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 1.1 christos License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program; if not, write to the Free Software
20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include <stdio.h>
25 1.1 christos #include <ctype.h>
26 1.1 christos #include <sys/types.h>
27 1.1 christos
28 1.1 christos #include "dis-asm.h"
29 1.1 christos #include "opintl.h"
30 1.1 christos #include "libiberty.h"
31 1.1 christos
32 1.1 christos #define DASM_SECTION
33 1.1 christos #include "opcode/msp430.h"
34 1.1 christos #undef DASM_SECTION
35 1.1 christos
36 1.1 christos
37 1.1 christos #define PS(x) (0xffff & (x))
38 1.1 christos
39 1.1 christos static unsigned short
40 1.1 christos msp430dis_opcode (bfd_vma addr, disassemble_info *info)
41 1.1 christos {
42 1.1 christos bfd_byte buffer[2];
43 1.1 christos int status;
44 1.1 christos
45 1.1 christos status = info->read_memory_func (addr, buffer, 2, info);
46 1.1 christos if (status != 0)
47 1.1 christos {
48 1.1 christos info->memory_error_func (status, addr, info);
49 1.1 christos return -1;
50 1.1 christos }
51 1.1 christos return bfd_getl16 (buffer);
52 1.1 christos }
53 1.1 christos
54 1.1 christos static int
55 1.1 christos msp430_nooperands (struct msp430_opcode_s *opcode,
56 1.1 christos bfd_vma addr ATTRIBUTE_UNUSED,
57 1.1 christos unsigned short insn ATTRIBUTE_UNUSED,
58 1.1 christos char *comm,
59 1.1 christos int *cycles)
60 1.1 christos {
61 1.1 christos /* Pop with constant. */
62 1.1 christos if (insn == 0x43b2)
63 1.1 christos return 0;
64 1.1 christos if (insn == opcode->bin_opcode)
65 1.1 christos return 2;
66 1.1 christos
67 1.1 christos if (opcode->fmt == 0)
68 1.1 christos {
69 1.1 christos if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2)
70 1.1 christos return 0;
71 1.1 christos
72 1.1 christos strcpy (comm, "emulated...");
73 1.1 christos *cycles = 1;
74 1.1 christos }
75 1.1 christos else
76 1.1 christos {
77 1.1 christos strcpy (comm, "return from interupt");
78 1.1 christos *cycles = 5;
79 1.1 christos }
80 1.1 christos
81 1.1 christos return 2;
82 1.1 christos }
83 1.1 christos
84 1.1 christos static int
85 1.1 christos print_as2_reg_name (int regno, char * op1, char * comm1,
86 1.1 christos int c2, int c3, int cd)
87 1.1 christos {
88 1.1 christos switch (regno)
89 1.1 christos {
90 1.1 christos case 2:
91 1.1 christos sprintf (op1, "#4");
92 1.1 christos sprintf (comm1, "r2 As==10");
93 1.1 christos return c2;
94 1.1 christos
95 1.1 christos case 3:
96 1.1 christos sprintf (op1, "#2");
97 1.1 christos sprintf (comm1, "r3 As==10");
98 1.1 christos return c3;
99 1.1 christos
100 1.1 christos default:
101 1.1 christos /* Indexed register mode @Rn. */
102 1.1 christos sprintf (op1, "@r%d", regno);
103 1.1 christos return cd;
104 1.1 christos }
105 1.1 christos }
106 1.1 christos
107 1.1 christos static int
108 1.1 christos print_as3_reg_name (int regno, char * op1, char * comm1,
109 1.1 christos int c2, int c3, int cd)
110 1.1 christos {
111 1.1 christos switch (regno)
112 1.1 christos {
113 1.1 christos case 2:
114 1.1 christos sprintf (op1, "#8");
115 1.1 christos sprintf (comm1, "r2 As==11");
116 1.1 christos return c2;
117 1.1 christos
118 1.1 christos case 3:
119 1.1 christos sprintf (op1, "#-1");
120 1.1 christos sprintf (comm1, "r3 As==11");
121 1.1 christos return c3;
122 1.1 christos
123 1.1 christos default:
124 1.1 christos /* Post incremented @Rn+. */
125 1.1 christos sprintf (op1, "@r%d+", regno);
126 1.1 christos return cd;
127 1.1 christos }
128 1.1 christos }
129 1.1 christos
130 1.1 christos static int
131 1.1 christos msp430_singleoperand (disassemble_info *info,
132 1.1 christos struct msp430_opcode_s *opcode,
133 1.1 christos bfd_vma addr,
134 1.1 christos unsigned short insn,
135 1.1 christos char *op,
136 1.1 christos char *comm,
137 1.1 christos unsigned short extension_word,
138 1.1 christos int *cycles)
139 1.1 christos {
140 1.1 christos int regs = 0, regd = 0;
141 1.1 christos int ad = 0, as = 0;
142 1.1 christos int where = 0;
143 1.1 christos int cmd_len = 2;
144 1.1 christos int dst = 0;
145 1.1 christos int fmt;
146 1.1 christos int extended_dst = extension_word & 0xf;
147 1.1 christos
148 1.1 christos regd = insn & 0x0f;
149 1.1 christos regs = (insn & 0x0f00) >> 8;
150 1.1 christos as = (insn & 0x0030) >> 4;
151 1.1 christos ad = (insn & 0x0080) >> 7;
152 1.1 christos
153 1.1 christos if (opcode->fmt < 0)
154 1.1 christos fmt = (- opcode->fmt) - 1;
155 1.1 christos else
156 1.1 christos fmt = opcode->fmt;
157 1.1 christos
158 1.1 christos switch (fmt)
159 1.1 christos {
160 1.1 christos case 0: /* Emulated work with dst register. */
161 1.1 christos if (regs != 2 && regs != 3 && regs != 1)
162 1.1 christos return 0;
163 1.1 christos
164 1.1 christos /* Check if not clr insn. */
165 1.1 christos if (opcode->bin_opcode == 0x4300 && (ad || as))
166 1.1 christos return 0;
167 1.1 christos
168 1.1 christos /* Check if really inc, incd insns. */
169 1.1 christos if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
170 1.1 christos return 0;
171 1.1 christos
172 1.1 christos if (ad == 0)
173 1.1 christos {
174 1.1 christos *cycles = 1;
175 1.1 christos
176 1.1 christos /* Register. */
177 1.1 christos if (regd == 0)
178 1.1 christos {
179 1.1 christos *cycles += 1;
180 1.1 christos sprintf (op, "r0");
181 1.1 christos }
182 1.1 christos else if (regd == 1)
183 1.1 christos sprintf (op, "r1");
184 1.1 christos
185 1.1 christos else if (regd == 2)
186 1.1 christos sprintf (op, "r2");
187 1.1 christos
188 1.1 christos else
189 1.1 christos sprintf (op, "r%d", regd);
190 1.1 christos }
191 1.1 christos else /* ad == 1 msp430dis_opcode. */
192 1.1 christos {
193 1.1 christos if (regd == 0)
194 1.1 christos {
195 1.1 christos /* PC relative. */
196 1.1 christos dst = msp430dis_opcode (addr + 2, info);
197 1.1 christos cmd_len += 2;
198 1.1 christos *cycles = 4;
199 1.1 christos sprintf (op, "0x%04x", dst);
200 1.1 christos sprintf (comm, "PC rel. abs addr 0x%04x",
201 1.1 christos PS ((short) (addr + 2) + dst));
202 1.1 christos if (extended_dst)
203 1.1 christos {
204 1.1 christos dst |= extended_dst << 16;
205 1.1 christos sprintf (op, "0x%05x", dst);
206 1.1 christos sprintf (comm, "PC rel. abs addr 0x%05lx",
207 1.1 christos (long)((addr + 2 + dst) & 0xfffff));
208 1.1 christos }
209 1.1 christos }
210 1.1 christos else if (regd == 2)
211 1.1 christos {
212 1.1 christos /* Absolute. */
213 1.1 christos dst = msp430dis_opcode (addr + 2, info);
214 1.1 christos cmd_len += 2;
215 1.1 christos *cycles = 4;
216 1.1 christos sprintf (op, "&0x%04x", PS (dst));
217 1.1 christos if (extended_dst)
218 1.1 christos {
219 1.1 christos dst |= extended_dst << 16;
220 1.1 christos sprintf (op, "&0x%05x", dst & 0xfffff);
221 1.1 christos }
222 1.1 christos }
223 1.1 christos else
224 1.1 christos {
225 1.1 christos dst = msp430dis_opcode (addr + 2, info);
226 1.1 christos cmd_len += 2;
227 1.1 christos *cycles = 4;
228 1.1 christos if (extended_dst)
229 1.1 christos {
230 1.1 christos dst |= extended_dst << 16;
231 1.1 christos if (dst & 0x80000)
232 1.1 christos dst |= -1 << 20;
233 1.1 christos }
234 1.1 christos else if (dst & 0x8000)
235 1.1 christos dst |= -1 << 16;
236 1.1 christos sprintf (op, "%d(r%d)", dst, regd);
237 1.1 christos }
238 1.1 christos }
239 1.1 christos break;
240 1.1 christos
241 1.1 christos case 2: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */
242 1.1 christos if (as == 0)
243 1.1 christos {
244 1.1 christos if (regd == 3)
245 1.1 christos {
246 1.1 christos /* Constsnts. */
247 1.1 christos sprintf (op, "#0");
248 1.1 christos sprintf (comm, "r3 As==00");
249 1.1 christos }
250 1.1 christos else
251 1.1 christos {
252 1.1 christos /* Register. */
253 1.1 christos sprintf (op, "r%d", regd);
254 1.1 christos }
255 1.1 christos *cycles = 1;
256 1.1 christos }
257 1.1 christos else if (as == 2)
258 1.1 christos {
259 1.1 christos * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
260 1.1 christos }
261 1.1 christos else if (as == 3)
262 1.1 christos {
263 1.1 christos if (regd == 0)
264 1.1 christos {
265 1.1 christos *cycles = 3;
266 1.1 christos /* absolute. @pc+ */
267 1.1 christos dst = msp430dis_opcode (addr + 2, info);
268 1.1 christos cmd_len += 2;
269 1.1 christos sprintf (op, "#%d", dst);
270 1.1 christos if (dst > 9 || dst < 0)
271 1.1 christos sprintf (comm, "#0x%04x", PS (dst));
272 1.1 christos if (extended_dst)
273 1.1 christos {
274 1.1 christos dst |= extended_dst << 16;
275 1.1 christos if (dst & 0x80000)
276 1.1 christos dst |= -1 << 20;
277 1.1 christos sprintf (op, "#%d", dst);
278 1.1 christos if (dst > 9 || dst < 0)
279 1.1 christos sprintf (comm, "#0x%05x", dst);
280 1.1 christos }
281 1.1 christos }
282 1.1 christos else
283 1.1 christos * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
284 1.1 christos }
285 1.1 christos else if (as == 1)
286 1.1 christos {
287 1.1 christos *cycles = 4;
288 1.1 christos if (regd == 0)
289 1.1 christos {
290 1.1 christos /* PC relative. */
291 1.1 christos dst = msp430dis_opcode (addr + 2, info);
292 1.1 christos cmd_len += 2;
293 1.1 christos sprintf (op, "0x%04x", PS (dst));
294 1.1 christos sprintf (comm, "PC rel. 0x%04x",
295 1.1 christos PS ((short) addr + 2 + dst));
296 1.1 christos if (extended_dst)
297 1.1 christos {
298 1.1 christos dst |= extended_dst << 16;
299 1.1 christos sprintf (op, "0x%05x", dst & 0xffff);
300 1.1 christos sprintf (comm, "PC rel. 0x%05lx",
301 1.1 christos (long)((addr + 2 + dst) & 0xfffff));
302 1.1 christos }
303 1.1 christos }
304 1.1 christos else if (regd == 2)
305 1.1 christos {
306 1.1 christos /* Absolute. */
307 1.1 christos dst = msp430dis_opcode (addr + 2, info);
308 1.1 christos cmd_len += 2;
309 1.1 christos sprintf (op, "&0x%04x", PS (dst));
310 1.1 christos if (extended_dst)
311 1.1 christos {
312 1.1 christos dst |= extended_dst << 16;
313 1.1 christos sprintf (op, "&0x%05x", dst & 0xfffff);
314 1.1 christos }
315 1.1 christos }
316 1.1 christos else if (regd == 3)
317 1.1 christos {
318 1.1 christos *cycles = 1;
319 1.1 christos sprintf (op, "#1");
320 1.1 christos sprintf (comm, "r3 As==01");
321 1.1 christos }
322 1.1 christos else
323 1.1 christos {
324 1.1 christos /* Indexed. */
325 1.1 christos dst = msp430dis_opcode (addr + 2, info);
326 1.1 christos cmd_len += 2;
327 1.1 christos if (extended_dst)
328 1.1 christos {
329 1.1 christos dst |= extended_dst << 16;
330 1.1 christos if (dst & 0x80000)
331 1.1 christos dst |= -1 << 20;
332 1.1 christos }
333 1.1 christos else if (dst & 0x8000)
334 1.1 christos dst |= -1 << 16;
335 1.1 christos sprintf (op, "%d(r%d)", dst, regd);
336 1.1 christos if (dst > 9 || dst < 0)
337 1.1 christos sprintf (comm, "%05x", dst);
338 1.1 christos }
339 1.1 christos }
340 1.1 christos break;
341 1.1 christos
342 1.1 christos case 3: /* Jumps. */
343 1.1 christos where = insn & 0x03ff;
344 1.1 christos if (where & 0x200)
345 1.1 christos where |= ~0x03ff;
346 1.1 christos if (where > 512 || where < -511)
347 1.1 christos return 0;
348 1.1 christos
349 1.1 christos where *= 2;
350 1.1 christos sprintf (op, "$%+-8d", where + 2);
351 1.1 christos sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
352 1.1 christos *cycles = 2;
353 1.1 christos return 2;
354 1.1 christos break;
355 1.1 christos default:
356 1.1 christos cmd_len = 0;
357 1.1 christos }
358 1.1 christos
359 1.1 christos return cmd_len;
360 1.1 christos }
361 1.1 christos
362 1.1 christos static int
363 1.1 christos msp430_doubleoperand (disassemble_info *info,
364 1.1 christos struct msp430_opcode_s *opcode,
365 1.1 christos bfd_vma addr,
366 1.1 christos unsigned short insn,
367 1.1 christos char *op1,
368 1.1 christos char *op2,
369 1.1 christos char *comm1,
370 1.1 christos char *comm2,
371 1.1 christos unsigned short extension_word,
372 1.1 christos int *cycles)
373 1.1 christos {
374 1.1 christos int regs = 0, regd = 0;
375 1.1 christos int ad = 0, as = 0;
376 1.1 christos int cmd_len = 2;
377 1.1 christos int dst = 0;
378 1.1 christos int fmt;
379 1.1 christos int extended_dst = extension_word & 0xf;
380 1.1 christos int extended_src = (extension_word >> 7) & 0xf;
381 1.1 christos
382 1.1 christos regd = insn & 0x0f;
383 1.1 christos regs = (insn & 0x0f00) >> 8;
384 1.1 christos as = (insn & 0x0030) >> 4;
385 1.1 christos ad = (insn & 0x0080) >> 7;
386 1.1 christos
387 1.1 christos if (opcode->fmt < 0)
388 1.1 christos fmt = (- opcode->fmt) - 1;
389 1.1 christos else
390 1.1 christos fmt = opcode->fmt;
391 1.1 christos
392 1.1 christos if (fmt == 0)
393 1.1 christos {
394 1.1 christos /* Special case: rla and rlc are the only 2 emulated instructions that
395 1.1 christos fall into two operand instructions. */
396 1.1 christos /* With dst, there are only:
397 1.1 christos Rm Register,
398 1.1 christos x(Rm) Indexed,
399 1.1 christos 0xXXXX Relative,
400 1.1 christos &0xXXXX Absolute
401 1.1 christos emulated_ins dst
402 1.1 christos basic_ins dst, dst. */
403 1.1 christos
404 1.1 christos if (regd != regs || as != ad)
405 1.1 christos return 0; /* May be 'data' section. */
406 1.1 christos
407 1.1 christos if (ad == 0)
408 1.1 christos {
409 1.1 christos /* Register mode. */
410 1.1 christos if (regd == 3)
411 1.1 christos {
412 1.1 christos strcpy (comm1, _("Illegal as emulation instr"));
413 1.1 christos return -1;
414 1.1 christos }
415 1.1 christos
416 1.1 christos sprintf (op1, "r%d", regd);
417 1.1 christos *cycles = 1;
418 1.1 christos }
419 1.1 christos else /* ad == 1 */
420 1.1 christos {
421 1.1 christos if (regd == 0)
422 1.1 christos {
423 1.1 christos /* PC relative, Symbolic. */
424 1.1 christos dst = msp430dis_opcode (addr + 2, info);
425 1.1 christos cmd_len += 4;
426 1.1 christos *cycles = 6;
427 1.1 christos sprintf (op1, "0x%04x", PS (dst));
428 1.1 christos sprintf (comm1, "PC rel. 0x%04x",
429 1.1 christos PS ((short) addr + 2 + dst));
430 1.1 christos if (extended_dst)
431 1.1 christos {
432 1.1 christos dst |= extended_dst << 16;
433 1.1 christos if (dst & 0x80000)
434 1.1 christos dst |= -1 << 20;
435 1.1 christos sprintf (op1, "0x%05x", dst & 0xfffff);
436 1.1 christos sprintf (comm1, "PC rel. 0x%05lx",
437 1.1 christos (long)((addr + 2 + dst) & 0xfffff));
438 1.1 christos }
439 1.1 christos }
440 1.1 christos else if (regd == 2)
441 1.1 christos {
442 1.1 christos /* Absolute. */
443 1.1 christos dst = msp430dis_opcode (addr + 2, info);
444 1.1 christos /* If the 'src' field is not the same as the dst
445 1.1 christos then this is not an rla instruction. */
446 1.1 christos if (dst != msp430dis_opcode (addr + 4, info))
447 1.1 christos return 0;
448 1.1 christos cmd_len += 4;
449 1.1 christos *cycles = 6;
450 1.1 christos sprintf (op1, "&0x%04x", PS (dst));
451 1.1 christos if (extended_dst)
452 1.1 christos {
453 1.1 christos dst |= extended_dst << 16;
454 1.1 christos sprintf (op1, "&0x%05x", dst & 0xfffff);
455 1.1 christos }
456 1.1 christos }
457 1.1 christos else
458 1.1 christos {
459 1.1 christos /* Indexed. */
460 1.1 christos dst = msp430dis_opcode (addr + 2, info);
461 1.1 christos if (extended_dst)
462 1.1 christos {
463 1.1 christos dst |= extended_dst << 16;
464 1.1 christos if (dst & 0x80000)
465 1.1 christos dst |= -1 << 20;
466 1.1 christos }
467 1.1 christos else if (dst & 0x8000)
468 1.1 christos dst |= -1 << 16;
469 1.1 christos cmd_len += 4;
470 1.1 christos *cycles = 6;
471 1.1 christos sprintf (op1, "%d(r%d)", dst, regd);
472 1.1 christos if (dst > 9 || dst < -9)
473 1.1 christos sprintf (comm1, "#0x%05x", dst);
474 1.1 christos }
475 1.1 christos }
476 1.1 christos
477 1.1 christos *op2 = 0;
478 1.1 christos *comm2 = 0;
479 1.1 christos
480 1.1 christos return cmd_len;
481 1.1 christos }
482 1.1 christos
483 1.1 christos /* Two operands exactly. */
484 1.1 christos if (ad == 0 && regd == 3)
485 1.1 christos {
486 1.1 christos /* R2/R3 are illegal as dest: may be data section. */
487 1.1 christos strcpy (comm1, _("Illegal as 2-op instr"));
488 1.1 christos return -1;
489 1.1 christos }
490 1.1 christos
491 1.1 christos /* Source. */
492 1.1 christos if (as == 0)
493 1.1 christos {
494 1.1 christos *cycles = 1;
495 1.1 christos if (regs == 3)
496 1.1 christos {
497 1.1 christos /* Constants. */
498 1.1 christos sprintf (op1, "#0");
499 1.1 christos sprintf (comm1, "r3 As==00");
500 1.1 christos }
501 1.1 christos else
502 1.1 christos {
503 1.1 christos /* Register. */
504 1.1 christos sprintf (op1, "r%d", regs);
505 1.1 christos }
506 1.1 christos }
507 1.1 christos else if (as == 2)
508 1.1 christos {
509 1.1 christos * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
510 1.1 christos }
511 1.1 christos else if (as == 3)
512 1.1 christos {
513 1.1 christos if (regs == 0)
514 1.1 christos {
515 1.1 christos *cycles = 3;
516 1.1 christos /* Absolute. @pc+. */
517 1.1 christos dst = msp430dis_opcode (addr + 2, info);
518 1.1 christos cmd_len += 2;
519 1.1 christos sprintf (op1, "#%d", dst);
520 1.1 christos if (dst > 9 || dst < 0)
521 1.1 christos sprintf (comm1, "#0x%04x", PS (dst));
522 1.1 christos if (extended_src)
523 1.1 christos {
524 1.1 christos dst |= extended_src << 16;
525 1.1 christos if (dst & 0x80000)
526 1.1 christos dst |= -1 << 20;
527 1.1 christos sprintf (op1, "#%d", dst);
528 1.1 christos if (dst > 9 || dst < 0)
529 1.1 christos sprintf (comm1, "0x%05x", dst & 0xfffff);
530 1.1 christos }
531 1.1 christos }
532 1.1 christos else
533 1.1 christos * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
534 1.1 christos }
535 1.1 christos else if (as == 1)
536 1.1 christos {
537 1.1 christos if (regs == 0)
538 1.1 christos {
539 1.1 christos *cycles = 4;
540 1.1 christos /* PC relative. */
541 1.1 christos dst = msp430dis_opcode (addr + 2, info);
542 1.1 christos cmd_len += 2;
543 1.1 christos sprintf (op1, "0x%04x", PS (dst));
544 1.1 christos sprintf (comm1, "PC rel. 0x%04x",
545 1.1 christos PS ((short) addr + 2 + dst));
546 1.1 christos if (extended_src)
547 1.1 christos {
548 1.1 christos dst |= extended_src << 16;
549 1.1 christos if (dst & 0x80000)
550 1.1 christos dst |= -1 << 20;
551 1.1 christos sprintf (op1, "0x%05x", dst & 0xfffff);
552 1.1 christos sprintf (comm1, "PC rel. 0x%05lx",
553 1.1 christos (long) ((addr + 2 + dst) & 0xfffff));
554 1.1 christos }
555 1.1 christos }
556 1.1 christos else if (regs == 2)
557 1.1 christos {
558 1.1 christos *cycles = 2;
559 1.1 christos /* Absolute. */
560 1.1 christos dst = msp430dis_opcode (addr + 2, info);
561 1.1 christos cmd_len += 2;
562 1.1 christos sprintf (op1, "&0x%04x", PS (dst));
563 1.1 christos sprintf (comm1, "0x%04x", PS (dst));
564 1.1 christos if (extended_src)
565 1.1 christos {
566 1.1 christos dst |= extended_src << 16;
567 1.1 christos sprintf (op1, "&0x%05x", dst & 0xfffff);
568 1.1 christos * comm1 = 0;
569 1.1 christos }
570 1.1 christos }
571 1.1 christos else if (regs == 3)
572 1.1 christos {
573 1.1 christos *cycles = 1;
574 1.1 christos sprintf (op1, "#1");
575 1.1 christos sprintf (comm1, "r3 As==01");
576 1.1 christos }
577 1.1 christos else
578 1.1 christos {
579 1.1 christos *cycles = 3;
580 1.1 christos /* Indexed. */
581 1.1 christos dst = msp430dis_opcode (addr + 2, info);
582 1.1 christos cmd_len += 2;
583 1.1 christos if (extended_src)
584 1.1 christos {
585 1.1 christos dst |= extended_src << 16;
586 1.1 christos if (dst & 0x80000)
587 1.1 christos dst |= -1 << 20;
588 1.1 christos }
589 1.1 christos else if (dst & 0x8000)
590 1.1 christos dst |= -1 << 16;
591 1.1 christos sprintf (op1, "%d(r%d)", dst, regs);
592 1.1 christos if (dst > 9 || dst < -9)
593 1.1 christos sprintf (comm1, "0x%05x", dst);
594 1.1 christos }
595 1.1 christos }
596 1.1 christos
597 1.1 christos /* Destination. Special care needed on addr + XXXX. */
598 1.1 christos
599 1.1 christos if (ad == 0)
600 1.1 christos {
601 1.1 christos /* Register. */
602 1.1 christos if (regd == 0)
603 1.1 christos {
604 1.1 christos *cycles += 1;
605 1.1 christos sprintf (op2, "r0");
606 1.1 christos }
607 1.1 christos else if (regd == 1)
608 1.1 christos sprintf (op2, "r1");
609 1.1 christos
610 1.1 christos else if (regd == 2)
611 1.1 christos sprintf (op2, "r2");
612 1.1 christos
613 1.1 christos else
614 1.1 christos sprintf (op2, "r%d", regd);
615 1.1 christos }
616 1.1 christos else /* ad == 1. */
617 1.1 christos {
618 1.1 christos * cycles += 3;
619 1.1 christos
620 1.1 christos if (regd == 0)
621 1.1 christos {
622 1.1 christos /* PC relative. */
623 1.1 christos *cycles += 1;
624 1.1 christos dst = msp430dis_opcode (addr + cmd_len, info);
625 1.1 christos sprintf (op2, "0x%04x", PS (dst));
626 1.1 christos sprintf (comm2, "PC rel. 0x%04x",
627 1.1 christos PS ((short) addr + cmd_len + dst));
628 1.1 christos if (extended_dst)
629 1.1 christos {
630 1.1 christos dst |= extended_dst << 16;
631 1.1 christos if (dst & 0x80000)
632 1.1 christos dst |= -1 << 20;
633 1.1 christos sprintf (op2, "0x%05x", dst & 0xfffff);
634 1.1 christos sprintf (comm2, "PC rel. 0x%05lx",
635 1.1 christos (long)((addr + cmd_len + dst) & 0xfffff));
636 1.1 christos }
637 1.1 christos cmd_len += 2;
638 1.1 christos }
639 1.1 christos else if (regd == 2)
640 1.1 christos {
641 1.1 christos /* Absolute. */
642 1.1 christos dst = msp430dis_opcode (addr + cmd_len, info);
643 1.1 christos cmd_len += 2;
644 1.1 christos sprintf (op2, "&0x%04x", PS (dst));
645 1.1 christos if (extended_dst)
646 1.1 christos {
647 1.1 christos dst |= extended_dst << 16;
648 1.1 christos sprintf (op2, "&0x%05x", dst & 0xfffff);
649 1.1 christos }
650 1.1 christos }
651 1.1 christos else
652 1.1 christos {
653 1.1 christos dst = msp430dis_opcode (addr + cmd_len, info);
654 1.1 christos cmd_len += 2;
655 1.1 christos if (dst & 0x8000)
656 1.1 christos dst |= -1 << 16;
657 1.1 christos if (dst > 9 || dst < 0)
658 1.1 christos sprintf (comm2, "0x%04x", PS (dst));
659 1.1 christos if (extended_dst)
660 1.1 christos {
661 1.1 christos dst |= extended_dst << 16;
662 1.1 christos if (dst & 0x80000)
663 1.1 christos dst |= -1 << 20;
664 1.1 christos if (dst > 9 || dst < 0)
665 1.1 christos sprintf (comm2, "0x%05x", dst & 0xfffff);
666 1.1 christos }
667 1.1 christos sprintf (op2, "%d(r%d)", dst, regd);
668 1.1 christos }
669 1.1 christos }
670 1.1 christos
671 1.1 christos return cmd_len;
672 1.1 christos }
673 1.1 christos
674 1.1 christos static int
675 1.1 christos msp430_branchinstr (disassemble_info *info,
676 1.1 christos struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED,
677 1.1 christos bfd_vma addr ATTRIBUTE_UNUSED,
678 1.1 christos unsigned short insn,
679 1.1 christos char *op1,
680 1.1 christos char *comm1,
681 1.1 christos int *cycles)
682 1.1 christos {
683 1.1 christos int regs = 0, regd = 0;
684 1.1 christos int as = 0;
685 1.1 christos int cmd_len = 2;
686 1.1 christos short dst = 0;
687 1.1 christos
688 1.1 christos regd = insn & 0x0f;
689 1.1 christos regs = (insn & 0x0f00) >> 8;
690 1.1 christos as = (insn & 0x0030) >> 4;
691 1.1 christos
692 1.1 christos if (regd != 0) /* Destination register is not a PC. */
693 1.1 christos return 0;
694 1.1 christos
695 1.1 christos /* dst is a source register. */
696 1.1 christos if (as == 0)
697 1.1 christos {
698 1.1 christos /* Constants. */
699 1.1 christos if (regs == 3)
700 1.1 christos {
701 1.1 christos *cycles = 1;
702 1.1 christos sprintf (op1, "#0");
703 1.1 christos sprintf (comm1, "r3 As==00");
704 1.1 christos }
705 1.1 christos else
706 1.1 christos {
707 1.1 christos /* Register. */
708 1.1 christos *cycles = 1;
709 1.1 christos sprintf (op1, "r%d", regs);
710 1.1 christos }
711 1.1 christos }
712 1.1 christos else if (as == 2)
713 1.1 christos {
714 1.1 christos * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
715 1.1 christos }
716 1.1 christos else if (as == 3)
717 1.1 christos {
718 1.1 christos if (regs == 0)
719 1.1 christos {
720 1.1 christos /* Absolute. @pc+ */
721 1.1 christos *cycles = 3;
722 1.1 christos dst = msp430dis_opcode (addr + 2, info);
723 1.1 christos cmd_len += 2;
724 1.1 christos sprintf (op1, "#0x%04x", PS (dst));
725 1.1 christos }
726 1.1 christos else
727 1.1 christos * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
728 1.1 christos }
729 1.1 christos else if (as == 1)
730 1.1 christos {
731 1.1 christos * cycles = 3;
732 1.1 christos
733 1.1 christos if (regs == 0)
734 1.1 christos {
735 1.1 christos /* PC relative. */
736 1.1 christos dst = msp430dis_opcode (addr + 2, info);
737 1.1 christos cmd_len += 2;
738 1.1 christos (*cycles)++;
739 1.1 christos sprintf (op1, "0x%04x", PS (dst));
740 1.1 christos sprintf (comm1, "PC rel. 0x%04x",
741 1.1 christos PS ((short) addr + 2 + dst));
742 1.1 christos }
743 1.1 christos else if (regs == 2)
744 1.1 christos {
745 1.1 christos /* Absolute. */
746 1.1 christos dst = msp430dis_opcode (addr + 2, info);
747 1.1 christos cmd_len += 2;
748 1.1 christos sprintf (op1, "&0x%04x", PS (dst));
749 1.1 christos }
750 1.1 christos else if (regs == 3)
751 1.1 christos {
752 1.1 christos (*cycles)--;
753 1.1 christos sprintf (op1, "#1");
754 1.1 christos sprintf (comm1, "r3 As==01");
755 1.1 christos }
756 1.1 christos else
757 1.1 christos {
758 1.1 christos /* Indexed. */
759 1.1 christos dst = msp430dis_opcode (addr + 2, info);
760 1.1 christos cmd_len += 2;
761 1.1 christos if (dst & 0x8000)
762 1.1 christos dst |= -1 << 16;
763 1.1 christos sprintf (op1, "%d(r%d)", dst, regs);
764 1.1 christos }
765 1.1 christos }
766 1.1 christos
767 1.1 christos return cmd_len;
768 1.1 christos }
769 1.1 christos
770 1.1 christos static int
771 1.1 christos msp430x_calla_instr (disassemble_info * info,
772 1.1 christos bfd_vma addr,
773 1.1 christos unsigned short insn,
774 1.1 christos char * op1,
775 1.1 christos char * comm1,
776 1.1 christos int * cycles)
777 1.1 christos {
778 1.1 christos unsigned int ureg = insn & 0xf;
779 1.1 christos int reg = insn & 0xf;
780 1.1 christos int am = (insn & 0xf0) >> 4;
781 1.1 christos int cmd_len = 2;
782 1.1 christos unsigned short udst = 0;
783 1.1 christos short dst = 0;
784 1.1 christos
785 1.1 christos switch (am)
786 1.1 christos {
787 1.1 christos case 4: /* CALLA Rdst */
788 1.1 christos *cycles = 1;
789 1.1 christos sprintf (op1, "r%d", reg);
790 1.1 christos break;
791 1.1 christos
792 1.1 christos case 5: /* CALLA x(Rdst) */
793 1.1 christos *cycles = 3;
794 1.1 christos dst = msp430dis_opcode (addr + 2, info);
795 1.1 christos cmd_len += 2;
796 1.1 christos sprintf (op1, "%d(r%d)", dst, reg);
797 1.1 christos if (reg == 0)
798 1.1 christos sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst));
799 1.1 christos else
800 1.1 christos sprintf (comm1, "0x%05x", dst);
801 1.1 christos break;
802 1.1 christos
803 1.1 christos case 6: /* CALLA @Rdst */
804 1.1 christos *cycles = 2;
805 1.1 christos sprintf (op1, "@r%d", reg);
806 1.1 christos break;
807 1.1 christos
808 1.1 christos case 7: /* CALLA @Rdst+ */
809 1.1 christos *cycles = 2;
810 1.1 christos sprintf (op1, "@r%d+", reg);
811 1.1 christos break;
812 1.1 christos
813 1.1 christos case 8: /* CALLA &abs20 */
814 1.1 christos udst = msp430dis_opcode (addr + 2, info);
815 1.1 christos cmd_len += 2;
816 1.1 christos *cycles = 4;
817 1.1 christos sprintf (op1, "&%d", (ureg << 16) + udst);
818 1.1 christos sprintf (comm1, "0x%05x", (ureg << 16) + udst);
819 1.1 christos break;
820 1.1 christos
821 1.1 christos case 9: /* CALLA pcrel-sym */
822 1.1 christos dst = msp430dis_opcode (addr + 2, info);
823 1.1 christos cmd_len += 2;
824 1.1 christos *cycles = 4;
825 1.1 christos sprintf (op1, "%d(PC)", (reg << 16) + dst);
826 1.1 christos sprintf (comm1, "PC rel. 0x%05lx",
827 1.1 christos (long) (addr + 2 + dst + (reg << 16)));
828 1.1 christos break;
829 1.1 christos
830 1.1 christos case 11: /* CALLA #imm20 */
831 1.1 christos udst = msp430dis_opcode (addr + 2, info);
832 1.1 christos cmd_len += 2;
833 1.1 christos *cycles = 4;
834 1.1 christos sprintf (op1, "#%d", (ureg << 16) + udst);
835 1.1 christos sprintf (comm1, "0x%05x", (ureg << 16) + udst);
836 1.1 christos break;
837 1.1 christos
838 1.1 christos default:
839 1.1 christos strcpy (comm1, _("unrecognised CALLA addressing mode"));
840 1.1 christos return -1;
841 1.1 christos }
842 1.1 christos
843 1.1 christos return cmd_len;
844 1.1 christos }
845 1.1 christos
846 1.1 christos int
847 1.1 christos print_insn_msp430 (bfd_vma addr, disassemble_info *info)
848 1.1 christos {
849 1.1 christos void *stream = info->stream;
850 1.1 christos fprintf_ftype prin = info->fprintf_func;
851 1.1 christos struct msp430_opcode_s *opcode;
852 1.1 christos char op1[32], op2[32], comm1[64], comm2[64];
853 1.1 christos int cmd_len = 0;
854 1.1 christos unsigned short insn;
855 1.1 christos int cycles = 0;
856 1.1 christos char *bc = "";
857 1.1 christos unsigned short extension_word = 0;
858 1.1 christos
859 1.1 christos insn = msp430dis_opcode (addr, info);
860 1.1 christos if (insn == (unsigned short) -1)
861 1.1 christos {
862 1.1 christos prin (stream, ".word 0xffff; ????");
863 1.1 christos return 2;
864 1.1 christos }
865 1.1 christos
866 1.1 christos if (((int) addr & 0xffff) > 0xffdf)
867 1.1 christos {
868 1.1 christos (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
869 1.1 christos return 2;
870 1.1 christos }
871 1.1 christos
872 1.1 christos *comm1 = 0;
873 1.1 christos *comm2 = 0;
874 1.1 christos
875 1.1 christos /* Check for an extension word. */
876 1.1 christos if ((insn & 0xf800) == 0x1800)
877 1.1 christos {
878 1.1 christos extension_word = insn;
879 1.1 christos addr += 2;
880 1.1 christos insn = msp430dis_opcode (addr, info);
881 1.1 christos if (insn == (unsigned short) -1)
882 1.1 christos {
883 1.1 christos prin (stream, ".word 0x%04x, 0xffff; ????",
884 1.1 christos extension_word);
885 1.1 christos return 4;
886 1.1 christos }
887 1.1 christos }
888 1.1 christos
889 1.1 christos for (opcode = msp430_opcodes; opcode->name; opcode++)
890 1.1 christos {
891 1.1 christos if ((insn & opcode->bin_mask) == opcode->bin_opcode
892 1.1 christos && opcode->bin_opcode != 0x9300)
893 1.1 christos {
894 1.1 christos *op1 = 0;
895 1.1 christos *op2 = 0;
896 1.1 christos *comm1 = 0;
897 1.1 christos *comm2 = 0;
898 1.1 christos
899 1.1 christos /* r0 as destination. Ad should be zero. */
900 1.1 christos if (opcode->insn_opnumb == 3
901 1.1 christos && (insn & 0x000f) == 0
902 1.1 christos && (insn & 0x0080) == 0)
903 1.1 christos {
904 1.1 christos cmd_len +=
905 1.1 christos msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
906 1.1 christos &cycles);
907 1.1 christos if (cmd_len)
908 1.1 christos break;
909 1.1 christos }
910 1.1 christos
911 1.1 christos switch (opcode->insn_opnumb)
912 1.1 christos {
913 1.1 christos int n;
914 1.1 christos int reg;
915 1.1 christos
916 1.1 christos case 4:
917 1.1 christos cmd_len += msp430x_calla_instr (info, addr, insn,
918 1.1 christos op1, comm1, & cycles);
919 1.1 christos break;
920 1.1 christos
921 1.1 christos case 5: /* PUSHM/POPM */
922 1.1 christos n = (insn & 0xf0) >> 4;
923 1.1 christos reg = (insn & 0xf);
924 1.1 christos
925 1.1 christos sprintf (op1, "#%d", n + 1);
926 1.1 christos if (opcode->bin_opcode == 0x1400)
927 1.1 christos /* PUSHM */
928 1.1 christos sprintf (op2, "r%d", reg);
929 1.1 christos else
930 1.1 christos /* POPM */
931 1.1 christos sprintf (op2, "r%d", reg + n);
932 1.1 christos if (insn & 0x100)
933 1.1 christos sprintf (comm1, "16-bit words");
934 1.1 christos else
935 1.1 christos {
936 1.1 christos sprintf (comm1, "20-bit words");
937 1.1 christos bc =".a";
938 1.1 christos }
939 1.1 christos
940 1.1 christos cycles = 2; /*FIXME*/
941 1.1 christos cmd_len = 2;
942 1.1 christos break;
943 1.1 christos
944 1.1 christos case 6: /* RRAM, RRCM, RRUM, RLAM. */
945 1.1 christos n = ((insn >> 10) & 0x3) + 1;
946 1.1 christos reg = (insn & 0xf);
947 1.1 christos if ((insn & 0x10) == 0)
948 1.1 christos bc =".a";
949 1.1 christos sprintf (op1, "#%d", n);
950 1.1 christos sprintf (op2, "r%d", reg);
951 1.1 christos cycles = 2; /*FIXME*/
952 1.1 christos cmd_len = 2;
953 1.1 christos break;
954 1.1 christos
955 1.1 christos case 8: /* ADDA, CMPA, SUBA. */
956 1.1 christos reg = (insn & 0xf);
957 1.1 christos n = (insn >> 8) & 0xf;
958 1.1 christos if (insn & 0x40)
959 1.1 christos {
960 1.1 christos sprintf (op1, "r%d", n);
961 1.1 christos cmd_len = 2;
962 1.1 christos }
963 1.1 christos else
964 1.1 christos {
965 1.1 christos n <<= 16;
966 1.1 christos n |= msp430dis_opcode (addr + 2, info);
967 1.1 christos sprintf (op1, "#%d", n);
968 1.1 christos if (n > 9 || n < 0)
969 1.1 christos sprintf (comm1, "0x%05x", n);
970 1.1 christos cmd_len = 4;
971 1.1 christos }
972 1.1 christos sprintf (op2, "r%d", reg);
973 1.1 christos cycles = 2; /*FIXME*/
974 1.1 christos break;
975 1.1 christos
976 1.1 christos case 9: /* MOVA */
977 1.1 christos reg = (insn & 0xf);
978 1.1 christos n = (insn >> 8) & 0xf;
979 1.1 christos switch ((insn >> 4) & 0xf)
980 1.1 christos {
981 1.1 christos case 0: /* MOVA @Rsrc, Rdst */
982 1.1 christos cmd_len = 2;
983 1.1 christos sprintf (op1, "@r%d", n);
984 1.1 christos if (strcmp (opcode->name, "bra") != 0)
985 1.1 christos sprintf (op2, "r%d", reg);
986 1.1 christos break;
987 1.1 christos
988 1.1 christos case 1: /* MOVA @Rsrc+, Rdst */
989 1.1 christos cmd_len = 2;
990 1.1 christos if (strcmp (opcode->name, "reta") != 0)
991 1.1 christos {
992 1.1 christos sprintf (op1, "@r%d+", n);
993 1.1 christos if (strcmp (opcode->name, "bra") != 0)
994 1.1 christos sprintf (op2, "r%d", reg);
995 1.1 christos }
996 1.1 christos break;
997 1.1 christos
998 1.1 christos case 2: /* MOVA &abs20, Rdst */
999 1.1 christos cmd_len = 4;
1000 1.1 christos n <<= 16;
1001 1.1 christos n |= msp430dis_opcode (addr + 2, info);
1002 1.1 christos sprintf (op1, "&%d", n);
1003 1.1 christos if (n > 9 || n < 0)
1004 1.1 christos sprintf (comm1, "0x%05x", n);
1005 1.1 christos if (strcmp (opcode->name, "bra") != 0)
1006 1.1 christos sprintf (op2, "r%d", reg);
1007 1.1 christos break;
1008 1.1 christos
1009 1.1 christos case 3: /* MOVA x(Rsrc), Rdst */
1010 1.1 christos cmd_len = 4;
1011 1.1 christos if (strcmp (opcode->name, "bra") != 0)
1012 1.1 christos sprintf (op2, "r%d", reg);
1013 1.1 christos reg = n;
1014 1.1 christos n = msp430dis_opcode (addr + 2, info);
1015 1.1 christos if (n & 0x8000)
1016 1.1 christos n |= -1 << 16;
1017 1.1 christos sprintf (op1, "%d(r%d)", n, reg);
1018 1.1 christos if (n > 9 || n < 0)
1019 1.1 christos {
1020 1.1 christos if (reg == 0)
1021 1.1 christos sprintf (comm1, "PC rel. 0x%05lx",
1022 1.1 christos (long) (addr + 2 + n));
1023 1.1 christos else
1024 1.1 christos sprintf (comm1, "0x%05x", n);
1025 1.1 christos }
1026 1.1 christos break;
1027 1.1 christos
1028 1.1 christos case 6: /* MOVA Rsrc, &abs20 */
1029 1.1 christos cmd_len = 4;
1030 1.1 christos reg <<= 16;
1031 1.1 christos reg |= msp430dis_opcode (addr + 2, info);
1032 1.1 christos sprintf (op1, "r%d", n);
1033 1.1 christos sprintf (op2, "&%d", reg);
1034 1.1 christos if (reg > 9 || reg < 0)
1035 1.1 christos sprintf (comm2, "0x%05x", reg);
1036 1.1 christos break;
1037 1.1 christos
1038 1.1 christos case 7: /* MOVA Rsrc, x(Rdst) */
1039 1.1 christos cmd_len = 4;
1040 1.1 christos sprintf (op1, "r%d", n);
1041 1.1 christos n = msp430dis_opcode (addr + 2, info);
1042 1.1 christos if (n & 0x8000)
1043 1.1 christos n |= -1 << 16;
1044 1.1 christos sprintf (op2, "%d(r%d)", n, reg);
1045 1.1 christos if (n > 9 || n < 0)
1046 1.1 christos {
1047 1.1 christos if (reg == 0)
1048 1.1 christos sprintf (comm2, "PC rel. 0x%05lx",
1049 1.1 christos (long) (addr + 2 + n));
1050 1.1 christos else
1051 1.1 christos sprintf (comm2, "0x%05x", n);
1052 1.1 christos }
1053 1.1 christos break;
1054 1.1 christos
1055 1.1 christos case 8: /* MOVA #imm20, Rdst */
1056 1.1 christos cmd_len = 4;
1057 1.1 christos n <<= 16;
1058 1.1 christos n |= msp430dis_opcode (addr + 2, info);
1059 1.1 christos if (n & 0x80000)
1060 1.1 christos n |= -1 << 20;
1061 1.1 christos sprintf (op1, "#%d", n);
1062 1.1 christos if (n > 9 || n < 0)
1063 1.1 christos sprintf (comm1, "0x%05x", n);
1064 1.1 christos if (strcmp (opcode->name, "bra") != 0)
1065 1.1 christos sprintf (op2, "r%d", reg);
1066 1.1 christos break;
1067 1.1 christos
1068 1.1 christos case 12: /* MOVA Rsrc, Rdst */
1069 1.1 christos cmd_len = 2;
1070 1.1 christos sprintf (op1, "r%d", n);
1071 1.1 christos if (strcmp (opcode->name, "bra") != 0)
1072 1.1 christos sprintf (op2, "r%d", reg);
1073 1.1 christos break;
1074 1.1 christos
1075 1.1 christos default:
1076 1.1 christos break;
1077 1.1 christos }
1078 1.1 christos cycles = 2; /* FIXME */
1079 1.1 christos break;
1080 1.1 christos }
1081 1.1 christos
1082 1.1 christos if (cmd_len)
1083 1.1 christos break;
1084 1.1 christos
1085 1.1 christos switch (opcode->insn_opnumb)
1086 1.1 christos {
1087 1.1 christos case 0:
1088 1.1 christos cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
1089 1.1 christos break;
1090 1.1 christos case 2:
1091 1.1 christos cmd_len +=
1092 1.1 christos msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
1093 1.1 christos comm1, comm2,
1094 1.1 christos extension_word,
1095 1.1 christos &cycles);
1096 1.1 christos if (insn & BYTE_OPERATION)
1097 1.1 christos {
1098 1.1 christos if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1099 1.1 christos bc = ".a";
1100 1.1 christos else
1101 1.1 christos bc = ".b";
1102 1.1 christos }
1103 1.1 christos else if (extension_word)
1104 1.1 christos {
1105 1.1 christos if (extension_word & (1 << 6))
1106 1.1 christos bc = ".w";
1107 1.1 christos else
1108 1.1 christos {
1109 1.1 christos bc = ".?";
1110 1.1 christos sprintf (comm2, _("Reserved use of A/L and B/W bits detected"));
1111 1.1 christos }
1112 1.1 christos }
1113 1.1 christos
1114 1.1 christos break;
1115 1.1 christos case 1:
1116 1.1 christos cmd_len +=
1117 1.1 christos msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
1118 1.1 christos extension_word,
1119 1.1 christos &cycles);
1120 1.1 christos if (extension_word
1121 1.1 christos && (strcmp (opcode->name, "swpb") == 0
1122 1.1 christos || strcmp (opcode->name, "sxt") == 0))
1123 1.1 christos {
1124 1.1 christos if (insn & BYTE_OPERATION)
1125 1.1 christos {
1126 1.1 christos bc = ".?";
1127 1.1 christos sprintf (comm2, _("Reserved use of A/L and B/W bits detected"));
1128 1.1 christos }
1129 1.1 christos else if (extension_word & BYTE_OPERATION)
1130 1.1 christos bc = ".w";
1131 1.1 christos else
1132 1.1 christos bc = ".a";
1133 1.1 christos }
1134 1.1 christos else if (insn & BYTE_OPERATION && opcode->fmt != 3)
1135 1.1 christos {
1136 1.1 christos if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
1137 1.1 christos bc = ".a";
1138 1.1 christos else
1139 1.1 christos bc = ".b";
1140 1.1 christos }
1141 1.1 christos else if (extension_word)
1142 1.1 christos {
1143 1.1 christos if (extension_word & (1 << 6))
1144 1.1 christos bc = ".w";
1145 1.1 christos else
1146 1.1 christos {
1147 1.1 christos bc = ".?";
1148 1.1 christos sprintf (comm2, _("Reserved use of A/L and B/W bits detected"));
1149 1.1 christos }
1150 1.1 christos }
1151 1.1 christos break;
1152 1.1 christos default:
1153 1.1 christos break;
1154 1.1 christos }
1155 1.1 christos }
1156 1.1 christos
1157 1.1 christos if (cmd_len)
1158 1.1 christos break;
1159 1.1 christos }
1160 1.1 christos
1161 1.1 christos if (cmd_len < 1)
1162 1.1 christos {
1163 1.1 christos /* Unknown opcode, or invalid combination of operands. */
1164 1.1 christos if (extension_word)
1165 1.1 christos {
1166 1.1 christos prin (stream, ".word 0x%04x, 0x%04x; ????", extension_word, PS (insn));
1167 1.1 christos if (*comm1)
1168 1.1 christos prin (stream, "\t %s", comm1);
1169 1.1 christos return 4;
1170 1.1 christos }
1171 1.1 christos (*prin) (stream, ".word 0x%04x; ????", PS (insn));
1172 1.1 christos return 2;
1173 1.1 christos }
1174 1.1 christos
1175 1.1 christos /* Display the repeat count (if set) for extended register mode. */
1176 1.1 christos if (cmd_len == 2 && ((extension_word & 0xf) != 0))
1177 1.1 christos {
1178 1.1 christos if (extension_word & (1 << 7))
1179 1.1 christos prin (stream, "rpt r%d { ", extension_word & 0xf);
1180 1.1 christos else
1181 1.1 christos prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1);
1182 1.1 christos }
1183 1.1 christos
1184 1.1 christos if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x')
1185 1.1 christos (*prin) (stream, "%sx%s", opcode->name, bc);
1186 1.1 christos else
1187 1.1 christos (*prin) (stream, "%s%s", opcode->name, bc);
1188 1.1 christos
1189 1.1 christos if (*op1)
1190 1.1 christos (*prin) (stream, "\t%s", op1);
1191 1.1 christos if (*op2)
1192 1.1 christos (*prin) (stream, ",");
1193 1.1 christos
1194 1.1 christos if (strlen (op1) < 7)
1195 1.1 christos (*prin) (stream, "\t");
1196 1.1 christos if (!strlen (op1))
1197 1.1 christos (*prin) (stream, "\t");
1198 1.1 christos
1199 1.1 christos if (*op2)
1200 1.1 christos (*prin) (stream, "%s", op2);
1201 1.1 christos if (strlen (op2) < 8)
1202 1.1 christos (*prin) (stream, "\t");
1203 1.1 christos
1204 1.1 christos if (*comm1 || *comm2)
1205 1.1 christos (*prin) (stream, ";");
1206 1.1 christos else if (cycles)
1207 1.1 christos {
1208 1.1 christos if (*op2)
1209 1.1 christos (*prin) (stream, ";");
1210 1.1 christos else
1211 1.1 christos {
1212 1.1 christos if (strlen (op1) < 7)
1213 1.1 christos (*prin) (stream, ";");
1214 1.1 christos else
1215 1.1 christos (*prin) (stream, "\t;");
1216 1.1 christos }
1217 1.1 christos }
1218 1.1 christos if (*comm1)
1219 1.1 christos (*prin) (stream, "%s", comm1);
1220 1.1 christos if (*comm1 && *comm2)
1221 1.1 christos (*prin) (stream, ",");
1222 1.1 christos if (*comm2)
1223 1.1 christos (*prin) (stream, " %s", comm2);
1224 1.1 christos
1225 1.1 christos if (extension_word)
1226 1.1 christos cmd_len += 2;
1227 1.1 christos
1228 1.1 christos return cmd_len;
1229 1.1 christos }
1230