1 /* MSPDebug - debugging tool for the eZ430
2 * Copyright (C) 2009, 2010 Daniel Beer
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <ctype.h>
24
25 #include "dis.h"
26 #include "util.h"
27
28 #define ALL_ONES 0xfffff
29 #define EXTENSION_BIT 0x20000
30
31 /**********************************************************************/
32 /* Disassembler
33 */
34
add_index(address_t reg_base,address_t index,int is_20bit)35 static address_t add_index(address_t reg_base, address_t index,
36 int is_20bit)
37 {
38 return (reg_base + index) & (is_20bit ? 0xfffff : 0xffff);
39 }
40
decode_00xx(const uint8_t * code,address_t len,struct msp430_instruction * insn)41 static int decode_00xx(const uint8_t *code, address_t len,
42 struct msp430_instruction *insn)
43 {
44 uint16_t op = code[0] | (code[1] << 8);
45 int subtype = (op >> 4) & 0xf;
46 int have_arg = 0;
47 address_t arg = 0;
48
49 /* Parameters common to most cases */
50 insn->op = MSP430_OP_MOVA;
51 insn->itype = MSP430_ITYPE_DOUBLE;
52 insn->dsize = MSP430_DSIZE_AWORD;
53 insn->dst_mode = MSP430_AMODE_REGISTER;
54 insn->dst_reg = op & 0xf;
55 insn->src_mode = MSP430_AMODE_REGISTER;
56 insn->src_reg = (op >> 8) & 0xf;
57
58 if (len >= 4) {
59 have_arg = 1;
60 arg = code[2] | (code[3] << 8);
61 }
62
63 switch (subtype) {
64 case 0:
65 insn->src_mode = MSP430_AMODE_INDIRECT;
66 return 2;
67
68 case 1:
69 insn->src_mode = MSP430_AMODE_INDIRECT_INC;
70 return 2;
71
72 case 2:
73 if (!have_arg)
74 return -1;
75 insn->src_mode = MSP430_AMODE_ABSOLUTE;
76 insn->src_addr = ((op & 0xf00) << 8) | arg;
77 return 4;
78
79 case 3:
80 if (!have_arg)
81 return -1;
82 insn->src_mode = MSP430_AMODE_INDEXED;
83 insn->src_addr = arg;
84 return 4;
85
86 case 4:
87 case 5:
88 /* RxxM */
89 insn->itype = MSP430_ITYPE_DOUBLE;
90 insn->op = op & 0xf3e0;
91 insn->dst_mode = MSP430_AMODE_REGISTER;
92 insn->dst_reg = op & 0xf;
93 insn->src_mode = MSP430_AMODE_IMMEDIATE;
94 insn->src_addr = 1 + ((op >> 10) & 3);
95 insn->dsize = (op & 0x0010) ?
96 MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
97 return 2;
98
99 case 6:
100 if (!have_arg)
101 return -1;
102
103 insn->dst_mode = MSP430_AMODE_ABSOLUTE;
104 insn->dst_addr = ((op & 0xf) << 16) | arg;
105 return 4;
106
107 case 7:
108 if (!have_arg)
109 return -1;
110 insn->dst_mode = MSP430_AMODE_INDEXED;
111 insn->dst_addr = arg;
112 return 4;
113
114 case 8:
115 if (!have_arg)
116 return -1;
117 insn->src_mode = MSP430_AMODE_IMMEDIATE;
118 insn->src_addr = ((op & 0xf00) << 8) | arg;
119 return 4;
120
121 case 9:
122 if (!have_arg)
123 return -1;
124 insn->op = MSP430_OP_CMPA;
125 insn->src_mode = MSP430_AMODE_IMMEDIATE;
126 insn->src_addr = ((op & 0xf00) << 8) | arg;
127 return 4;
128
129 case 10:
130 if (!have_arg)
131 return -1;
132 insn->op = MSP430_OP_ADDA;
133 insn->src_mode = MSP430_AMODE_IMMEDIATE;
134 insn->src_addr = ((op & 0xf00) << 8) | arg;
135 return 4;
136
137 case 11:
138 if (!have_arg)
139 return -1;
140 insn->op = MSP430_OP_SUBA;
141 insn->src_mode = MSP430_AMODE_IMMEDIATE;
142 insn->src_addr = ((op & 0xf00) << 8) | arg;
143 return 4;
144
145 case 12:
146 return 2;
147
148 case 13:
149 insn->op = MSP430_OP_CMPA;
150 return 2;
151
152 case 14:
153 insn->op = MSP430_OP_ADDA;
154 return 2;
155
156 case 15:
157 insn->op = MSP430_OP_SUBA;
158 return 2;
159 }
160
161 return -1;
162 }
163
decode_13xx(const uint8_t * code,address_t len,struct msp430_instruction * insn)164 static int decode_13xx(const uint8_t *code, address_t len,
165 struct msp430_instruction *insn)
166 {
167 uint16_t op = code[0] | (code[1] << 8);
168 int subtype = (op >> 4) & 0xf;
169
170 insn->itype = MSP430_ITYPE_SINGLE;
171 insn->op = MSP430_OP_CALLA;
172
173 switch (subtype) {
174 case 0:
175 insn->itype = MSP430_ITYPE_NOARG;
176 insn->op = MSP430_OP_RETI;
177 return 2;
178
179 case 4:
180 insn->dst_mode = MSP430_AMODE_REGISTER;
181 insn->dst_reg = op & 0xf;
182 return 2;
183
184 case 5:
185 insn->dst_mode = MSP430_AMODE_INDEXED;
186 insn->dst_reg = op & 0xf;
187 break;
188
189 case 6:
190 insn->dst_mode = MSP430_AMODE_INDIRECT;
191 insn->dst_reg = op & 0xf;
192 return 2;
193
194 case 7:
195 insn->dst_mode = MSP430_AMODE_INDIRECT_INC;
196 insn->dst_reg = op & 0xf;
197 return 2;
198
199 case 8:
200 insn->dst_mode = MSP430_AMODE_ABSOLUTE;
201 insn->dst_addr = (address_t)(op & 0xf) << 16;
202 break;
203
204 case 9:
205 insn->dst_mode = MSP430_AMODE_SYMBOLIC;
206 insn->dst_addr = (address_t)(op & 0xf) << 16;
207 break;
208
209 case 11:
210 insn->dst_mode = MSP430_AMODE_IMMEDIATE;
211 insn->dst_addr = (address_t)(op & 0xf) << 16;
212 break;
213
214 default:
215 return -1;
216 }
217
218 if (len < 4)
219 return -1;
220
221 insn->dsize = MSP430_DSIZE_AWORD;
222 insn->dst_addr |= code[2];
223 insn->dst_addr |= code[3] << 8;
224
225 return 4;
226 }
227
decode_14xx(const uint8_t * code,struct msp430_instruction * insn)228 static int decode_14xx(const uint8_t *code,
229 struct msp430_instruction *insn)
230 {
231 uint16_t op = (code[1] << 8) | code[0];
232
233 /* PUSHM/POPM */
234 insn->itype = MSP430_ITYPE_DOUBLE;
235 insn->op = op & 0xfe00;
236 insn->dst_mode = MSP430_AMODE_REGISTER;
237 insn->dst_reg = op & 0xf;
238 insn->src_mode = MSP430_AMODE_IMMEDIATE;
239 insn->src_addr = 1 + ((op >> 4) & 0xf);
240 insn->dsize = (op & 0x0100) ?
241 MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD;
242
243 return 2;
244 }
245
246 /* Decode a single-operand instruction.
247 *
248 * Returns the number of bytes consumed in decoding, or -1 if the a
249 * valid single-operand instruction could not be found.
250 */
decode_single(const uint8_t * code,address_t offset,address_t size,struct msp430_instruction * insn)251 static int decode_single(const uint8_t *code, address_t offset,
252 address_t size, struct msp430_instruction *insn)
253 {
254 uint16_t op = (code[1] << 8) | code[0];
255 int need_arg = 0;
256
257 insn->itype = MSP430_ITYPE_SINGLE;
258 insn->op = op & 0xff80;
259 insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
260
261 insn->dst_mode = (op >> 4) & 0x3;
262 insn->dst_reg = op & 0xf;
263
264 switch (insn->dst_mode) {
265 case MSP430_AMODE_REGISTER: break;
266
267 case MSP430_AMODE_INDEXED:
268 need_arg = 1;
269 if (insn->dst_reg == MSP430_REG_PC) {
270 insn->dst_addr = offset + 4;
271 insn->dst_mode = MSP430_AMODE_SYMBOLIC;
272 } else if (insn->dst_reg == MSP430_REG_SR) {
273 insn->dst_mode = MSP430_AMODE_ABSOLUTE;
274 } else if (insn->dst_reg == MSP430_REG_R3) {
275 need_arg = 0; /* constant generator: #1 */
276 }
277 break;
278
279 case MSP430_AMODE_INDIRECT: break;
280
281 case MSP430_AMODE_INDIRECT_INC:
282 if (insn->dst_reg == MSP430_REG_PC) {
283 insn->dst_mode = MSP430_AMODE_IMMEDIATE;
284 need_arg = 1;
285 }
286 break;
287
288 default: break;
289 }
290
291 if (need_arg) {
292 if (size < 4)
293 return -1;
294
295 insn->dst_addr = add_index(insn->dst_addr,
296 (code[3] << 8) | code[2], 0);
297 return 4;
298 }
299
300 return 2;
301 }
302
303 /* Decode a double-operand instruction.
304 *
305 * Returns the number of bytes consumed or -1 if a valid instruction
306 * could not be found.
307 */
decode_double(const uint8_t * code,address_t offset,address_t size,struct msp430_instruction * insn,uint16_t ex_word)308 static int decode_double(const uint8_t *code, address_t offset,
309 address_t size, struct msp430_instruction *insn,
310 uint16_t ex_word)
311 {
312 uint16_t op = (code[1] << 8) | code[0];
313 int need_src = 0;
314 int need_dst = 0;
315 int ret = 2;
316
317 /* Decode and consume opcode */
318 insn->itype = MSP430_ITYPE_DOUBLE;
319 insn->op = op & 0xf000;
320 insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
321
322 insn->src_mode = (op >> 4) & 0x3;
323 insn->src_reg = (op >> 8) & 0xf;
324
325 insn->dst_mode = (op >> 7) & 0x1;
326 insn->dst_reg = op & 0xf;
327
328 offset += 2;
329 code += 2;
330 size -= 2;
331
332 /* Decode and consume source operand */
333 switch (insn->src_mode) {
334 case MSP430_AMODE_REGISTER: break;
335 case MSP430_AMODE_INDEXED:
336 need_src = 1;
337
338 if (insn->src_reg == MSP430_REG_PC) {
339 insn->src_mode = MSP430_AMODE_SYMBOLIC;
340 insn->src_addr = offset;
341 } else if (insn->src_reg == MSP430_REG_SR)
342 insn->src_mode = MSP430_AMODE_ABSOLUTE;
343 else if (insn->src_reg == MSP430_REG_R3)
344 need_src = 0;
345 break;
346
347 case MSP430_AMODE_INDIRECT: break;
348
349 case MSP430_AMODE_INDIRECT_INC:
350 if (insn->src_reg == MSP430_REG_PC) {
351 insn->src_mode = MSP430_AMODE_IMMEDIATE;
352 need_src = 1;
353 }
354 break;
355
356 default: break;
357 }
358
359 if (need_src) {
360 if (size < 2)
361 return -1;
362
363 insn->src_addr = add_index(insn->src_addr,
364 ((ex_word << 9) & 0xf0000) |
365 ((code[1] << 8) | code[0]),
366 ex_word);
367 offset += 2;
368 code += 2;
369 size -= 2;
370 ret += 2;
371 }
372
373 /* Decode and consume destination operand */
374 switch (insn->dst_mode) {
375 case MSP430_AMODE_REGISTER: break;
376 case MSP430_AMODE_INDEXED:
377 need_dst = 1;
378
379 if (insn->dst_reg == MSP430_REG_PC) {
380 insn->dst_mode = MSP430_AMODE_SYMBOLIC;
381 insn->dst_addr = offset;
382 } else if (insn->dst_reg == MSP430_REG_SR)
383 insn->dst_mode = MSP430_AMODE_ABSOLUTE;
384 break;
385
386 default: break;
387 }
388
389 if (need_dst) {
390 if (size < 2)
391 return -1;
392
393 insn->dst_addr = add_index(insn->dst_addr,
394 ((ex_word << 16) & 0xf0000) |
395 (code[1] << 8) | code[0],
396 ex_word);
397 ret += 2;
398 }
399
400 return ret;
401 }
402
403 /* Decode a jump instruction.
404 *
405 * All jump instructions are one word in length, so this function
406 * always returns 2 (to indicate the consumption of 2 bytes).
407 */
decode_jump(const uint8_t * code,address_t offset,struct msp430_instruction * insn)408 static int decode_jump(const uint8_t *code, address_t offset,
409 struct msp430_instruction *insn)
410 {
411 uint16_t op = (code[1] << 8) | code[0];
412 int tgtrel = op & 0x3ff;
413
414 if (tgtrel & 0x200)
415 tgtrel -= 0x400;
416
417 insn->op = op & 0xfc00;
418 insn->itype = MSP430_ITYPE_JUMP;
419 insn->dst_addr = offset + 2 + tgtrel * 2;
420 insn->dst_mode = MSP430_AMODE_SYMBOLIC;
421 insn->dst_reg = MSP430_REG_PC;
422
423 return 2;
424 }
425
remap_cgen(msp430_amode_t * mode,address_t * addr,msp430_reg_t * reg)426 static void remap_cgen(msp430_amode_t *mode,
427 address_t *addr,
428 msp430_reg_t *reg)
429 {
430 if (*reg == MSP430_REG_SR) {
431 if (*mode == MSP430_AMODE_INDIRECT) {
432 *mode = MSP430_AMODE_IMMEDIATE;
433 *addr = 4;
434 } else if (*mode == MSP430_AMODE_INDIRECT_INC) {
435 *mode = MSP430_AMODE_IMMEDIATE;
436 *addr = 8;
437 }
438 } else if (*reg == MSP430_REG_R3) {
439 if (*mode == MSP430_AMODE_REGISTER)
440 *addr = 0;
441 else if (*mode == MSP430_AMODE_INDEXED)
442 *addr = 1;
443 else if (*mode == MSP430_AMODE_INDIRECT)
444 *addr = 2;
445 else if (*mode == MSP430_AMODE_INDIRECT_INC)
446 *addr = ALL_ONES;
447
448 *mode = MSP430_AMODE_IMMEDIATE;
449 }
450 }
451
452 /* Take a decoded instruction and replace certain addressing modes of
453 * the constant generator registers with their corresponding immediate
454 * values.
455 */
find_cgens(struct msp430_instruction * insn)456 static void find_cgens(struct msp430_instruction *insn)
457 {
458 if (insn->itype == MSP430_ITYPE_DOUBLE)
459 remap_cgen(&insn->src_mode, &insn->src_addr,
460 &insn->src_reg);
461 else if (insn->itype == MSP430_ITYPE_SINGLE)
462 remap_cgen(&insn->dst_mode, &insn->dst_addr,
463 &insn->dst_reg);
464 }
465
466 /* Recognise special cases of real instructions and translate them to
467 * emulated instructions.
468 */
find_emulated_ops(struct msp430_instruction * insn)469 static void find_emulated_ops(struct msp430_instruction *insn)
470 {
471 switch (insn->op) {
472 case MSP430_OP_ADD:
473 if (insn->src_mode == MSP430_AMODE_IMMEDIATE) {
474 if (insn->src_addr == 1) {
475 insn->op = MSP430_OP_INC;
476 insn->itype = MSP430_ITYPE_SINGLE;
477 } else if (insn->src_addr == 2) {
478 insn->op = MSP430_OP_INCD;
479 insn->itype = MSP430_ITYPE_SINGLE;
480 }
481 } else if (insn->dst_mode == insn->src_mode &&
482 insn->dst_reg == insn->src_reg &&
483 insn->dst_addr == insn->src_addr) {
484 insn->op = MSP430_OP_RLA;
485 insn->itype = MSP430_ITYPE_SINGLE;
486 }
487 break;
488
489 case MSP430_OP_ADDA:
490 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
491 insn->src_addr == 2) {
492 insn->op = MSP430_OP_INCDA;
493 insn->itype = MSP430_ITYPE_SINGLE;
494 }
495 break;
496
497 case MSP430_OP_ADDX:
498 if (insn->src_mode == MSP430_AMODE_IMMEDIATE) {
499 if (insn->src_addr == 1) {
500 insn->op = MSP430_OP_INCX;
501 insn->itype = MSP430_ITYPE_SINGLE;
502 } else if (insn->src_addr == 2) {
503 insn->op = MSP430_OP_INCDX;
504 insn->itype = MSP430_ITYPE_SINGLE;
505 }
506 } else if (insn->dst_mode == insn->src_mode &&
507 insn->dst_reg == insn->src_reg &&
508 insn->dst_addr == insn->src_addr) {
509 insn->op = MSP430_OP_RLAX;
510 insn->itype = MSP430_ITYPE_SINGLE;
511 }
512 break;
513
514 case MSP430_OP_ADDC:
515 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
516 !insn->src_addr) {
517 insn->op = MSP430_OP_ADC;
518 insn->itype = MSP430_ITYPE_SINGLE;
519 } else if (insn->dst_mode == insn->src_mode &&
520 insn->dst_reg == insn->src_reg &&
521 insn->dst_addr == insn->src_addr) {
522 insn->op = MSP430_OP_RLC;
523 insn->itype = MSP430_ITYPE_SINGLE;
524 }
525 break;
526
527 case MSP430_OP_ADDCX:
528 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
529 !insn->src_addr) {
530 insn->op = MSP430_OP_ADCX;
531 insn->itype = MSP430_ITYPE_SINGLE;
532 } else if (insn->dst_mode == insn->src_mode &&
533 insn->dst_reg == insn->src_reg &&
534 insn->dst_addr == insn->src_addr) {
535 insn->op = MSP430_OP_RLCX;
536 insn->itype = MSP430_ITYPE_SINGLE;
537 }
538 break;
539
540 case MSP430_OP_BIC:
541 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
542 insn->dst_reg == MSP430_REG_SR &&
543 insn->src_mode == MSP430_AMODE_IMMEDIATE) {
544 if (insn->src_addr == 1) {
545 insn->op = MSP430_OP_CLRC;
546 insn->itype = MSP430_ITYPE_NOARG;
547 } else if (insn->src_addr == 4) {
548 insn->op = MSP430_OP_CLRN;
549 insn->itype = MSP430_ITYPE_NOARG;
550 } else if (insn->src_addr == 2) {
551 insn->op = MSP430_OP_CLRZ;
552 insn->itype = MSP430_ITYPE_NOARG;
553 } else if (insn->src_addr == 8) {
554 insn->op = MSP430_OP_DINT;
555 insn->itype = MSP430_ITYPE_NOARG;
556 }
557 }
558 break;
559
560 case MSP430_OP_BIS:
561 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
562 insn->dst_reg == MSP430_REG_SR &&
563 insn->src_mode == MSP430_AMODE_IMMEDIATE) {
564 if (insn->src_addr == 1) {
565 insn->op = MSP430_OP_SETC;
566 insn->itype = MSP430_ITYPE_NOARG;
567 } else if (insn->src_addr == 4) {
568 insn->op = MSP430_OP_SETN;
569 insn->itype = MSP430_ITYPE_NOARG;
570 } else if (insn->src_addr == 2) {
571 insn->op = MSP430_OP_SETZ;
572 insn->itype = MSP430_ITYPE_NOARG;
573 } else if (insn->src_addr == 8) {
574 insn->op = MSP430_OP_EINT;
575 insn->itype = MSP430_ITYPE_NOARG;
576 }
577 }
578 break;
579
580 case MSP430_OP_CMP:
581 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
582 !insn->src_addr) {
583 insn->op = MSP430_OP_TST;
584 insn->itype = MSP430_ITYPE_SINGLE;
585 }
586 break;
587
588 case MSP430_OP_CMPA:
589 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
590 !insn->src_addr) {
591 insn->op = MSP430_OP_TSTA;
592 insn->itype = MSP430_ITYPE_SINGLE;
593 }
594 break;
595
596 case MSP430_OP_CMPX:
597 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
598 !insn->src_addr) {
599 insn->op = MSP430_OP_TSTX;
600 insn->itype = MSP430_ITYPE_SINGLE;
601 }
602 break;
603
604 case MSP430_OP_DADD:
605 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
606 !insn->src_addr) {
607 insn->op = MSP430_OP_DADC;
608 insn->itype = MSP430_ITYPE_SINGLE;
609 }
610 break;
611
612 case MSP430_OP_DADDX:
613 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
614 !insn->src_addr) {
615 insn->op = MSP430_OP_DADCX;
616 insn->itype = MSP430_ITYPE_SINGLE;
617 }
618 break;
619
620 case MSP430_OP_MOV:
621 if (insn->src_mode == MSP430_AMODE_INDIRECT_INC &&
622 insn->src_reg == MSP430_REG_SP) {
623 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
624 insn->dst_reg == MSP430_REG_PC) {
625 insn->op = MSP430_OP_RET;
626 insn->itype = MSP430_ITYPE_NOARG;
627 } else {
628 insn->op = MSP430_OP_POP;
629 insn->itype = MSP430_ITYPE_SINGLE;
630 }
631 } else if (insn->dst_mode == MSP430_AMODE_REGISTER &&
632 insn->dst_reg == MSP430_REG_PC) {
633 insn->op = MSP430_OP_BR;
634 insn->itype = MSP430_ITYPE_SINGLE;
635 insn->dst_mode = insn->src_mode;
636 insn->dst_reg = insn->src_reg;
637 insn->dst_addr = insn->src_addr;
638 } else if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
639 !insn->src_addr) {
640 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
641 insn->dst_reg == MSP430_REG_R3) {
642 insn->op = MSP430_OP_NOP;
643 insn->itype = MSP430_ITYPE_NOARG;
644 } else {
645 insn->op = MSP430_OP_CLR;
646 insn->itype = MSP430_ITYPE_SINGLE;
647 }
648 }
649 break;
650
651 case MSP430_OP_MOVA:
652 if (insn->src_mode == MSP430_AMODE_INDIRECT_INC &&
653 insn->src_reg == MSP430_REG_SP) {
654 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
655 insn->dst_reg == MSP430_REG_PC) {
656 insn->op = MSP430_OP_RETA;
657 insn->itype = MSP430_ITYPE_NOARG;
658 } else {
659 insn->op = MSP430_OP_POPX;
660 insn->itype = MSP430_ITYPE_SINGLE;
661 }
662 } else if (insn->dst_mode == MSP430_AMODE_REGISTER &&
663 insn->dst_reg == MSP430_REG_PC) {
664 insn->op = MSP430_OP_BRA;
665 insn->itype = MSP430_ITYPE_SINGLE;
666 insn->dst_mode = insn->src_mode;
667 insn->dst_reg = insn->src_reg;
668 insn->dst_addr = insn->src_addr;
669 } else if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
670 !insn->src_addr) {
671 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
672 insn->dst_reg == MSP430_REG_R3) {
673 insn->op = MSP430_OP_NOP;
674 insn->itype = MSP430_ITYPE_NOARG;
675 } else {
676 insn->op = MSP430_OP_CLRX;
677 insn->itype = MSP430_ITYPE_SINGLE;
678 }
679 }
680 break;
681
682 case MSP430_OP_SUB:
683 if (insn->src_mode == MSP430_AMODE_IMMEDIATE) {
684 if (insn->src_addr == 1) {
685 insn->op = MSP430_OP_DEC;
686 insn->itype = MSP430_ITYPE_SINGLE;
687 } else if (insn->src_addr == 2) {
688 insn->op = MSP430_OP_DECD;
689 insn->itype = MSP430_ITYPE_SINGLE;
690 }
691 }
692 break;
693
694 case MSP430_OP_SUBA:
695 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
696 insn->src_addr == 2) {
697 insn->op = MSP430_OP_DECDA;
698 insn->itype = MSP430_ITYPE_SINGLE;
699 }
700 break;
701
702 case MSP430_OP_SUBX:
703 if (insn->src_mode == MSP430_AMODE_IMMEDIATE) {
704 if (insn->src_addr == 1) {
705 insn->op = MSP430_OP_DECX;
706 insn->itype = MSP430_ITYPE_SINGLE;
707 } else if (insn->src_addr == 2) {
708 insn->op = MSP430_OP_DECDX;
709 insn->itype = MSP430_ITYPE_SINGLE;
710 }
711 }
712 break;
713
714 case MSP430_OP_SUBC:
715 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
716 !insn->src_addr) {
717 insn->op = MSP430_OP_SBC;
718 insn->itype = MSP430_ITYPE_SINGLE;
719 }
720 break;
721
722 case MSP430_OP_SUBCX:
723 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
724 !insn->src_addr) {
725 insn->op = MSP430_OP_SECX;
726 insn->itype = MSP430_ITYPE_SINGLE;
727 }
728 break;
729
730 case MSP430_OP_XOR:
731 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
732 insn->src_addr == ALL_ONES) {
733 insn->op = MSP430_OP_INV;
734 insn->itype = MSP430_ITYPE_SINGLE;
735 }
736 break;
737
738 case MSP430_OP_XORX:
739 if (insn->src_mode == MSP430_AMODE_IMMEDIATE &&
740 insn->src_addr == ALL_ONES) {
741 insn->op = MSP430_OP_INVX;
742 insn->itype = MSP430_ITYPE_SINGLE;
743 }
744 break;
745
746 default: break;
747 }
748 }
749
750 /* Decode a single instruction.
751 *
752 * Returns the number of bytes consumed, or -1 if an error occured.
753 *
754 * The caller needs to pass a pointer to the bytes to be decoded, the
755 * virtual offset of those bytes, and the maximum number available. If
756 * successful, the decoded instruction is written into the structure
757 * pointed to by insn.
758 */
dis_decode(const uint8_t * code,address_t offset,address_t len,struct msp430_instruction * insn)759 int dis_decode(const uint8_t *code, address_t offset, address_t len,
760 struct msp430_instruction *insn)
761 {
762 uint16_t op;
763 uint16_t ex_word = 0;
764 int ret;
765 address_t ds_mask = ALL_ONES;
766
767 memset(insn, 0, sizeof(*insn));
768 insn->offset = offset;
769
770 /* Perform decoding */
771 if (len < 2)
772 return -1;
773 op = (code[1] << 8) | code[0];
774
775 if ((op & 0xf800) == 0x1800) {
776 ex_word = op;
777 code += 2;
778 offset += 2;
779 len -= 2;
780
781 if (len < 2)
782 return -1;
783 op = (code[1] << 8) | code[0];
784
785 if ((op & 0xf000) >= 0x4000)
786 ret = decode_double(code, offset, len, insn, ex_word);
787 else if ((op & 0xf000) == 0x1000 && (op & 0xfc00) < 0x1280)
788 ret = decode_single(code, offset, len, insn);
789 else
790 return -1;
791
792 insn->op |= EXTENSION_BIT;
793 ret += 2;
794
795 if (insn->dst_mode == MSP430_AMODE_REGISTER &&
796 (insn->itype == MSP430_ITYPE_SINGLE ||
797 insn->src_mode == MSP430_AMODE_REGISTER)) {
798 if ((ex_word >> 8) & 1) {
799 if (insn->op != MSP430_OP_RRCX)
800 return -1;
801 insn->op = MSP430_OP_RRUX;
802 }
803 insn->rep_register = (ex_word >> 7) & 1;
804 insn->rep_index = ex_word & 0xf;
805 }
806
807 if (!(ex_word & 0x40))
808 insn->dsize |= 2;
809 } else {
810 if ((op & 0xf000) == 0x0000)
811 ret = decode_00xx(code, len, insn);
812 else if ((op & 0xfc00) == 0x1400)
813 ret = decode_14xx(code, insn);
814 else if ((op & 0xff00) == 0x1300)
815 ret = decode_13xx(code, len, insn);
816 else if ((op & 0xf000) == 0x1000)
817 ret = decode_single(code, offset, len, insn);
818 else if ((op & 0xf000) >= 0x2000 && (op & 0xf000) < 0x4000)
819 ret = decode_jump(code, offset, insn);
820 else if ((op & 0xf000) >= 0x4000)
821 ret = decode_double(code, offset, len, insn, 0);
822 else
823 return -1;
824 }
825
826 /* Interpret "emulated" instructions, constant generation, and
827 * trim data sizes.
828 */
829 find_cgens(insn);
830 find_emulated_ops(insn);
831
832 if (insn->dsize == MSP430_DSIZE_BYTE)
833 ds_mask = 0xff;
834 else if (insn->dsize == MSP430_DSIZE_WORD)
835 ds_mask = 0xffff;
836
837 if (insn->src_mode == MSP430_AMODE_IMMEDIATE)
838 insn->src_addr &= ds_mask;
839 if (insn->dst_mode == MSP430_AMODE_IMMEDIATE)
840 insn->dst_addr &= ds_mask;
841
842 insn->len = ret;
843 return ret;
844 }
845
846 static const struct {
847 msp430_op_t op;
848 const char *mnemonic;
849 } opcode_names[] = {
850 /* Single operand */
851 {MSP430_OP_RRC, "RRC"},
852 {MSP430_OP_SWPB, "SWPB"},
853 {MSP430_OP_RRA, "RRA"},
854 {MSP430_OP_SXT, "SXT"},
855 {MSP430_OP_PUSH, "PUSH"},
856 {MSP430_OP_CALL, "CALL"},
857 {MSP430_OP_RETI, "RETI"},
858
859 /* Jump */
860 {MSP430_OP_JNZ, "JNZ"},
861 {MSP430_OP_JZ, "JZ"},
862 {MSP430_OP_JNC, "JNC"},
863 {MSP430_OP_JC, "JC"},
864 {MSP430_OP_JN, "JN"},
865 {MSP430_OP_JL, "JL"},
866 {MSP430_OP_JGE, "JGE"},
867 {MSP430_OP_JMP, "JMP"},
868
869 /* Double operand */
870 {MSP430_OP_MOV, "MOV"},
871 {MSP430_OP_ADD, "ADD"},
872 {MSP430_OP_ADDC, "ADDC"},
873 {MSP430_OP_SUBC, "SUBC"},
874 {MSP430_OP_SUB, "SUB"},
875 {MSP430_OP_CMP, "CMP"},
876 {MSP430_OP_DADD, "DADD"},
877 {MSP430_OP_BIT, "BIT"},
878 {MSP430_OP_BIC, "BIC"},
879 {MSP430_OP_BIS, "BIS"},
880 {MSP430_OP_XOR, "XOR"},
881 {MSP430_OP_AND, "AND"},
882
883 /* Emulated instructions */
884 {MSP430_OP_ADC, "ADC"},
885 {MSP430_OP_BR, "BR"},
886 {MSP430_OP_CLR, "CLR"},
887 {MSP430_OP_CLRC, "CLRC"},
888 {MSP430_OP_CLRN, "CLRN"},
889 {MSP430_OP_CLRZ, "CLRZ"},
890 {MSP430_OP_DADC, "DADC"},
891 {MSP430_OP_DEC, "DEC"},
892 {MSP430_OP_DECD, "DECD"},
893 {MSP430_OP_DINT, "DINT"},
894 {MSP430_OP_EINT, "EINT"},
895 {MSP430_OP_INC, "INC"},
896 {MSP430_OP_INCD, "INCD"},
897 {MSP430_OP_INV, "INV"},
898 {MSP430_OP_NOP, "NOP"},
899 {MSP430_OP_POP, "POP"},
900 {MSP430_OP_RET, "RET"},
901 {MSP430_OP_RLA, "RLA"},
902 {MSP430_OP_RLC, "RLC"},
903 {MSP430_OP_SBC, "SBC"},
904 {MSP430_OP_SETC, "SETC"},
905 {MSP430_OP_SETN, "SETN"},
906 {MSP430_OP_SETZ, "SETZ"},
907 {MSP430_OP_TST, "TST"},
908
909 /* MSP430X double operand (extension word) */
910 {MSP430_OP_MOVX, "MOVX"},
911 {MSP430_OP_ADDX, "ADDX"},
912 {MSP430_OP_ADDCX, "ADDCX"},
913 {MSP430_OP_SUBCX, "SUBCX"},
914 {MSP430_OP_SUBX, "SUBX"},
915 {MSP430_OP_CMPX, "CMPX"},
916 {MSP430_OP_DADDX, "DADDX"},
917 {MSP430_OP_BITX, "BITX"},
918 {MSP430_OP_BICX, "BICX"},
919 {MSP430_OP_BISX, "BISX"},
920 {MSP430_OP_XORX, "XORX"},
921 {MSP430_OP_ANDX, "ANDX"},
922
923 /* MSP430X single operand (extension word) */
924 {MSP430_OP_RRCX, "RRCX"},
925 {MSP430_OP_RRUX, "RRUX"},
926 {MSP430_OP_SWPBX, "SWPBX"},
927 {MSP430_OP_RRAX, "RRAX"},
928 {MSP430_OP_SXTX, "SXTX"},
929 {MSP430_OP_PUSHX, "PUSHX"},
930
931 /* MSP430X group 13xx */
932 {MSP430_OP_CALLA, "CALLA"},
933
934 /* MSP430X group 14xx */
935 {MSP430_OP_PUSHM, "PUSHM"},
936 {MSP430_OP_POPM, "POPM"},
937
938 /* MSP430X address instructions */
939 {MSP430_OP_MOVA, "MOVA"},
940 {MSP430_OP_CMPA, "CMPA"},
941 {MSP430_OP_SUBA, "SUBA"},
942 {MSP430_OP_ADDA, "ADDA"},
943
944 /* MSP430X group 00xx, non-address */
945 {MSP430_OP_RRCM, "RRCM"},
946 {MSP430_OP_RRAM, "RRAM"},
947 {MSP430_OP_RLAM, "RLAM"},
948 {MSP430_OP_RRUM, "RRUM"},
949
950 /* MSP430X emulated instructions */
951 {MSP430_OP_ADCX, "ADCX"},
952 {MSP430_OP_BRA, "BRA"},
953 {MSP430_OP_RETA, "RETA"},
954 {MSP430_OP_CLRX, "CLRX"},
955 {MSP430_OP_DADCX, "DADCX"},
956 {MSP430_OP_DECX, "DECX"},
957 {MSP430_OP_DECDA, "DECDA"},
958 {MSP430_OP_DECDX, "DECDX"},
959 {MSP430_OP_INCX, "INCX"},
960 {MSP430_OP_INCDA, "INCDA"},
961 {MSP430_OP_INVX, "INVX"},
962 {MSP430_OP_RLAX, "RLAX"},
963 {MSP430_OP_RLCX, "RLCX"},
964 {MSP430_OP_SECX, "SECX"},
965 {MSP430_OP_TSTA, "TSTA"},
966 {MSP430_OP_TSTX, "TSTX"},
967 {MSP430_OP_POPX, "POPX"},
968 {MSP430_OP_INCDX, "INCDX"}
969 };
970
971 /* Return the mnemonic for an operation, if possible. */
dis_opcode_name(msp430_op_t op)972 const char *dis_opcode_name(msp430_op_t op)
973 {
974 int i;
975
976 for (i = 0; i < ARRAY_LEN(opcode_names); i++)
977 if (op == opcode_names[i].op)
978 return opcode_names[i].mnemonic;
979
980 return NULL;
981 }
982
dis_opcode_from_name(const char * name)983 int dis_opcode_from_name(const char *name)
984 {
985 int i;
986
987 for (i = 0; i < ARRAY_LEN(opcode_names); i++)
988 if (!strcasecmp(name, opcode_names[i].mnemonic))
989 return opcode_names[i].op;
990
991 return -1;
992 }
993
994 static const char *const msp430_reg_names[] = {
995 "PC", "SP", "SR", "R3",
996 "R4", "R5", "R6", "R7",
997 "R8", "R9", "R10", "R11",
998 "R12", "R13", "R14", "R15"
999 };
1000
dis_reg_from_name(const char * name)1001 int dis_reg_from_name(const char *name)
1002 {
1003 int i;
1004
1005 if (!strcasecmp(name, "pc"))
1006 return 0;
1007 if (!strcasecmp(name, "sp"))
1008 return 1;
1009 if (!strcasecmp(name, "sr"))
1010 return 2;
1011
1012 if (toupper(*name) == 'R')
1013 name++;
1014
1015 for (i = 0; name[i]; i++)
1016 if (!isdigit(name[i]))
1017 return -1;
1018
1019 i = atoi(name);
1020 if (i < 0 || i > 15)
1021 return -1;
1022
1023 return i;
1024 }
1025
dis_reg_name(msp430_reg_t reg)1026 const char *dis_reg_name(msp430_reg_t reg)
1027 {
1028 if (reg <= 15)
1029 return msp430_reg_names[reg];
1030
1031 return NULL;
1032 }
1033