David Brownell <david-b@pacbell.net> ARM disassembly support for about five dozen...
[fw/openocd] / src / target / arm_disassembler.c
1 /***************************************************************************
2  *   Copyright (C) 2006 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2009 by David Brownell                                  *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "target.h"
27 #include "arm_disassembler.h"
28 #include "log.h"
29
30
31 /* textual represenation of the condition field */
32 /* ALways (default) is ommitted (empty string) */
33 char *arm_condition_strings[] =
34 {
35         "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
36 };
37
38 /* make up for C's missing ROR */
39 uint32_t ror(uint32_t value, int places)
40 {
41         return (value >> places) | (value << (32 - places));
42 }
43
44 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
45 {
46         /* PLD */
47         if ((opcode & 0x0d70f0000) == 0x0550f000)
48         {
49                 instruction->type = ARM_PLD;
50
51                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
52
53                 return ERROR_OK;
54         }
55         else
56         {
57                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
58                 return ERROR_OK;
59         }
60
61         LOG_ERROR("should never reach this point");
62         return -1;
63 }
64
65 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
66 {
67         instruction->type = ARM_SWI;
68
69         snprintf(instruction->text, 128,
70                         "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
71                         address, opcode, (opcode & 0xffffff));
72
73         return ERROR_OK;
74 }
75
76 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
77 {
78         int offset;
79         uint32_t immediate;
80         uint32_t target_address;
81
82         instruction->type = ARM_BLX;
83         immediate = opcode & 0x00ffffff;
84
85         /* sign extend 24-bit immediate */
86         if (immediate & 0x00800000)
87                 offset = 0xff000000 | immediate;
88         else
89                 offset = immediate;
90
91         /* shift two bits left */
92         offset <<= 2;
93
94         /* odd/event halfword */
95         if (opcode & 0x01000000)
96                 offset |= 0x2;
97
98         target_address = address + 8 + offset;
99
100         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
101
102         instruction->info.b_bl_bx_blx.reg_operand = -1;
103         instruction->info.b_bl_bx_blx.target_address = target_address;
104
105         return ERROR_OK;
106 }
107
108 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
109 {
110         uint8_t L;
111         uint32_t immediate;
112         int offset;
113         uint32_t target_address;
114
115         immediate = opcode & 0x00ffffff;
116         L = (opcode & 0x01000000) >> 24;
117
118         /* sign extend 24-bit immediate */
119         if (immediate & 0x00800000)
120                 offset = 0xff000000 | immediate;
121         else
122                 offset = immediate;
123
124         /* shift two bits left */
125         offset <<= 2;
126
127         target_address = address + 8 + offset;
128
129         if (L)
130                 instruction->type = ARM_BL;
131         else
132                 instruction->type = ARM_B;
133
134         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
135                          (L) ? "L" : "", COND(opcode), target_address);
136
137         instruction->info.b_bl_bx_blx.reg_operand = -1;
138         instruction->info.b_bl_bx_blx.target_address = target_address;
139
140         return ERROR_OK;
141 }
142
143 /* Coprocessor load/store and double register transfers */
144 /* both normal and extended instruction space (condition field b1111) */
145 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
146 {
147         uint8_t cp_num = (opcode & 0xf00) >> 8;
148
149         /* MCRR or MRRC */
150         if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
151         {
152                 uint8_t cp_opcode, Rd, Rn, CRm;
153                 char *mnemonic;
154
155                 cp_opcode = (opcode & 0xf0) >> 4;
156                 Rd = (opcode & 0xf000) >> 12;
157                 Rn = (opcode & 0xf0000) >> 16;
158                 CRm = (opcode & 0xf);
159
160                 /* MCRR */
161                 if ((opcode & 0x0ff00000) == 0x0c400000)
162                 {
163                         instruction->type = ARM_MCRR;
164                         mnemonic = "MCRR";
165                 }
166
167                 /* MRRC */
168                 if ((opcode & 0x0ff00000) == 0x0c500000)
169                 {
170                         instruction->type = ARM_MRRC;
171                         mnemonic = "MRRC";
172                 }
173
174                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
175                                  address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
176         }
177         else /* LDC or STC */
178         {
179                 uint8_t CRd, Rn, offset;
180                 uint8_t U, N;
181                 char *mnemonic;
182                 char addressing_mode[32];
183
184                 CRd = (opcode & 0xf000) >> 12;
185                 Rn = (opcode & 0xf0000) >> 16;
186                 offset = (opcode & 0xff);
187
188                 /* load/store */
189                 if (opcode & 0x00100000)
190                 {
191                         instruction->type = ARM_LDC;
192                         mnemonic = "LDC";
193                 }
194                 else
195                 {
196                         instruction->type = ARM_STC;
197                         mnemonic = "STC";
198                 }
199
200                 U = (opcode & 0x00800000) >> 23;
201                 N = (opcode & 0x00400000) >> 22;
202
203                 /* addressing modes */
204                 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
205                         snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
206                 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
207                         snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
208                 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
209                         snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
210                 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
211                         snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
212
213                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
214                                  address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
215                                  (N) ? "L" : "",
216                                  cp_num, CRd, addressing_mode);
217         }
218
219         return ERROR_OK;
220 }
221
222 /* Coprocessor data processing instructions */
223 /* Coprocessor register transfer instructions */
224 /* both normal and extended instruction space (condition field b1111) */
225 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
226 {
227         char* cond;
228         char* mnemonic;
229         uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
230
231         cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
232         cp_num = (opcode & 0xf00) >> 8;
233         CRd_Rd = (opcode & 0xf000) >> 12;
234         CRn = (opcode & 0xf0000) >> 16;
235         CRm = (opcode & 0xf);
236         opcode_2 = (opcode & 0xe0) >> 5;
237
238         /* CDP or MRC/MCR */
239         if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
240         {
241                 if (opcode & 0x00100000) /* bit 20 set -> MRC */
242                 {
243                         instruction->type = ARM_MRC;
244                         mnemonic = "MRC";
245                 }
246                 else /* bit 20 not set -> MCR */
247                 {
248                         instruction->type = ARM_MCR;
249                         mnemonic = "MCR";
250                 }
251
252                 opcode_1 = (opcode & 0x00e00000) >> 21;
253
254                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
255                                  address, opcode, mnemonic, cond,
256                                  cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
257         }
258         else /* bit 4 not set -> CDP */
259         {
260                 instruction->type = ARM_CDP;
261                 mnemonic = "CDP";
262
263                 opcode_1 = (opcode & 0x00f00000) >> 20;
264
265                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
266                                  address, opcode, mnemonic, cond,
267                                  cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
268         }
269
270         return ERROR_OK;
271 }
272
273 /* Load/store instructions */
274 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
275 {
276         uint8_t I, P, U, B, W, L;
277         uint8_t Rn, Rd;
278         char *operation; /* "LDR" or "STR" */
279         char *suffix; /* "", "B", "T", "BT" */
280         char offset[32];
281
282         /* examine flags */
283         I = (opcode & 0x02000000) >> 25;
284         P = (opcode & 0x01000000) >> 24;
285         U = (opcode & 0x00800000) >> 23;
286         B = (opcode & 0x00400000) >> 22;
287         W = (opcode & 0x00200000) >> 21;
288         L = (opcode & 0x00100000) >> 20;
289
290         /* target register */
291         Rd = (opcode & 0xf000) >> 12;
292
293         /* base register */
294         Rn = (opcode & 0xf0000) >> 16;
295
296         instruction->info.load_store.Rd = Rd;
297         instruction->info.load_store.Rn = Rn;
298         instruction->info.load_store.U = U;
299
300         /* determine operation */
301         if (L)
302                 operation = "LDR";
303         else
304                 operation = "STR";
305
306         /* determine instruction type and suffix */
307         if (B)
308         {
309                 if ((P == 0) && (W == 1))
310                 {
311                         if (L)
312                                 instruction->type = ARM_LDRBT;
313                         else
314                                 instruction->type = ARM_STRBT;
315                         suffix = "BT";
316                 }
317                 else
318                 {
319                         if (L)
320                                 instruction->type = ARM_LDRB;
321                         else
322                                 instruction->type = ARM_STRB;
323                         suffix = "B";
324                 }
325         }
326         else
327         {
328                 if ((P == 0) && (W == 1))
329                 {
330                         if (L)
331                                 instruction->type = ARM_LDRT;
332                         else
333                                 instruction->type = ARM_STRT;
334                         suffix = "T";
335                 }
336                 else
337                 {
338                         if (L)
339                                 instruction->type = ARM_LDR;
340                         else
341                                 instruction->type = ARM_STR;
342                         suffix = "";
343                 }
344         }
345
346         if (!I) /* #+-<offset_12> */
347         {
348                 uint32_t offset_12 = (opcode & 0xfff);
349                 if (offset_12)
350                         snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
351                 else
352                         snprintf(offset, 32, "%s", "");
353
354                 instruction->info.load_store.offset_mode = 0;
355                 instruction->info.load_store.offset.offset = offset_12;
356         }
357         else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
358         {
359                 uint8_t shift_imm, shift;
360                 uint8_t Rm;
361
362                 shift_imm = (opcode & 0xf80) >> 7;
363                 shift = (opcode & 0x60) >> 5;
364                 Rm = (opcode & 0xf);
365
366                 /* LSR encodes a shift by 32 bit as 0x0 */
367                 if ((shift == 0x1) && (shift_imm == 0x0))
368                         shift_imm = 0x20;
369
370                 /* ASR encodes a shift by 32 bit as 0x0 */
371                 if ((shift == 0x2) && (shift_imm == 0x0))
372                         shift_imm = 0x20;
373
374                 /* ROR by 32 bit is actually a RRX */
375                 if ((shift == 0x3) && (shift_imm == 0x0))
376                         shift = 0x4;
377
378                 instruction->info.load_store.offset_mode = 1;
379                 instruction->info.load_store.offset.reg.Rm = Rm;
380                 instruction->info.load_store.offset.reg.shift = shift;
381                 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
382
383                 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
384                 {
385                         snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
386                 }
387                 else /* +-<Rm>, <Shift>, #<shift_imm> */
388                 {
389                         switch (shift)
390                         {
391                                 case 0x0: /* LSL */
392                                         snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
393                                         break;
394                                 case 0x1: /* LSR */
395                                         snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
396                                         break;
397                                 case 0x2: /* ASR */
398                                         snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
399                                         break;
400                                 case 0x3: /* ROR */
401                                         snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
402                                         break;
403                                 case 0x4: /* RRX */
404                                         snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
405                                         break;
406                         }
407                 }
408         }
409
410         if (P == 1)
411         {
412                 if (W == 0) /* offset */
413                 {
414                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
415                                          address, opcode, operation, COND(opcode), suffix,
416                                          Rd, Rn, offset);
417
418                         instruction->info.load_store.index_mode = 0;
419                 }
420                 else /* pre-indexed */
421                 {
422                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
423                                          address, opcode, operation, COND(opcode), suffix,
424                                          Rd, Rn, offset);
425
426                         instruction->info.load_store.index_mode = 1;
427                 }
428         }
429         else /* post-indexed */
430         {
431                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
432                                  address, opcode, operation, COND(opcode), suffix,
433                                  Rd, Rn, offset);
434
435                 instruction->info.load_store.index_mode = 2;
436         }
437
438         return ERROR_OK;
439 }
440
441 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
442 {
443         unsigned rm = (opcode >> 0) & 0xf;
444         unsigned rd = (opcode >> 12) & 0xf;
445         unsigned rn = (opcode >> 16) & 0xf;
446         char *type, *rot;
447
448         switch ((opcode >> 24) & 0x3) {
449         case 0:
450                 type = "B16";
451                 break;
452         case 1:
453                 sprintf(cp, "UNDEFINED");
454                 return ARM_UNDEFINED_INSTRUCTION;
455         case 2:
456                 type = "B";
457                 break;
458         case 3:
459                 type = "H";
460                 break;
461         }
462
463         switch ((opcode >> 10) & 0x3) {
464         case 0:
465                 rot = "";
466                 break;
467         case 1:
468                 rot = ", ROR #8";
469                 break;
470         case 2:
471                 rot = ", ROR #16";
472                 break;
473         case 3:
474                 rot = ", ROR #24";
475                 break;
476         }
477
478         if (rn == 0xf) {
479                 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
480                                 (opcode & (1 << 22)) ? 'U' : 'S',
481                                 type, COND(opcode),
482                                 rd, rm, rot);
483                 return ARM_MOV;
484         } else {
485                 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
486                                 (opcode & (1 << 22)) ? 'U' : 'S',
487                                 type, COND(opcode),
488                                 rd, rn, rm, rot);
489                 return ARM_ADD;
490         }
491 }
492
493 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
494 {
495         char *prefix;
496         char *op;
497         int type;
498
499         switch ((opcode >> 20) & 0x7) {
500         case 1:
501                 prefix = "S";
502                 break;
503         case 2:
504                 prefix = "Q";
505                 break;
506         case 3:
507                 prefix = "SH";
508                 break;
509         case 5:
510                 prefix = "U";
511                 break;
512         case 6:
513                 prefix = "UQ";
514                 break;
515         case 7:
516                 prefix = "UH";
517                 break;
518         default:
519                 goto undef;
520         }
521
522         switch ((opcode >> 5) & 0x7) {
523         case 0:
524                 op = "ADD16";
525                 type = ARM_ADD;
526                 break;
527         case 1:
528                 op = "ADDSUBX";
529                 type = ARM_ADD;
530                 break;
531         case 2:
532                 op = "SUBADDX";
533                 type = ARM_SUB;
534                 break;
535         case 3:
536                 op = "SUB16";
537                 type = ARM_SUB;
538                 break;
539         case 4:
540                 op = "ADD8";
541                 type = ARM_ADD;
542                 break;
543         case 7:
544                 op = "SUB8";
545                 type = ARM_SUB;
546                 break;
547         default:
548                 goto undef;
549         }
550
551         sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
552                         (int) (opcode >> 12) & 0xf,
553                         (int) (opcode >> 16) & 0xf,
554                         (int) (opcode >> 0) & 0xf);
555         return type;
556
557 undef:
558         /* these opcodes might be used someday */
559         sprintf(cp, "UNDEFINED");
560         return ARM_UNDEFINED_INSTRUCTION;
561 }
562
563 /* ARMv6 and later support "media" instructions (includes SIMD) */
564 static int evaluate_media(uint32_t opcode, uint32_t address,
565                 arm_instruction_t *instruction)
566 {
567         char *cp = instruction->text;
568         char *mnemonic = NULL;
569
570         sprintf(cp,
571                 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
572                 address, opcode);
573         cp = strchr(cp, 0);
574
575         /* parallel add/subtract */
576         if ((opcode & 0x01800000) == 0x00000000) {
577                 instruction->type = evaluate_p_add_sub(opcode, address, cp);
578                 return ERROR_OK;
579         }
580
581         /* halfword pack */
582         if ((opcode & 0x01f00020) == 0x00800000) {
583                 char *type, *shift;
584                 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
585
586                 if (opcode & (1 << 6)) {
587                         type = "TB";
588                         shift = "ASR";
589                         if (imm == 0)
590                                 imm = 32;
591                 } else {
592                         type = "BT";
593                         shift = "LSL";
594                 }
595                 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
596                         type, COND(opcode),
597                         (int) (opcode >> 12) & 0xf,
598                         (int) (opcode >> 16) & 0xf,
599                         (int) (opcode >> 0) & 0xf,
600                         shift, imm);
601                 return ERROR_OK;
602         }
603
604         /* word saturate */
605         if ((opcode & 0x01a00020) == 0x00a00000) {
606                 char *shift;
607                 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
608
609                 if (opcode & (1 << 6)) {
610                         shift = "ASR";
611                         if (imm == 0)
612                                 imm = 32;
613                 } else {
614                         shift = "LSL";
615                 }
616
617                 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
618                         (opcode & (1 << 22)) ? 'U' : 'S',
619                         COND(opcode),
620                         (int) (opcode >> 12) & 0xf,
621                         (int) (opcode >> 16) & 0x1f,
622                         (int) (opcode >> 0) & 0xf,
623                         shift, imm);
624                 return ERROR_OK;
625         }
626
627         /* sign extension */
628         if ((opcode & 0x018000f0) == 0x00800070) {
629                 instruction->type = evaluate_extend(opcode, address, cp);
630                 return ERROR_OK;
631         }
632
633         /* multiplies */
634         if ((opcode & 0x01f00080) == 0x01000000) {
635                 unsigned rn = (opcode >> 12) & 0xf;
636
637                 if (rn != 0xf)
638                         sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
639                                 (opcode & (1 << 6)) ? 'S' : 'A',
640                                 (opcode & (1 << 5)) ? "X" : "",
641                                 COND(opcode),
642                                 (int) (opcode >> 16) & 0xf,
643                                 (int) (opcode >> 0) & 0xf,
644                                 (int) (opcode >> 8) & 0xf,
645                                 rn);
646                 else
647                         sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
648                                 (opcode & (1 << 6)) ? 'S' : 'A',
649                                 (opcode & (1 << 5)) ? "X" : "",
650                                 COND(opcode),
651                                 (int) (opcode >> 16) & 0xf,
652                                 (int) (opcode >> 0) & 0xf,
653                                 (int) (opcode >> 8) & 0xf);
654                 return ERROR_OK;
655         }
656         if ((opcode & 0x01f00000) == 0x01400000) {
657                 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
658                         (opcode & (1 << 6)) ? 'S' : 'A',
659                         (opcode & (1 << 5)) ? "X" : "",
660                         COND(opcode),
661                         (int) (opcode >> 12) & 0xf,
662                         (int) (opcode >> 16) & 0xf,
663                         (int) (opcode >> 0) & 0xf,
664                         (int) (opcode >> 8) & 0xf);
665                 return ERROR_OK;
666         }
667         if ((opcode & 0x01f00000) == 0x01500000) {
668                 unsigned rn = (opcode >> 12) & 0xf;
669
670                 switch (opcode & 0xc0) {
671                 case 3:
672                         if (rn == 0xf)
673                                 goto undef;
674                         /* FALL THROUGH */
675                 case 0:
676                         break;
677                 default:
678                         goto undef;
679                 }
680
681                 if (rn != 0xf)
682                         sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
683                                 (opcode & (1 << 6)) ? 'S' : 'A',
684                                 (opcode & (1 << 5)) ? "R" : "",
685                                 COND(opcode),
686                                 (int) (opcode >> 16) & 0xf,
687                                 (int) (opcode >> 0) & 0xf,
688                                 (int) (opcode >> 8) & 0xf,
689                                 rn);
690                 else
691                         sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
692                                 (opcode & (1 << 5)) ? "R" : "",
693                                 COND(opcode),
694                                 (int) (opcode >> 16) & 0xf,
695                                 (int) (opcode >> 0) & 0xf,
696                                 (int) (opcode >> 8) & 0xf);
697                 return ERROR_OK;
698         }
699
700
701         /* simple matches against the remaining decode bits */
702         switch (opcode & 0x01f000f0) {
703         case 0x00a00030:
704         case 0x00e00030:
705                 /* parallel halfword saturate */
706                 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
707                         (opcode & (1 << 22)) ? 'U' : 'S',
708                         COND(opcode),
709                         (int) (opcode >> 12) & 0xf,
710                         (int) (opcode >> 16) & 0xf,
711                         (int) (opcode >> 0) & 0xf);
712                 return ERROR_OK;
713         case 0x00b00030:
714                 mnemonic = "REV";
715                 break;
716         case 0x00b000b0:
717                 mnemonic = "REV16";
718                 break;
719         case 0x00f000b0:
720                 mnemonic = "REVSH";
721                 break;
722         case 0x008000b0:
723                 /* select bytes */
724                 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
725                         (int) (opcode >> 12) & 0xf,
726                         (int) (opcode >> 16) & 0xf,
727                         (int) (opcode >> 0) & 0xf);
728                 return ERROR_OK;
729         case 0x01800010:
730                 /* unsigned sum of absolute differences */
731                 if (((opcode >> 12) & 0xf) == 0xf)
732                         sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
733                                 (int) (opcode >> 16) & 0xf,
734                                 (int) (opcode >> 0) & 0xf,
735                                 (int) (opcode >> 8) & 0xf);
736                 else
737                         sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
738                                 (int) (opcode >> 16) & 0xf,
739                                 (int) (opcode >> 0) & 0xf,
740                                 (int) (opcode >> 8) & 0xf,
741                                 (int) (opcode >> 12) & 0xf);
742                 return ERROR_OK;
743         }
744         if (mnemonic) {
745                 unsigned rm = (opcode >> 0) & 0xf;
746                 unsigned rd = (opcode >> 12) & 0xf;
747
748                 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
749                 return ERROR_OK;
750         }
751
752 undef:
753         /* these opcodes might be used someday */
754         sprintf(cp, "UNDEFINED");
755         return ERROR_OK;
756 }
757
758 /* Miscellaneous load/store instructions */
759 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
760 {
761         uint8_t P, U, I, W, L, S, H;
762         uint8_t Rn, Rd;
763         char *operation; /* "LDR" or "STR" */
764         char *suffix; /* "H", "SB", "SH", "D" */
765         char offset[32];
766
767         /* examine flags */
768         P = (opcode & 0x01000000) >> 24;
769         U = (opcode & 0x00800000) >> 23;
770         I = (opcode & 0x00400000) >> 22;
771         W = (opcode & 0x00200000) >> 21;
772         L = (opcode & 0x00100000) >> 20;
773         S = (opcode & 0x00000040) >> 6;
774         H = (opcode & 0x00000020) >> 5;
775
776         /* target register */
777         Rd = (opcode & 0xf000) >> 12;
778
779         /* base register */
780         Rn = (opcode & 0xf0000) >> 16;
781
782         instruction->info.load_store.Rd = Rd;
783         instruction->info.load_store.Rn = Rn;
784         instruction->info.load_store.U = U;
785
786         /* determine instruction type and suffix */
787         if (S) /* signed */
788         {
789                 if (L) /* load */
790                 {
791                         if (H)
792                         {
793                                 operation = "LDR";
794                                 instruction->type = ARM_LDRSH;
795                                 suffix = "SH";
796                         }
797                         else
798                         {
799                                 operation = "LDR";
800                                 instruction->type = ARM_LDRSB;
801                                 suffix = "SB";
802                         }
803                 }
804                 else /* there are no signed stores, so this is used to encode double-register load/stores */
805                 {
806                         suffix = "D";
807                         if (H)
808                         {
809                                 operation = "STR";
810                                 instruction->type = ARM_STRD;
811                         }
812                         else
813                         {
814                                 operation = "LDR";
815                                 instruction->type = ARM_LDRD;
816                         }
817                 }
818         }
819         else /* unsigned */
820         {
821                 suffix = "H";
822                 if (L) /* load */
823                 {
824                         operation = "LDR";
825                         instruction->type = ARM_LDRH;
826                 }
827                 else /* store */
828                 {
829                         operation = "STR";
830                         instruction->type = ARM_STRH;
831                 }
832         }
833
834         if (I) /* Immediate offset/index (#+-<offset_8>)*/
835         {
836                 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
837                 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
838
839                 instruction->info.load_store.offset_mode = 0;
840                 instruction->info.load_store.offset.offset = offset_8;
841         }
842         else /* Register offset/index (+-<Rm>) */
843         {
844                 uint8_t Rm;
845                 Rm = (opcode & 0xf);
846                 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
847
848                 instruction->info.load_store.offset_mode = 1;
849                 instruction->info.load_store.offset.reg.Rm = Rm;
850                 instruction->info.load_store.offset.reg.shift = 0x0;
851                 instruction->info.load_store.offset.reg.shift_imm = 0x0;
852         }
853
854         if (P == 1)
855         {
856                 if (W == 0) /* offset */
857                 {
858                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
859                                          address, opcode, operation, COND(opcode), suffix,
860                                          Rd, Rn, offset);
861
862                         instruction->info.load_store.index_mode = 0;
863                 }
864                 else /* pre-indexed */
865                 {
866                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
867                                          address, opcode, operation, COND(opcode), suffix,
868                                          Rd, Rn, offset);
869
870                         instruction->info.load_store.index_mode = 1;
871                 }
872         }
873         else /* post-indexed */
874         {
875                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
876                                  address, opcode, operation, COND(opcode), suffix,
877                                  Rd, Rn, offset);
878
879                 instruction->info.load_store.index_mode = 2;
880         }
881
882         return ERROR_OK;
883 }
884
885 /* Load/store multiples instructions */
886 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
887 {
888         uint8_t P, U, S, W, L, Rn;
889         uint32_t register_list;
890         char *addressing_mode;
891         char *mnemonic;
892         char reg_list[69];
893         char *reg_list_p;
894         int i;
895         int first_reg = 1;
896
897         P = (opcode & 0x01000000) >> 24;
898         U = (opcode & 0x00800000) >> 23;
899         S = (opcode & 0x00400000) >> 22;
900         W = (opcode & 0x00200000) >> 21;
901         L = (opcode & 0x00100000) >> 20;
902         register_list = (opcode & 0xffff);
903         Rn = (opcode & 0xf0000) >> 16;
904
905         instruction->info.load_store_multiple.Rn = Rn;
906         instruction->info.load_store_multiple.register_list = register_list;
907         instruction->info.load_store_multiple.S = S;
908         instruction->info.load_store_multiple.W = W;
909
910         if (L)
911         {
912                 instruction->type = ARM_LDM;
913                 mnemonic = "LDM";
914         }
915         else
916         {
917                 instruction->type = ARM_STM;
918                 mnemonic = "STM";
919         }
920
921         if (P)
922         {
923                 if (U)
924                 {
925                         instruction->info.load_store_multiple.addressing_mode = 1;
926                         addressing_mode = "IB";
927                 }
928                 else
929                 {
930                         instruction->info.load_store_multiple.addressing_mode = 3;
931                         addressing_mode = "DB";
932                 }
933         }
934         else
935         {
936                 if (U)
937                 {
938                         instruction->info.load_store_multiple.addressing_mode = 0;
939                         /* "IA" is the default in UAL syntax */
940                         addressing_mode = "";
941                 }
942                 else
943                 {
944                         instruction->info.load_store_multiple.addressing_mode = 2;
945                         addressing_mode = "DA";
946                 }
947         }
948
949         reg_list_p = reg_list;
950         for (i = 0; i <= 15; i++)
951         {
952                 if ((register_list >> i) & 1)
953                 {
954                         if (first_reg)
955                         {
956                                 first_reg = 0;
957                                 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
958                         }
959                         else
960                         {
961                                 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
962                         }
963                 }
964         }
965
966         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
967                          address, opcode, mnemonic, COND(opcode), addressing_mode,
968                          Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
969
970         return ERROR_OK;
971 }
972
973 /* Multiplies, extra load/stores */
974 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
975 {
976         /* Multiply (accumulate) (long) and Swap/swap byte */
977         if ((opcode & 0x000000f0) == 0x00000090)
978         {
979                 /* Multiply (accumulate) */
980                 if ((opcode & 0x0f800000) == 0x00000000)
981                 {
982                         uint8_t Rm, Rs, Rn, Rd, S;
983                         Rm = opcode & 0xf;
984                         Rs = (opcode & 0xf00) >> 8;
985                         Rn = (opcode & 0xf000) >> 12;
986                         Rd = (opcode & 0xf0000) >> 16;
987                         S = (opcode & 0x00100000) >> 20;
988
989                         /* examine A bit (accumulate) */
990                         if (opcode & 0x00200000)
991                         {
992                                 instruction->type = ARM_MLA;
993                                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
994                                                 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
995                         }
996                         else
997                         {
998                                 instruction->type = ARM_MUL;
999                                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1000                                                  address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
1001                         }
1002
1003                         return ERROR_OK;
1004                 }
1005
1006                 /* Multiply (accumulate) long */
1007                 if ((opcode & 0x0f800000) == 0x00800000)
1008                 {
1009                         char* mnemonic = NULL;
1010                         uint8_t Rm, Rs, RdHi, RdLow, S;
1011                         Rm = opcode & 0xf;
1012                         Rs = (opcode & 0xf00) >> 8;
1013                         RdHi = (opcode & 0xf000) >> 12;
1014                         RdLow = (opcode & 0xf0000) >> 16;
1015                         S = (opcode & 0x00100000) >> 20;
1016
1017                         switch ((opcode & 0x00600000) >> 21)
1018                         {
1019                                 case 0x0:
1020                                         instruction->type = ARM_UMULL;
1021                                         mnemonic = "UMULL";
1022                                         break;
1023                                 case 0x1:
1024                                         instruction->type = ARM_UMLAL;
1025                                         mnemonic = "UMLAL";
1026                                         break;
1027                                 case 0x2:
1028                                         instruction->type = ARM_SMULL;
1029                                         mnemonic = "SMULL";
1030                                         break;
1031                                 case 0x3:
1032                                         instruction->type = ARM_SMLAL;
1033                                         mnemonic = "SMLAL";
1034                                         break;
1035                         }
1036
1037                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1038                                                 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
1039                                                 RdLow, RdHi, Rm, Rs);
1040
1041                         return ERROR_OK;
1042                 }
1043
1044                 /* Swap/swap byte */
1045                 if ((opcode & 0x0f800000) == 0x01000000)
1046                 {
1047                         uint8_t Rm, Rd, Rn;
1048                         Rm = opcode & 0xf;
1049                         Rd = (opcode & 0xf000) >> 12;
1050                         Rn = (opcode & 0xf0000) >> 16;
1051
1052                         /* examine B flag */
1053                         instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1054
1055                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1056                                          address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
1057                         return ERROR_OK;
1058                 }
1059
1060         }
1061
1062         return evaluate_misc_load_store(opcode, address, instruction);
1063 }
1064
1065 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1066 {
1067         int R = (opcode & 0x00400000) >> 22;
1068         char *PSR = (R) ? "SPSR" : "CPSR";
1069
1070         /* Move register to status register (MSR) */
1071         if (opcode & 0x00200000)
1072         {
1073                 instruction->type = ARM_MSR;
1074
1075                 /* immediate variant */
1076                 if (opcode & 0x02000000)
1077                 {
1078                         uint8_t immediate = (opcode & 0xff);
1079                         uint8_t rotate = (opcode & 0xf00);
1080
1081                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
1082                                          address, opcode, COND(opcode), PSR,
1083                                          (opcode & 0x10000) ? "c" : "",
1084                                          (opcode & 0x20000) ? "x" : "",
1085                                          (opcode & 0x40000) ? "s" : "",
1086                                          (opcode & 0x80000) ? "f" : "",
1087                                          ror(immediate, (rotate * 2))
1088 );
1089                 }
1090                 else /* register variant */
1091                 {
1092                         uint8_t Rm = opcode & 0xf;
1093                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1094                                          address, opcode, COND(opcode), PSR,
1095                                          (opcode & 0x10000) ? "c" : "",
1096                                          (opcode & 0x20000) ? "x" : "",
1097                                          (opcode & 0x40000) ? "s" : "",
1098                                          (opcode & 0x80000) ? "f" : "",
1099                                          Rm
1100 );
1101                 }
1102
1103         }
1104         else /* Move status register to register (MRS) */
1105         {
1106                 uint8_t Rd;
1107
1108                 instruction->type = ARM_MRS;
1109                 Rd = (opcode & 0x0000f000) >> 12;
1110
1111                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1112                                  address, opcode, COND(opcode), Rd, PSR);
1113         }
1114
1115         return ERROR_OK;
1116 }
1117
1118 /* Miscellaneous instructions */
1119 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1120 {
1121         /* MRS/MSR */
1122         if ((opcode & 0x000000f0) == 0x00000000)
1123         {
1124                 evaluate_mrs_msr(opcode, address, instruction);
1125         }
1126
1127         /* BX */
1128         if ((opcode & 0x006000f0) == 0x00200010)
1129         {
1130                 uint8_t Rm;
1131                 instruction->type = ARM_BX;
1132                 Rm = opcode & 0xf;
1133
1134                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1135                                  address, opcode, COND(opcode), Rm);
1136
1137                 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1138                 instruction->info.b_bl_bx_blx.target_address = -1;
1139         }
1140
1141         /* BXJ - "Jazelle" support (ARMv5-J) */
1142         if ((opcode & 0x006000f0) == 0x00200020)
1143         {
1144                 uint8_t Rm;
1145                 instruction->type = ARM_BX;
1146                 Rm = opcode & 0xf;
1147
1148                 snprintf(instruction->text, 128,
1149                                 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1150                                  address, opcode, COND(opcode), Rm);
1151
1152                 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1153                 instruction->info.b_bl_bx_blx.target_address = -1;
1154         }
1155
1156         /* CLZ */
1157         if ((opcode & 0x006000f0) == 0x00600010)
1158         {
1159                 uint8_t Rm, Rd;
1160                 instruction->type = ARM_CLZ;
1161                 Rm = opcode & 0xf;
1162                 Rd = (opcode & 0xf000) >> 12;
1163
1164                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1165                                  address, opcode, COND(opcode), Rd, Rm);
1166         }
1167
1168         /* BLX(2) */
1169         if ((opcode & 0x006000f0) == 0x00200030)
1170         {
1171                 uint8_t Rm;
1172                 instruction->type = ARM_BLX;
1173                 Rm = opcode & 0xf;
1174
1175                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1176                                  address, opcode, COND(opcode), Rm);
1177
1178                 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1179                 instruction->info.b_bl_bx_blx.target_address = -1;
1180         }
1181
1182         /* Enhanced DSP add/subtracts */
1183         if ((opcode & 0x0000000f0) == 0x00000050)
1184         {
1185                 uint8_t Rm, Rd, Rn;
1186                 char *mnemonic = NULL;
1187                 Rm = opcode & 0xf;
1188                 Rd = (opcode & 0xf000) >> 12;
1189                 Rn = (opcode & 0xf0000) >> 16;
1190
1191                 switch ((opcode & 0x00600000) >> 21)
1192                 {
1193                         case 0x0:
1194                                 instruction->type = ARM_QADD;
1195                                 mnemonic = "QADD";
1196                                 break;
1197                         case 0x1:
1198                                 instruction->type = ARM_QSUB;
1199                                 mnemonic = "QSUB";
1200                                 break;
1201                         case 0x2:
1202                                 instruction->type = ARM_QDADD;
1203                                 mnemonic = "QDADD";
1204                                 break;
1205                         case 0x3:
1206                                 instruction->type = ARM_QDSUB;
1207                                 mnemonic = "QDSUB";
1208                                 break;
1209                 }
1210
1211                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1212                                  address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
1213         }
1214
1215         /* Software breakpoints */
1216         if ((opcode & 0x0000000f0) == 0x00000070)
1217         {
1218                 uint32_t immediate;
1219                 instruction->type = ARM_BKPT;
1220                 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1221
1222                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
1223                                  address, opcode, immediate);
1224         }
1225
1226         /* Enhanced DSP multiplies */
1227         if ((opcode & 0x000000090) == 0x00000080)
1228         {
1229                 int x = (opcode & 0x20) >> 5;
1230                 int y = (opcode & 0x40) >> 6;
1231
1232                 /* SMLA < x><y> */
1233                 if ((opcode & 0x00600000) == 0x00000000)
1234                 {
1235                         uint8_t Rd, Rm, Rs, Rn;
1236                         instruction->type = ARM_SMLAxy;
1237                         Rd = (opcode & 0xf0000) >> 16;
1238                         Rm = (opcode & 0xf);
1239                         Rs = (opcode & 0xf00) >> 8;
1240                         Rn = (opcode & 0xf000) >> 12;
1241
1242                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1243                                          address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1244                                          Rd, Rm, Rs, Rn);
1245                 }
1246
1247                 /* SMLAL < x><y> */
1248                 if ((opcode & 0x00600000) == 0x00400000)
1249                 {
1250                         uint8_t RdLow, RdHi, Rm, Rs;
1251                         instruction->type = ARM_SMLAxy;
1252                         RdHi = (opcode & 0xf0000) >> 16;
1253                         RdLow = (opcode & 0xf000) >> 12;
1254                         Rm = (opcode & 0xf);
1255                         Rs = (opcode & 0xf00) >> 8;
1256
1257                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1258                                          address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1259                                          RdLow, RdHi, Rm, Rs);
1260                 }
1261
1262                 /* SMLAW < y> */
1263                 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
1264                 {
1265                         uint8_t Rd, Rm, Rs, Rn;
1266                         instruction->type = ARM_SMLAWy;
1267                         Rd = (opcode & 0xf0000) >> 16;
1268                         Rm = (opcode & 0xf);
1269                         Rs = (opcode & 0xf00) >> 8;
1270                         Rn = (opcode & 0xf000) >> 12;
1271
1272                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1273                                          address, opcode, (y) ? "T" : "B", COND(opcode),
1274                                          Rd, Rm, Rs, Rn);
1275                 }
1276
1277                 /* SMUL < x><y> */
1278                 if ((opcode & 0x00600000) == 0x00300000)
1279                 {
1280                         uint8_t Rd, Rm, Rs;
1281                         instruction->type = ARM_SMULxy;
1282                         Rd = (opcode & 0xf0000) >> 16;
1283                         Rm = (opcode & 0xf);
1284                         Rs = (opcode & 0xf00) >> 8;
1285
1286                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1287                                          address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1288                                          Rd, Rm, Rs);
1289                 }
1290
1291                 /* SMULW < y> */
1292                 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
1293                 {
1294                         uint8_t Rd, Rm, Rs;
1295                         instruction->type = ARM_SMULWy;
1296                         Rd = (opcode & 0xf0000) >> 16;
1297                         Rm = (opcode & 0xf);
1298                         Rs = (opcode & 0xf00) >> 8;
1299
1300                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1301                                          address, opcode, (y) ? "T" : "B", COND(opcode),
1302                                          Rd, Rm, Rs);
1303                 }
1304         }
1305
1306         return ERROR_OK;
1307 }
1308
1309 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1310 {
1311         uint8_t I, op, S, Rn, Rd;
1312         char *mnemonic = NULL;
1313         char shifter_operand[32];
1314
1315         I = (opcode & 0x02000000) >> 25;
1316         op = (opcode & 0x01e00000) >> 21;
1317         S = (opcode & 0x00100000) >> 20;
1318
1319         Rd = (opcode & 0xf000) >> 12;
1320         Rn = (opcode & 0xf0000) >> 16;
1321
1322         instruction->info.data_proc.Rd = Rd;
1323         instruction->info.data_proc.Rn = Rn;
1324         instruction->info.data_proc.S = S;
1325
1326         switch (op)
1327         {
1328                 case 0x0:
1329                         instruction->type = ARM_AND;
1330                         mnemonic = "AND";
1331                         break;
1332                 case 0x1:
1333                         instruction->type = ARM_EOR;
1334                         mnemonic = "EOR";
1335                         break;
1336                 case 0x2:
1337                         instruction->type = ARM_SUB;
1338                         mnemonic = "SUB";
1339                         break;
1340                 case 0x3:
1341                         instruction->type = ARM_RSB;
1342                         mnemonic = "RSB";
1343                         break;
1344                 case 0x4:
1345                         instruction->type = ARM_ADD;
1346                         mnemonic = "ADD";
1347                         break;
1348                 case 0x5:
1349                         instruction->type = ARM_ADC;
1350                         mnemonic = "ADC";
1351                         break;
1352                 case 0x6:
1353                         instruction->type = ARM_SBC;
1354                         mnemonic = "SBC";
1355                         break;
1356                 case 0x7:
1357                         instruction->type = ARM_RSC;
1358                         mnemonic = "RSC";
1359                         break;
1360                 case 0x8:
1361                         instruction->type = ARM_TST;
1362                         mnemonic = "TST";
1363                         break;
1364                 case 0x9:
1365                         instruction->type = ARM_TEQ;
1366                         mnemonic = "TEQ";
1367                         break;
1368                 case 0xa:
1369                         instruction->type = ARM_CMP;
1370                         mnemonic = "CMP";
1371                         break;
1372                 case 0xb:
1373                         instruction->type = ARM_CMN;
1374                         mnemonic = "CMN";
1375                         break;
1376                 case 0xc:
1377                         instruction->type = ARM_ORR;
1378                         mnemonic = "ORR";
1379                         break;
1380                 case 0xd:
1381                         instruction->type = ARM_MOV;
1382                         mnemonic = "MOV";
1383                         break;
1384                 case 0xe:
1385                         instruction->type = ARM_BIC;
1386                         mnemonic = "BIC";
1387                         break;
1388                 case 0xf:
1389                         instruction->type = ARM_MVN;
1390                         mnemonic = "MVN";
1391                         break;
1392         }
1393
1394         if (I) /* immediate shifter operand (#<immediate>)*/
1395         {
1396                 uint8_t immed_8 = opcode & 0xff;
1397                 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1398                 uint32_t immediate;
1399
1400                 immediate = ror(immed_8, rotate_imm * 2);
1401
1402                 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1403
1404                 instruction->info.data_proc.variant = 0;
1405                 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1406         }
1407         else /* register-based shifter operand */
1408         {
1409                 uint8_t shift, Rm;
1410                 shift = (opcode & 0x60) >> 5;
1411                 Rm = (opcode & 0xf);
1412
1413                 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1414                 {
1415                         uint8_t shift_imm;
1416                         shift_imm = (opcode & 0xf80) >> 7;
1417
1418                         instruction->info.data_proc.variant = 1;
1419                         instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1420                         instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1421                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1422
1423                         /* LSR encodes a shift by 32 bit as 0x0 */
1424                         if ((shift == 0x1) && (shift_imm == 0x0))
1425                                 shift_imm = 0x20;
1426
1427                         /* ASR encodes a shift by 32 bit as 0x0 */
1428                         if ((shift == 0x2) && (shift_imm == 0x0))
1429                                 shift_imm = 0x20;
1430
1431                         /* ROR by 32 bit is actually a RRX */
1432                         if ((shift == 0x3) && (shift_imm == 0x0))
1433                                 shift = 0x4;
1434
1435                         if ((shift_imm == 0x0) && (shift == 0x0))
1436                         {
1437                                 snprintf(shifter_operand, 32, "r%i", Rm);
1438                         }
1439                         else
1440                         {
1441                                 if (shift == 0x0) /* LSL */
1442                                 {
1443                                         snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1444                                 }
1445                                 else if (shift == 0x1) /* LSR */
1446                                 {
1447                                         snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1448                                 }
1449                                 else if (shift == 0x2) /* ASR */
1450                                 {
1451                                         snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1452                                 }
1453                                 else if (shift == 0x3) /* ROR */
1454                                 {
1455                                         snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1456                                 }
1457                                 else if (shift == 0x4) /* RRX */
1458                                 {
1459                                         snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1460                                 }
1461                         }
1462                 }
1463                 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1464                 {
1465                         uint8_t Rs = (opcode & 0xf00) >> 8;
1466
1467                         instruction->info.data_proc.variant = 2;
1468                         instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1469                         instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1470                         instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1471
1472                         if (shift == 0x0) /* LSL */
1473                         {
1474                                 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1475                         }
1476                         else if (shift == 0x1) /* LSR */
1477                         {
1478                                 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1479                         }
1480                         else if (shift == 0x2) /* ASR */
1481                         {
1482                                 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1483                         }
1484                         else if (shift == 0x3) /* ROR */
1485                         {
1486                                 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1487                         }
1488                 }
1489         }
1490
1491         if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1492         {
1493                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1494                                  address, opcode, mnemonic, COND(opcode),
1495                                  (S) ? "S" : "", Rd, Rn, shifter_operand);
1496         }
1497         else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1498         {
1499                 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1500                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1501                 else
1502                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1503                                  address, opcode, mnemonic, COND(opcode),
1504                                  (S) ? "S" : "", Rd, shifter_operand);
1505         }
1506         else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1507         {
1508                 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1509                                  address, opcode, mnemonic, COND(opcode),
1510                                  Rn, shifter_operand);
1511         }
1512
1513         return ERROR_OK;
1514 }
1515
1516 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1517 {
1518         /* clear fields, to avoid confusion */
1519         memset(instruction, 0, sizeof(arm_instruction_t));
1520         instruction->opcode = opcode;
1521         instruction->instruction_size = 4;
1522
1523         /* catch opcodes with condition field [31:28] = b1111 */
1524         if ((opcode & 0xf0000000) == 0xf0000000)
1525         {
1526                 /* Undefined instruction (or ARMv5E cache preload PLD) */
1527                 if ((opcode & 0x08000000) == 0x00000000)
1528                         return evaluate_pld(opcode, address, instruction);
1529
1530                 /* Undefined instruction */
1531                 if ((opcode & 0x0e000000) == 0x08000000)
1532                 {
1533                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1534                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1535                         return ERROR_OK;
1536                 }
1537
1538                 /* Branch and branch with link and change to Thumb */
1539                 if ((opcode & 0x0e000000) == 0x0a000000)
1540                         return evaluate_blx_imm(opcode, address, instruction);
1541
1542                 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1543                 /* Coprocessor load/store and double register transfers */
1544                 if ((opcode & 0x0e000000) == 0x0c000000)
1545                         return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1546
1547                 /* Coprocessor data processing */
1548                 if ((opcode & 0x0f000100) == 0x0c000000)
1549                         return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1550
1551                 /* Coprocessor register transfers */
1552                 if ((opcode & 0x0f000010) == 0x0c000010)
1553                         return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1554
1555                 /* Undefined instruction */
1556                 if ((opcode & 0x0f000000) == 0x0f000000)
1557                 {
1558                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1559                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1560                         return ERROR_OK;
1561                 }
1562         }
1563
1564         /* catch opcodes with [27:25] = b000 */
1565         if ((opcode & 0x0e000000) == 0x00000000)
1566         {
1567                 /* Multiplies, extra load/stores */
1568                 if ((opcode & 0x00000090) == 0x00000090)
1569                         return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1570
1571                 /* Miscellaneous instructions */
1572                 if ((opcode & 0x0f900000) == 0x01000000)
1573                         return evaluate_misc_instr(opcode, address, instruction);
1574
1575                 return evaluate_data_proc(opcode, address, instruction);
1576         }
1577
1578         /* catch opcodes with [27:25] = b001 */
1579         if ((opcode & 0x0e000000) == 0x02000000)
1580         {
1581                 /* Undefined instruction */
1582                 if ((opcode & 0x0fb00000) == 0x03000000)
1583                 {
1584                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1585                         snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1586                         return ERROR_OK;
1587                 }
1588
1589                 /* Move immediate to status register */
1590                 if ((opcode & 0x0fb00000) == 0x03200000)
1591                         return evaluate_mrs_msr(opcode, address, instruction);
1592
1593                 return evaluate_data_proc(opcode, address, instruction);
1594
1595         }
1596
1597         /* catch opcodes with [27:25] = b010 */
1598         if ((opcode & 0x0e000000) == 0x04000000)
1599         {
1600                 /* Load/store immediate offset */
1601                 return evaluate_load_store(opcode, address, instruction);
1602         }
1603
1604         /* catch opcodes with [27:25] = b011 */
1605         if ((opcode & 0x0e000000) == 0x06000000)
1606         {
1607                 /* Load/store register offset */
1608                 if ((opcode & 0x00000010) == 0x00000000)
1609                         return evaluate_load_store(opcode, address, instruction);
1610
1611                 /* Architecturally Undefined instruction
1612                  * ... don't expect these to ever be used
1613                  */
1614                 if ((opcode & 0x07f000f0) == 0x07f000f0)
1615                 {
1616                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1617                         snprintf(instruction->text, 128,
1618                                 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1619                                 address, opcode);
1620                         return ERROR_OK;
1621                 }
1622
1623                 /* "media" instructions */
1624                 return evaluate_media(opcode, address, instruction);
1625         }
1626
1627         /* catch opcodes with [27:25] = b100 */
1628         if ((opcode & 0x0e000000) == 0x08000000)
1629         {
1630                 /* Load/store multiple */
1631                 return evaluate_ldm_stm(opcode, address, instruction);
1632         }
1633
1634         /* catch opcodes with [27:25] = b101 */
1635         if ((opcode & 0x0e000000) == 0x0a000000)
1636         {
1637                 /* Branch and branch with link */
1638                 return evaluate_b_bl(opcode, address, instruction);
1639         }
1640
1641         /* catch opcodes with [27:25] = b110 */
1642         if ((opcode & 0x0e000000) == 0x0a000000)
1643         {
1644                 /* Coprocessor load/store and double register transfers */
1645                 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1646         }
1647
1648         /* catch opcodes with [27:25] = b111 */
1649         if ((opcode & 0x0e000000) == 0x0e000000)
1650         {
1651                 /* Software interrupt */
1652                 if ((opcode & 0x0f000000) == 0x0f000000)
1653                         return evaluate_swi(opcode, address, instruction);
1654
1655                 /* Coprocessor data processing */
1656                 if ((opcode & 0x0f000010) == 0x0e000000)
1657                         return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1658
1659                 /* Coprocessor register transfers */
1660                 if ((opcode & 0x0f000010) == 0x0e000010)
1661                         return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1662         }
1663
1664         LOG_ERROR("should never reach this point");
1665         return -1;
1666 }
1667
1668 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1669 {
1670         uint32_t offset = opcode & 0x7ff;
1671         uint32_t opc = (opcode >> 11) & 0x3;
1672         uint32_t target_address;
1673         char *mnemonic = NULL;
1674
1675         /* sign extend 11-bit offset */
1676         if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1677                 offset = 0xfffff800 | offset;
1678
1679         target_address = address + 4 + (offset << 1);
1680
1681         switch (opc)
1682         {
1683                 /* unconditional branch */
1684                 case 0:
1685                         instruction->type = ARM_B;
1686                         mnemonic = "B";
1687                         break;
1688                 /* BLX suffix */
1689                 case 1:
1690                         instruction->type = ARM_BLX;
1691                         mnemonic = "BLX";
1692                         break;
1693                 /* BL/BLX prefix */
1694                 case 2:
1695                         instruction->type = ARM_UNKNOWN_INSTUCTION;
1696                         mnemonic = "prefix";
1697                         target_address = offset << 12;
1698                         break;
1699                 /* BL suffix */
1700                 case 3:
1701                         instruction->type = ARM_BL;
1702                         mnemonic = "BL";
1703                         break;
1704         }
1705
1706         /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1707          * these are effectively 32-bit instructions even in Thumb1.
1708          * Might be simplest to always use the Thumb2 decoder.
1709          */
1710
1711         snprintf(instruction->text, 128,
1712                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\t%#8.8" PRIx32,
1713                         address, opcode, mnemonic, target_address);
1714
1715         instruction->info.b_bl_bx_blx.reg_operand = -1;
1716         instruction->info.b_bl_bx_blx.target_address = target_address;
1717
1718         return ERROR_OK;
1719 }
1720
1721 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1722 {
1723         uint8_t Rd = (opcode >> 0) & 0x7;
1724         uint8_t Rn = (opcode >> 3) & 0x7;
1725         uint8_t Rm_imm = (opcode >> 6) & 0x7;
1726         uint32_t opc = opcode & (1 << 9);
1727         uint32_t reg_imm  = opcode & (1 << 10);
1728         char *mnemonic;
1729
1730         if (opc)
1731         {
1732                 instruction->type = ARM_SUB;
1733                 mnemonic = "SUBS";
1734         }
1735         else
1736         {
1737                 /* REVISIT:  if reg_imm == 0, display as "MOVS" */
1738                 instruction->type = ARM_ADD;
1739                 mnemonic = "ADDS";
1740         }
1741
1742         instruction->info.data_proc.Rd = Rd;
1743         instruction->info.data_proc.Rn = Rn;
1744         instruction->info.data_proc.S = 1;
1745
1746         if (reg_imm)
1747         {
1748                 instruction->info.data_proc.variant = 0; /*immediate*/
1749                 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1750                 snprintf(instruction->text, 128,
1751                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%d",
1752                         address, opcode, mnemonic, Rd, Rn, Rm_imm);
1753         }
1754         else
1755         {
1756                 instruction->info.data_proc.variant = 1; /*immediate shift*/
1757                 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1758                 snprintf(instruction->text, 128,
1759                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, r%i",
1760                         address, opcode, mnemonic, Rd, Rn, Rm_imm);
1761         }
1762
1763         return ERROR_OK;
1764 }
1765
1766 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1767 {
1768         uint8_t Rd = (opcode >> 0) & 0x7;
1769         uint8_t Rm = (opcode >> 3) & 0x7;
1770         uint8_t imm = (opcode >> 6) & 0x1f;
1771         uint8_t opc = (opcode >> 11) & 0x3;
1772         char *mnemonic = NULL;
1773
1774         switch (opc)
1775         {
1776                 case 0:
1777                         instruction->type = ARM_MOV;
1778                         mnemonic = "LSLS";
1779                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1780                         break;
1781                 case 1:
1782                         instruction->type = ARM_MOV;
1783                         mnemonic = "LSRS";
1784                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1785                         break;
1786                 case 2:
1787                         instruction->type = ARM_MOV;
1788                         mnemonic = "ASRS";
1789                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1790                         break;
1791         }
1792
1793         if ((imm == 0) && (opc != 0))
1794                 imm = 32;
1795
1796         instruction->info.data_proc.Rd = Rd;
1797         instruction->info.data_proc.Rn = -1;
1798         instruction->info.data_proc.S = 1;
1799
1800         instruction->info.data_proc.variant = 1; /*immediate_shift*/
1801         instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1802         instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1803
1804         snprintf(instruction->text, 128,
1805                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%#2.2x" ,
1806                         address, opcode, mnemonic, Rd, Rm, imm);
1807
1808         return ERROR_OK;
1809 }
1810
1811 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1812 {
1813         uint8_t imm = opcode & 0xff;
1814         uint8_t Rd = (opcode >> 8) & 0x7;
1815         uint32_t opc = (opcode >> 11) & 0x3;
1816         char *mnemonic = NULL;
1817
1818         instruction->info.data_proc.Rd = Rd;
1819         instruction->info.data_proc.Rn = Rd;
1820         instruction->info.data_proc.S = 1;
1821         instruction->info.data_proc.variant = 0; /*immediate*/
1822         instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1823
1824         switch (opc)
1825         {
1826                 case 0:
1827                         instruction->type = ARM_MOV;
1828                         mnemonic = "MOVS";
1829                         instruction->info.data_proc.Rn = -1;
1830                         break;
1831                 case 1:
1832                         instruction->type = ARM_CMP;
1833                         mnemonic = "CMP";
1834                         instruction->info.data_proc.Rd = -1;
1835                         break;
1836                 case 2:
1837                         instruction->type = ARM_ADD;
1838                         mnemonic = "ADDS";
1839                         break;
1840                 case 3:
1841                         instruction->type = ARM_SUB;
1842                         mnemonic = "SUBS";
1843                         break;
1844         }
1845
1846         snprintf(instruction->text, 128,
1847                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, #%#2.2x",
1848                         address, opcode, mnemonic, Rd, imm);
1849
1850         return ERROR_OK;
1851 }
1852
1853 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1854 {
1855         uint8_t high_reg, op, Rm, Rd,H1,H2;
1856         char *mnemonic = NULL;
1857         bool nop = false;
1858
1859         high_reg = (opcode & 0x0400) >> 10;
1860         op = (opcode & 0x03C0) >> 6;
1861
1862         Rd = (opcode & 0x0007);
1863         Rm = (opcode & 0x0038) >> 3;
1864         H1 = (opcode & 0x0080) >> 7;
1865         H2 = (opcode & 0x0040) >> 6;
1866
1867         instruction->info.data_proc.Rd = Rd;
1868         instruction->info.data_proc.Rn = Rd;
1869         instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1870         instruction->info.data_proc.variant = 1 /*immediate shift*/;
1871         instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1872
1873         if (high_reg)
1874         {
1875                 Rd |= H1 << 3;
1876                 Rm |= H2 << 3;
1877                 op >>= 2;
1878
1879                 switch (op)
1880                 {
1881                         case 0x0:
1882                                 instruction->type = ARM_ADD;
1883                                 mnemonic = "ADD";
1884                                 break;
1885                         case 0x1:
1886                                 instruction->type = ARM_CMP;
1887                                 mnemonic = "CMP";
1888                                 break;
1889                         case 0x2:
1890                                 instruction->type = ARM_MOV;
1891                                 mnemonic = "MOV";
1892                                 if (Rd == Rm)
1893                                         nop = true;
1894                                 break;
1895                         case 0x3:
1896                                 if ((opcode & 0x7) == 0x0)
1897                                 {
1898                                         instruction->info.b_bl_bx_blx.reg_operand = Rm;
1899                                         if (H1)
1900                                         {
1901                                                 instruction->type = ARM_BLX;
1902                                                 snprintf(instruction->text, 128,
1903                                                         "0x%8.8" PRIx32
1904                                                         "  0x%4.4x    \tBLX\tr%i",
1905                                                         address, opcode, Rm);
1906                                         }
1907                                         else
1908                                         {
1909                                                 instruction->type = ARM_BX;
1910                                                 snprintf(instruction->text, 128,
1911                                                         "0x%8.8" PRIx32
1912                                                         "  0x%4.4x    \tBX\tr%i",
1913                                                         address, opcode, Rm);
1914                                         }
1915                                 }
1916                                 else
1917                                 {
1918                                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1919                                         snprintf(instruction->text, 128,
1920                                                 "0x%8.8" PRIx32
1921                                                 "  0x%4.4x    \t"
1922                                                 "UNDEFINED INSTRUCTION",
1923                                                 address, opcode);
1924                                 }
1925                                 return ERROR_OK;
1926                                 break;
1927                 }
1928         }
1929         else
1930         {
1931                 switch (op)
1932                 {
1933                         case 0x0:
1934                                 instruction->type = ARM_AND;
1935                                 mnemonic = "ANDS";
1936                                 break;
1937                         case 0x1:
1938                                 instruction->type = ARM_EOR;
1939                                 mnemonic = "EORS";
1940                                 break;
1941                         case 0x2:
1942                                 instruction->type = ARM_MOV;
1943                                 mnemonic = "LSLS";
1944                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1945                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1946                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1947                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1948                                 break;
1949                         case 0x3:
1950                                 instruction->type = ARM_MOV;
1951                                 mnemonic = "LSRS";
1952                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1953                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1954                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1955                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1956                                 break;
1957                         case 0x4:
1958                                 instruction->type = ARM_MOV;
1959                                 mnemonic = "ASRS";
1960                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1961                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1962                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1963                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1964                                 break;
1965                         case 0x5:
1966                                 instruction->type = ARM_ADC;
1967                                 mnemonic = "ADCS";
1968                                 break;
1969                         case 0x6:
1970                                 instruction->type = ARM_SBC;
1971                                 mnemonic = "SBCS";
1972                                 break;
1973                         case 0x7:
1974                                 instruction->type = ARM_MOV;
1975                                 mnemonic = "RORS";
1976                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1977                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1978                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1979                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1980                                 break;
1981                         case 0x8:
1982                                 instruction->type = ARM_TST;
1983                                 mnemonic = "TST";
1984                                 break;
1985                         case 0x9:
1986                                 instruction->type = ARM_RSB;
1987                                 mnemonic = "RSBS";
1988                                 instruction->info.data_proc.variant = 0 /*immediate*/;
1989                                 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1990                                 instruction->info.data_proc.Rn = Rm;
1991                                 break;
1992                         case 0xA:
1993                                 instruction->type = ARM_CMP;
1994                                 mnemonic = "CMP";
1995                                 break;
1996                         case 0xB:
1997                                 instruction->type = ARM_CMN;
1998                                 mnemonic = "CMN";
1999                                 break;
2000                         case 0xC:
2001                                 instruction->type = ARM_ORR;
2002                                 mnemonic = "ORRS";
2003                                 break;
2004                         case 0xD:
2005                                 instruction->type = ARM_MUL;
2006                                 mnemonic = "MULS";
2007                                 break;
2008                         case 0xE:
2009                                 instruction->type = ARM_BIC;
2010                                 mnemonic = "BICS";
2011                                 break;
2012                         case 0xF:
2013                                 instruction->type = ARM_MVN;
2014                                 mnemonic = "MVNS";
2015                                 break;
2016                 }
2017         }
2018
2019         if (nop)
2020                 snprintf(instruction->text, 128,
2021                                 "0x%8.8" PRIx32 "  0x%4.4x    \tNOP\t\t\t"
2022                                 "; (%s r%i, r%i)",
2023                                  address, opcode, mnemonic, Rd, Rm);
2024         else
2025                 snprintf(instruction->text, 128,
2026                                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i",
2027                                  address, opcode, mnemonic, Rd, Rm);
2028
2029         return ERROR_OK;
2030 }
2031
2032 /* PC-relative data addressing is word-aligned even with Thumb */
2033 static inline uint32_t thumb_alignpc4(uint32_t addr)
2034 {
2035         return (addr + 4) & ~3;
2036 }
2037
2038 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2039 {
2040         uint32_t immediate;
2041         uint8_t Rd = (opcode >> 8) & 0x7;
2042
2043         instruction->type = ARM_LDR;
2044         immediate = opcode & 0x000000ff;
2045         immediate *= 4;
2046
2047         instruction->info.load_store.Rd = Rd;
2048         instruction->info.load_store.Rn = 15 /*PC*/;
2049         instruction->info.load_store.index_mode = 0; /*offset*/
2050         instruction->info.load_store.offset_mode = 0; /*immediate*/
2051         instruction->info.load_store.offset.offset = immediate;
2052
2053         snprintf(instruction->text, 128,
2054                 "0x%8.8" PRIx32 "  0x%4.4x    \t"
2055                 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2056                 address, opcode, Rd, immediate,
2057                 thumb_alignpc4(address) + immediate);
2058
2059         return ERROR_OK;
2060 }
2061
2062 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2063 {
2064         uint8_t Rd = (opcode >> 0) & 0x7;
2065         uint8_t Rn = (opcode >> 3) & 0x7;
2066         uint8_t Rm = (opcode >> 6) & 0x7;
2067         uint8_t opc = (opcode >> 9) & 0x7;
2068         char *mnemonic = NULL;
2069
2070         switch (opc)
2071         {
2072                 case 0:
2073                         instruction->type = ARM_STR;
2074                         mnemonic = "STR";
2075                         break;
2076                 case 1:
2077                         instruction->type = ARM_STRH;
2078                         mnemonic = "STRH";
2079                         break;
2080                 case 2:
2081                         instruction->type = ARM_STRB;
2082                         mnemonic = "STRB";
2083                         break;
2084                 case 3:
2085                         instruction->type = ARM_LDRSB;
2086                         mnemonic = "LDRSB";
2087                         break;
2088                 case 4:
2089                         instruction->type = ARM_LDR;
2090                         mnemonic = "LDR";
2091                         break;
2092                 case 5:
2093                         instruction->type = ARM_LDRH;
2094                         mnemonic = "LDRH";
2095                         break;
2096                 case 6:
2097                         instruction->type = ARM_LDRB;
2098                         mnemonic = "LDRB";
2099                         break;
2100                 case 7:
2101                         instruction->type = ARM_LDRSH;
2102                         mnemonic = "LDRSH";
2103                         break;
2104         }
2105
2106         snprintf(instruction->text, 128,
2107                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [r%i, r%i]",
2108                         address, opcode, mnemonic, Rd, Rn, Rm);
2109
2110         instruction->info.load_store.Rd = Rd;
2111         instruction->info.load_store.Rn = Rn;
2112         instruction->info.load_store.index_mode = 0; /*offset*/
2113         instruction->info.load_store.offset_mode = 1; /*register*/
2114         instruction->info.load_store.offset.reg.Rm = Rm;
2115
2116         return ERROR_OK;
2117 }
2118
2119 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2120 {
2121         uint32_t offset = (opcode >> 6) & 0x1f;
2122         uint8_t Rd = (opcode >> 0) & 0x7;
2123         uint8_t Rn = (opcode >> 3) & 0x7;
2124         uint32_t L = opcode & (1 << 11);
2125         uint32_t B = opcode & (1 << 12);
2126         char *mnemonic;
2127         char suffix = ' ';
2128         uint32_t shift = 2;
2129
2130         if (L)
2131         {
2132                 instruction->type = ARM_LDR;
2133                 mnemonic = "LDR";
2134         }
2135         else
2136         {
2137                 instruction->type = ARM_STR;
2138                 mnemonic = "STR";
2139         }
2140
2141         if ((opcode&0xF000) == 0x8000)
2142         {
2143                 suffix = 'H';
2144                 shift = 1;
2145         }
2146         else if (B)
2147         {
2148                 suffix = 'B';
2149                 shift = 0;
2150         }
2151
2152         snprintf(instruction->text, 128,
2153                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2154                 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2155
2156         instruction->info.load_store.Rd = Rd;
2157         instruction->info.load_store.Rn = Rn;
2158         instruction->info.load_store.index_mode = 0; /*offset*/
2159         instruction->info.load_store.offset_mode = 0; /*immediate*/
2160         instruction->info.load_store.offset.offset = offset << shift;
2161
2162         return ERROR_OK;
2163 }
2164
2165 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2166 {
2167         uint32_t offset = opcode  & 0xff;
2168         uint8_t Rd = (opcode >> 8) & 0x7;
2169         uint32_t L = opcode & (1 << 11);
2170         char *mnemonic;
2171
2172         if (L)
2173         {
2174                 instruction->type = ARM_LDR;
2175                 mnemonic = "LDR";
2176         }
2177         else
2178         {
2179                 instruction->type = ARM_STR;
2180                 mnemonic = "STR";
2181         }
2182
2183         snprintf(instruction->text, 128,
2184                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [SP, #%#" PRIx32 "]",
2185                 address, opcode, mnemonic, Rd, offset*4);
2186
2187         instruction->info.load_store.Rd = Rd;
2188         instruction->info.load_store.Rn = 13 /*SP*/;
2189         instruction->info.load_store.index_mode = 0; /*offset*/
2190         instruction->info.load_store.offset_mode = 0; /*immediate*/
2191         instruction->info.load_store.offset.offset = offset*4;
2192
2193         return ERROR_OK;
2194 }
2195
2196 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2197 {
2198         uint32_t imm = opcode  & 0xff;
2199         uint8_t Rd = (opcode >> 8) & 0x7;
2200         uint8_t Rn;
2201         uint32_t SP = opcode & (1 << 11);
2202         char *reg_name;
2203
2204         instruction->type = ARM_ADD;
2205
2206         if (SP)
2207         {
2208                 reg_name = "SP";
2209                 Rn = 13;
2210         }
2211         else
2212         {
2213                 reg_name = "PC";
2214                 Rn = 15;
2215         }
2216
2217         snprintf(instruction->text, 128,
2218                 "0x%8.8" PRIx32 "  0x%4.4x  \tADD\tr%i, %s, #%#" PRIx32,
2219                 address, opcode, Rd, reg_name, imm * 4);
2220
2221         instruction->info.data_proc.variant = 0 /* immediate */;
2222         instruction->info.data_proc.Rd = Rd;
2223         instruction->info.data_proc.Rn = Rn;
2224         instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2225
2226         return ERROR_OK;
2227 }
2228
2229 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2230 {
2231         uint32_t imm = opcode  & 0x7f;
2232         uint8_t opc = opcode & (1 << 7);
2233         char *mnemonic;
2234
2235
2236         if (opc)
2237         {
2238                 instruction->type = ARM_SUB;
2239                 mnemonic = "SUB";
2240         }
2241         else
2242         {
2243                 instruction->type = ARM_ADD;
2244                 mnemonic = "ADD";
2245         }
2246
2247         snprintf(instruction->text, 128,
2248                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tSP, #%#" PRIx32,
2249                         address, opcode, mnemonic, imm*4);
2250
2251         instruction->info.data_proc.variant = 0 /* immediate */;
2252         instruction->info.data_proc.Rd = 13 /*SP*/;
2253         instruction->info.data_proc.Rn = 13 /*SP*/;
2254         instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2255
2256         return ERROR_OK;
2257 }
2258
2259 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2260 {
2261         uint32_t imm = opcode  & 0xff;
2262
2263         instruction->type = ARM_BKPT;
2264
2265         snprintf(instruction->text, 128,
2266                         "0x%8.8" PRIx32 "  0x%4.4x  \tBKPT\t%#2.2" PRIx32 "",
2267                         address, opcode, imm);
2268
2269         return ERROR_OK;
2270 }
2271
2272 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2273 {
2274         uint32_t reg_list = opcode  & 0xff;
2275         uint32_t L = opcode & (1 << 11);
2276         uint32_t R = opcode & (1 << 8);
2277         uint8_t Rn = (opcode >> 8) & 7;
2278         uint8_t addr_mode = 0 /* IA */;
2279         char reg_names[40];
2280         char *reg_names_p;
2281         char *mnemonic;
2282         char ptr_name[7] = "";
2283         int i;
2284
2285         if ((opcode & 0xf000) == 0xc000)
2286         { /* generic load/store multiple */
2287                 char *wback = "!";
2288
2289                 if (L)
2290                 {
2291                         instruction->type = ARM_LDM;
2292                         mnemonic = "LDM";
2293                         if (opcode & (1 << Rn))
2294                                 wback = "";
2295                 }
2296                 else
2297                 {
2298                         instruction->type = ARM_STM;
2299                         mnemonic = "STM";
2300                 }
2301                 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2302         }
2303         else
2304         { /* push/pop */
2305                 Rn = 13; /* SP */
2306                 if (L)
2307                 {
2308                         instruction->type = ARM_LDM;
2309                         mnemonic = "POP";
2310                         if (R)
2311                                 reg_list |= (1 << 15) /*PC*/;
2312                 }
2313                 else
2314                 {
2315                         instruction->type = ARM_STM;
2316                         mnemonic = "PUSH";
2317                         addr_mode = 3; /*DB*/
2318                         if (R)
2319                                 reg_list |= (1 << 14) /*LR*/;
2320                 }
2321         }
2322
2323         reg_names_p = reg_names;
2324         for (i = 0; i <= 15; i++)
2325         {
2326                 if (reg_list & (1 << i))
2327                         reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
2328         }
2329         if (reg_names_p > reg_names)
2330                 reg_names_p[-2] = '\0';
2331         else /* invalid op : no registers */
2332                 reg_names[0] = '\0';
2333
2334         snprintf(instruction->text, 128,
2335                         "0x%8.8" PRIx32 "  0x%4.4x  \t%s\t%s{%s}",
2336                         address, opcode, mnemonic, ptr_name, reg_names);
2337
2338         instruction->info.load_store_multiple.register_list = reg_list;
2339         instruction->info.load_store_multiple.Rn = Rn;
2340         instruction->info.load_store_multiple.addressing_mode = addr_mode;
2341
2342         return ERROR_OK;
2343 }
2344
2345 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2346 {
2347         uint32_t offset = opcode  & 0xff;
2348         uint8_t cond = (opcode >> 8) & 0xf;
2349         uint32_t target_address;
2350
2351         if (cond == 0xf)
2352         {
2353                 instruction->type = ARM_SWI;
2354                 snprintf(instruction->text, 128,
2355                                 "0x%8.8" PRIx32 "  0x%4.4x    \tSVC\t%#2.2" PRIx32,
2356                                 address, opcode, offset);
2357                 return ERROR_OK;
2358         }
2359         else if (cond == 0xe)
2360         {
2361                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2362                 snprintf(instruction->text, 128,
2363                         "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
2364                         address, opcode);
2365                 return ERROR_OK;
2366         }
2367
2368         /* sign extend 8-bit offset */
2369         if (offset & 0x00000080)
2370                 offset = 0xffffff00 | offset;
2371
2372         target_address = address + 4 + (offset << 1);
2373
2374         snprintf(instruction->text, 128,
2375                         "0x%8.8" PRIx32 "  0x%4.4x    \tB%s\t%#8.8" PRIx32,
2376                         address, opcode,
2377                         arm_condition_strings[cond], target_address);
2378
2379         instruction->type = ARM_B;
2380         instruction->info.b_bl_bx_blx.reg_operand = -1;
2381         instruction->info.b_bl_bx_blx.target_address = target_address;
2382
2383         return ERROR_OK;
2384 }
2385
2386 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2387                 arm_instruction_t *instruction)
2388 {
2389         unsigned offset;
2390
2391         /* added in Thumb2 */
2392         offset = (opcode >> 3) & 0x1f;
2393         offset |= (opcode & 0x0200) >> 4;
2394
2395         snprintf(instruction->text, 128,
2396                         "0x%8.8" PRIx32 "  0x%4.4x    \tCB%sZ\tr%d, %#8.8" PRIx32,
2397                         address, opcode,
2398                         (opcode & 0x0800) ? "N" : "",
2399                         opcode & 0x7, address + 4 + (offset << 1));
2400
2401         return ERROR_OK;
2402 }
2403
2404 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2405                 arm_instruction_t *instruction)
2406 {
2407         /* added in ARMv6 */
2408         snprintf(instruction->text, 128,
2409                         "0x%8.8" PRIx32 "  0x%4.4x    \t%cXT%c\tr%d, r%d",
2410                         address, opcode,
2411                         (opcode & 0x0080) ? 'U' : 'S',
2412                         (opcode & 0x0040) ? 'B' : 'H',
2413                         opcode & 0x7, (opcode >> 3) & 0x7);
2414
2415         return ERROR_OK;
2416 }
2417
2418 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2419                 arm_instruction_t *instruction)
2420 {
2421         /* added in ARMv6 */
2422         if ((opcode & 0x0ff0) == 0x0650)
2423                 snprintf(instruction->text, 128,
2424                                 "0x%8.8" PRIx32 "  0x%4.4x    \tSETEND %s",
2425                                 address, opcode,
2426                                 (opcode & 0x80) ? "BE" : "LE");
2427         else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2428                 snprintf(instruction->text, 128,
2429                                 "0x%8.8" PRIx32 "  0x%4.4x    \tCPSI%c\t%s%s%s",
2430                                 address, opcode,
2431                                 (opcode & 0x0010) ? 'D' : 'E',
2432                                 (opcode & 0x0004) ? "A" : "",
2433                                 (opcode & 0x0002) ? "I" : "",
2434                                 (opcode & 0x0001) ? "F" : "");
2435
2436         return ERROR_OK;
2437 }
2438
2439 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2440                 arm_instruction_t *instruction)
2441 {
2442         char *suffix;
2443
2444         /* added in ARMv6 */
2445         switch ((opcode >> 6) & 3) {
2446         case 0:
2447                 suffix = "";
2448                 break;
2449         case 1:
2450                 suffix = "16";
2451                 break;
2452         default:
2453                 suffix = "SH";
2454                 break;
2455         }
2456         snprintf(instruction->text, 128,
2457                         "0x%8.8" PRIx32 "  0x%4.4x    \tREV%s\tr%d, r%d",
2458                         address, opcode, suffix,
2459                         opcode & 0x7, (opcode >> 3) & 0x7);
2460
2461         return ERROR_OK;
2462 }
2463
2464 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2465                 arm_instruction_t *instruction)
2466 {
2467         char *hint;
2468
2469         switch ((opcode >> 4) & 0x0f) {
2470         case 0:
2471                 hint = "NOP";
2472                 break;
2473         case 1:
2474                 hint = "YIELD";
2475                 break;
2476         case 2:
2477                 hint = "WFE";
2478                 break;
2479         case 3:
2480                 hint = "WFI";
2481                 break;
2482         case 4:
2483                 hint = "SEV";
2484                 break;
2485         default:
2486                 hint = "HINT (UNRECOGNIZED)";
2487                 break;
2488         }
2489
2490         snprintf(instruction->text, 128,
2491                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s",
2492                         address, opcode, hint);
2493
2494         return ERROR_OK;
2495 }
2496
2497 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2498                 arm_instruction_t *instruction)
2499 {
2500         unsigned cond = (opcode >> 4) & 0x0f;
2501         char *x = "", *y = "", *z = "";
2502
2503         if (opcode & 0x01)
2504                 z = (opcode & 0x02) ? "T" : "E";
2505         if (opcode & 0x03)
2506                 y = (opcode & 0x04) ? "T" : "E";
2507         if (opcode & 0x07)
2508                 x = (opcode & 0x08) ? "T" : "E";
2509
2510         snprintf(instruction->text, 128,
2511                         "0x%8.8" PRIx32 "  0x%4.4x    \tIT%s%s%s\t%s",
2512                         address, opcode,
2513                         x, y, z, arm_condition_strings[cond]);
2514
2515         /* NOTE:  strictly speaking, the next 1-4 instructions should
2516          * now be displayed with the relevant conditional suffix...
2517          */
2518
2519         return ERROR_OK;
2520 }
2521
2522 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2523 {
2524         /* clear fields, to avoid confusion */
2525         memset(instruction, 0, sizeof(arm_instruction_t));
2526         instruction->opcode = opcode;
2527         instruction->instruction_size = 2;
2528
2529         if ((opcode & 0xe000) == 0x0000)
2530         {
2531                 /* add/substract register or immediate */
2532                 if ((opcode & 0x1800) == 0x1800)
2533                         return evaluate_add_sub_thumb(opcode, address, instruction);
2534                 /* shift by immediate */
2535                 else
2536                         return evaluate_shift_imm_thumb(opcode, address, instruction);
2537         }
2538
2539         /* Add/substract/compare/move immediate */
2540         if ((opcode & 0xe000) == 0x2000)
2541         {
2542                 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2543         }
2544
2545         /* Data processing instructions */
2546         if ((opcode & 0xf800) == 0x4000)
2547         {
2548                 return evaluate_data_proc_thumb(opcode, address, instruction);
2549         }
2550
2551         /* Load from literal pool */
2552         if ((opcode & 0xf800) == 0x4800)
2553         {
2554                 return evaluate_load_literal_thumb(opcode, address, instruction);
2555         }
2556
2557         /* Load/Store register offset */
2558         if ((opcode & 0xf000) == 0x5000)
2559         {
2560                 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2561         }
2562
2563         /* Load/Store immediate offset */
2564         if (((opcode & 0xe000) == 0x6000)
2565                 ||((opcode & 0xf000) == 0x8000))
2566         {
2567                 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2568         }
2569
2570         /* Load/Store from/to stack */
2571         if ((opcode & 0xf000) == 0x9000)
2572         {
2573                 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2574         }
2575
2576         /* Add to SP/PC */
2577         if ((opcode & 0xf000) == 0xa000)
2578         {
2579                 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2580         }
2581
2582         /* Misc */
2583         if ((opcode & 0xf000) == 0xb000)
2584         {
2585                 switch ((opcode >> 8) & 0x0f) {
2586                 case 0x0:
2587                         return evaluate_adjust_stack_thumb(opcode, address, instruction);
2588                 case 0x1:
2589                 case 0x3:
2590                 case 0x9:
2591                 case 0xb:
2592                         return evaluate_cb_thumb(opcode, address, instruction);
2593                 case 0x2:
2594                         return evaluate_extend_thumb(opcode, address, instruction);
2595                 case 0x4:
2596                 case 0x5:
2597                 case 0xc:
2598                 case 0xd:
2599                         return evaluate_load_store_multiple_thumb(opcode, address,
2600                                                 instruction);
2601                 case 0x6:
2602                         return evaluate_cps_thumb(opcode, address, instruction);
2603                 case 0xa:
2604                         if ((opcode & 0x00c0) == 0x0080)
2605                                 break;
2606                         return evaluate_byterev_thumb(opcode, address, instruction);
2607                 case 0xe:
2608                         return evaluate_breakpoint_thumb(opcode, address, instruction);
2609                 case 0xf:
2610                         if (opcode & 0x000f)
2611                                 return evaluate_ifthen_thumb(opcode, address,
2612                                                 instruction);
2613                         else
2614                                 return evaluate_hint_thumb(opcode, address,
2615                                                 instruction);
2616                 }
2617
2618                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2619                 snprintf(instruction->text, 128,
2620                         "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
2621                         address, opcode);
2622                 return ERROR_OK;
2623         }
2624
2625         /* Load/Store multiple */
2626         if ((opcode & 0xf000) == 0xc000)
2627         {
2628                 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2629         }
2630
2631         /* Conditional branch + SWI */
2632         if ((opcode & 0xf000) == 0xd000)
2633         {
2634                 return evaluate_cond_branch_thumb(opcode, address, instruction);
2635         }
2636
2637         if ((opcode & 0xe000) == 0xe000)
2638         {
2639                 /* Undefined instructions */
2640                 if ((opcode & 0xf801) == 0xe801)
2641                 {
2642                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
2643                         snprintf(instruction->text, 128,
2644                                         "0x%8.8" PRIx32 "  0x%8.8x\t"
2645                                         "UNDEFINED INSTRUCTION",
2646                                         address, opcode);
2647                         return ERROR_OK;
2648                 }
2649                 else
2650                 { /* Branch to offset */
2651                         return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2652                 }
2653         }
2654
2655         LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2656         return -1;
2657 }
2658
2659 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2660                 arm_instruction_t *instruction, char *cp)
2661 {
2662         unsigned offset;
2663         unsigned b21 = 1 << 21;
2664         unsigned b22 = 1 << 22;
2665
2666         /* instead of combining two smaller 16-bit branch instructions,
2667          * Thumb2 uses only one larger 32-bit instruction.
2668          */
2669         offset = opcode & 0x7ff;
2670         offset |= (opcode & 0x03ff0000) >> 5;
2671         if (opcode & (1 << 26)) {
2672                 offset |= 0xff << 23;
2673                 if ((opcode & (1 << 11)) == 0)
2674                         b21 = 0;
2675                 if ((opcode & (1 << 13)) == 0)
2676                         b22 = 0;
2677         } else {
2678                 if (opcode & (1 << 11))
2679                         b21 = 0;
2680                 if (opcode & (1 << 13))
2681                         b22 = 0;
2682         }
2683         offset |= b21;
2684         offset |= b22;
2685
2686
2687         address += 4;
2688         address += offset << 1;
2689
2690         instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2691         instruction->info.b_bl_bx_blx.reg_operand = -1;
2692         instruction->info.b_bl_bx_blx.target_address = address;
2693         sprintf(cp, "%s\t%#8.8" PRIx32,
2694                         (opcode & (1 << 14)) ? "BL" : "B.W",
2695                         address);
2696
2697         return ERROR_OK;
2698 }
2699
2700 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2701                 arm_instruction_t *instruction, char *cp)
2702 {
2703         unsigned offset;
2704         unsigned b17 = 1 << 17;
2705         unsigned b18 = 1 << 18;
2706         unsigned cond = (opcode >> 22) & 0x0f;
2707
2708         offset = opcode & 0x7ff;
2709         offset |= (opcode & 0x003f0000) >> 5;
2710         if (opcode & (1 << 26)) {
2711                 offset |= 0xffff << 19;
2712                 if ((opcode & (1 << 11)) == 0)
2713                         b17 = 0;
2714                 if ((opcode & (1 << 13)) == 0)
2715                         b18 = 0;
2716         } else {
2717                 if (opcode & (1 << 11))
2718                         b17 = 0;
2719                 if (opcode & (1 << 13))
2720                         b18 = 0;
2721         }
2722         offset |= b17;
2723         offset |= b18;
2724
2725         address += 4;
2726         address += offset << 1;
2727
2728         instruction->type = ARM_B;
2729         instruction->info.b_bl_bx_blx.reg_operand = -1;
2730         instruction->info.b_bl_bx_blx.target_address = address;
2731         sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2732                         arm_condition_strings[cond],
2733                         address);
2734
2735         return ERROR_OK;
2736 }
2737
2738 static const char *special_name(int number)
2739 {
2740         char *special = "(RESERVED)";
2741
2742         switch (number) {
2743         case 0:
2744                 special = "apsr";
2745                 break;
2746         case 1:
2747                 special = "iapsr";
2748                 break;
2749         case 2:
2750                 special = "eapsr";
2751                 break;
2752         case 3:
2753                 special = "xpsr";
2754                 break;
2755         case 5:
2756                 special = "ipsr";
2757                 break;
2758         case 6:
2759                 special = "epsr";
2760                 break;
2761         case 7:
2762                 special = "iepsr";
2763                 break;
2764         case 8:
2765                 special = "msp";
2766                 break;
2767         case 9:
2768                 special = "psp";
2769                 break;
2770         case 16:
2771                 special = "primask";
2772                 break;
2773         case 17:
2774                 special = "basepri";
2775                 break;
2776         case 18:
2777                 special = "basepri_max";
2778                 break;
2779         case 19:
2780                 special = "faultmask";
2781                 break;
2782         case 20:
2783                 special = "control";
2784                 break;
2785         }
2786         return special;
2787 }
2788
2789 static int t2ev_hint(uint32_t opcode, uint32_t address,
2790                 arm_instruction_t *instruction, char *cp)
2791 {
2792         const char *mnemonic;
2793
2794         if (opcode & 0x0700) {
2795                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2796                 strcpy(cp, "UNDEFINED");
2797                 return ERROR_OK;
2798         }
2799
2800         if (opcode & 0x00f0) {
2801                 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2802                 return ERROR_OK;
2803         }
2804
2805         switch (opcode & 0x0f) {
2806         case 0:
2807                 mnemonic = "NOP.W";
2808                 break;
2809         case 1:
2810                 mnemonic = "YIELD.W";
2811                 break;
2812         case 2:
2813                 mnemonic = "WFE.W";
2814                 break;
2815         case 3:
2816                 mnemonic = "WFI.W";
2817                 break;
2818         case 4:
2819                 mnemonic = "SEV.W";
2820                 break;
2821         default:
2822                 mnemonic = "HINT.W (UNRECOGNIZED)";
2823                 break;
2824         }
2825         strcpy(cp, mnemonic);
2826         return ERROR_OK;
2827 }
2828
2829 static int t2ev_misc(uint32_t opcode, uint32_t address,
2830                 arm_instruction_t *instruction, char *cp)
2831 {
2832         const char *mnemonic;
2833
2834         switch ((opcode >> 4) & 0x0f) {
2835         case 2:
2836                 mnemonic = "CLREX";
2837                 break;
2838         case 4:
2839                 mnemonic = "DSB";
2840                 break;
2841         case 5:
2842                 mnemonic = "DMB";
2843                 break;
2844         case 6:
2845                 mnemonic = "ISB";
2846                 break;
2847         default:
2848                 return ERROR_INVALID_ARGUMENTS;
2849         }
2850         strcpy(cp, mnemonic);
2851         return ERROR_OK;
2852 }
2853
2854 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2855                 arm_instruction_t *instruction, char *cp)
2856 {
2857         /* permanently undefined */
2858         if ((opcode & 0x07f07000) == 0x07f02000) {
2859                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2860                 strcpy(cp, "UNDEFINED");
2861                 return ERROR_OK;
2862         }
2863
2864         switch ((opcode >> 12) & 0x5) {
2865         case 0x1:
2866         case 0x5:
2867                 return t2ev_b_bl(opcode, address, instruction, cp);
2868         case 0x4:
2869                 goto undef;
2870         case 0:
2871                 if (((opcode >> 23) & 0x07) != 0x07)
2872                         return t2ev_cond_b(opcode, address, instruction, cp);
2873                 if (opcode & (1 << 26))
2874                         goto undef;
2875                 break;
2876         }
2877
2878         switch ((opcode >> 20) & 0x7f) {
2879         case 0x38:
2880         case 0x39:
2881                 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2882                                 (int) (opcode >> 16) & 0x0f);
2883                 return ERROR_OK;
2884         case 0x3a:
2885                 return t2ev_hint(opcode, address, instruction, cp);
2886         case 0x3b:
2887                 return t2ev_misc(opcode, address, instruction, cp);
2888         case 0x3e:
2889         case 0x3f:
2890                 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2891                                 special_name(opcode & 0xff));
2892                 return ERROR_OK;
2893         }
2894
2895 undef:
2896         return ERROR_INVALID_ARGUMENTS;
2897 }
2898
2899 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2900                 arm_instruction_t *instruction, char *cp)
2901 {
2902         char *mnemonic = NULL;
2903         int rn = (opcode >> 16) & 0xf;
2904         int rd = (opcode >> 8) & 0xf;
2905         unsigned immed = opcode & 0xff;
2906         unsigned func;
2907         bool one = false;
2908         char *suffix = "";
2909         char *suffix2 = "";
2910
2911         /* ARMv7-M: A5.3.2 Modified immediate constants */
2912         func = (opcode >> 11) & 0x0e;
2913         if (immed & 0x80)
2914                 func |= 1;
2915         if (opcode & (1 << 26))
2916                 func |= 0x10;
2917
2918         /* "Modified" immediates */
2919         switch (func >> 1) {
2920         case 0:
2921                 break;
2922         case 2:
2923                 immed <<= 8;
2924                 /* FALLTHROUGH */
2925         case 1:
2926                 immed += immed << 16;
2927                 break;
2928         case 3:
2929                 immed += immed << 8;
2930                 immed += immed << 16;
2931                 break;
2932         default:
2933                 immed |= 0x80;
2934                 immed = ror(immed, func);
2935         }
2936
2937         if (opcode & (1 << 20))
2938                 suffix = "S";
2939
2940         switch ((opcode >> 21) & 0xf) {
2941         case 0:
2942                 if (rd == 0xf) {
2943                         instruction->type = ARM_TST;
2944                         mnemonic = "TST";
2945                         one = true;
2946                         suffix = "";
2947                         rd = rn;
2948                 } else {
2949                         instruction->type = ARM_AND;
2950                         mnemonic = "AND";
2951                 }
2952                 break;
2953         case 1:
2954                 instruction->type = ARM_BIC;
2955                 mnemonic = "BIC";
2956                 break;
2957         case 2:
2958                 if (rn == 0xf) {
2959                         instruction->type = ARM_MOV;
2960                         mnemonic = "MOV";
2961                         one = true;
2962                         suffix2 = ".W";
2963                 } else {
2964                         instruction->type = ARM_ORR;
2965                         mnemonic = "ORR";
2966                 }
2967                 break;
2968         case 3:
2969                 if (rn == 0xf) {
2970                         instruction->type = ARM_MVN;
2971                         mnemonic = "MVN";
2972                         one = true;
2973                 } else {
2974                         // instruction->type = ARM_ORN;
2975                         mnemonic = "ORN";
2976                 }
2977                 break;
2978         case 4:
2979                 if (rd == 0xf) {
2980                         instruction->type = ARM_TEQ;
2981                         mnemonic = "TEQ";
2982                         one = true;
2983                         suffix = "";
2984                         rd = rn;
2985                 } else {
2986                         instruction->type = ARM_EOR;
2987                         mnemonic = "EOR";
2988                 }
2989                 break;
2990         case 8:
2991                 if (rd == 0xf) {
2992                         instruction->type = ARM_CMN;
2993                         mnemonic = "CMN";
2994                         one = true;
2995                         suffix = "";
2996                         rd = rn;
2997                 } else {
2998                         instruction->type = ARM_ADD;
2999                         mnemonic = "ADD";
3000                         suffix2 = ".W";
3001                 }
3002                 break;
3003         case 10:
3004                 instruction->type = ARM_ADC;
3005                 mnemonic = "ADC";
3006                 suffix2 = ".W";
3007                 break;
3008         case 11:
3009                 instruction->type = ARM_SBC;
3010                 mnemonic = "SBC";
3011                 break;
3012         case 13:
3013                 if (rd == 0xf) {
3014                         instruction->type = ARM_CMP;
3015                         mnemonic = "CMP";
3016                         one = true;
3017                         suffix = "";
3018                         rd = rn;
3019                 } else {
3020                         instruction->type = ARM_SUB;
3021                         mnemonic = "SUB";
3022                 }
3023                 suffix2 = ".W";
3024                 break;
3025         case 14:
3026                 instruction->type = ARM_RSB;
3027                 mnemonic = "RSB";
3028                 suffix2 = ".W";
3029                 break;
3030         default:
3031                 return ERROR_INVALID_ARGUMENTS;
3032         }
3033
3034         if (one)
3035                 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3036                                 mnemonic, suffix2 ,rd, immed, immed);
3037         else
3038                 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3039                                 mnemonic, suffix, suffix2,
3040                                 rd, rn, immed, immed);
3041
3042         return ERROR_OK;
3043 }
3044
3045 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3046                 arm_instruction_t *instruction, char *cp)
3047 {
3048         char *mnemonic = NULL;
3049         int rn = (opcode >> 16) & 0xf;
3050         int rd = (opcode >> 8) & 0xf;
3051         unsigned immed;
3052         bool add = false;
3053         bool is_signed = false;
3054
3055         immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3056         if (opcode & (1 << 26))
3057                 immed |= (1 << 11);
3058
3059         switch ((opcode >> 20) & 0x1f) {
3060         case 0:
3061                 if (rn == 0xf) {
3062                         add = true;
3063                         goto do_adr;
3064                 }
3065                 mnemonic = "ADDW";
3066                 break;
3067         case 4:
3068                 immed |= (opcode >> 4) & 0xf000;
3069                 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3070                 return ERROR_OK;
3071         case 0x0a:
3072                 if (rn == 0xf)
3073                         goto do_adr;
3074                 mnemonic = "SUBW";
3075                 break;
3076         case 0x0c:
3077                 /* move constant to top 16 bits of register */
3078                 immed |= (opcode >> 4) & 0xf000;
3079                 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
3080                 return ERROR_OK;
3081         case 0x10:
3082         case 0x12:
3083                 is_signed = true;
3084         case 0x18:
3085         case 0x1a:
3086                 /* signed/unsigned saturated add */
3087                 immed = (opcode >> 6) & 0x03;
3088                 immed |= (opcode >> 10) & 0x1c;
3089                 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3090                                 is_signed ? "S" : "U",
3091                                 rd, (int) (opcode & 0x1f) + is_signed, rn,
3092                                 (opcode & (1 << 21)) ? "ASR" : "LSL",
3093                                 immed ? immed : 32);
3094                 return ERROR_OK;
3095         case 0x14:
3096                 is_signed = true;
3097                 /* FALLTHROUGH */
3098         case 0x1c:
3099                 /* signed/unsigned bitfield extract */
3100                 immed = (opcode >> 6) & 0x03;
3101                 immed |= (opcode >> 10) & 0x1c;
3102                 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3103                                 is_signed ? "S" : "U",
3104                                 rd, rn, immed,
3105                                 (int) (opcode & 0x1f) + 1);
3106                 return ERROR_OK;
3107         case 0x16:
3108                 immed = (opcode >> 6) & 0x03;
3109                 immed |= (opcode >> 10) & 0x1c;
3110                 if (rn == 0xf)          /* bitfield clear */
3111                         sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3112                                         rd, immed,
3113                                         (int) (opcode & 0x1f) + 1 - immed);
3114                 else                    /* bitfield insert */
3115                         sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3116                                         rd, rn, immed,
3117                                         (int) (opcode & 0x1f) + 1 - immed);
3118                 return ERROR_OK;
3119         default:
3120                 return ERROR_INVALID_ARGUMENTS;
3121         }
3122
3123         sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3124                         rd, rn, immed, immed);
3125         return ERROR_OK;
3126
3127 do_adr:
3128         address = thumb_alignpc4(address);
3129         if (add)
3130                 address += immed;
3131         else
3132                 address -= immed;
3133         /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3134          * not hiding the pc-relative stuff will sometimes be useful.
3135          */
3136         sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3137         return ERROR_OK;
3138 }
3139
3140 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3141                 arm_instruction_t *instruction, char *cp)
3142 {
3143         unsigned op = (opcode >> 20) & 0xf;
3144         char *size = "";
3145         char *suffix = "";
3146         char *p1 = "";
3147         char *p2 = "]";
3148         unsigned immed;
3149         unsigned rn = (opcode >> 16) & 0x0f;
3150         unsigned rt = (opcode >> 12) & 0x0f;
3151
3152         if (rn == 0xf)
3153                 return ERROR_INVALID_ARGUMENTS;
3154
3155         if (opcode & 0x0800)
3156                 op |= 1;
3157         switch (op) {
3158         /* byte */
3159         case 0x8:
3160         case 0x9:
3161                 size = "B";
3162                 goto imm12;
3163         case 0x1:
3164                 size = "B";
3165                 goto imm8;
3166         case 0x0:
3167                 size = "B";
3168                 break;
3169         /* halfword */
3170         case 0xa:
3171         case 0xb:
3172                 size = "H";
3173                 goto imm12;
3174         case 0x3:
3175                 size = "H";
3176                 goto imm8;
3177         case 0x2:
3178                 size = "H";
3179                 break;
3180         /* word */
3181         case 0xc:
3182         case 0xd:
3183                 goto imm12;
3184         case 0x5:
3185                 goto imm8;
3186         case 0x4:
3187                 break;
3188         /* error */
3189         default:
3190                 return ERROR_INVALID_ARGUMENTS;
3191         }
3192
3193         sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3194                         size, rt, rn, (int) opcode & 0x0f,
3195                         (int) (opcode >> 4) & 0x03);
3196         return ERROR_OK;
3197
3198 imm12:
3199         immed = opcode & 0x0fff;
3200         sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3201                         size, rt, rn, immed, immed);
3202         return ERROR_OK;
3203
3204 imm8:
3205         immed = opcode & 0x00ff;
3206
3207         switch (opcode & 0x700) {
3208         case 0x600:
3209                 suffix = "T";
3210                 break;
3211         case 0x000:
3212         case 0x200:
3213                 return ERROR_INVALID_ARGUMENTS;
3214         }
3215
3216         /* two indexed modes will write back rn */
3217         if (opcode & 0x100) {
3218                 if (opcode & 0x400)     /* pre-indexed */
3219                         p2 = "]!";
3220                 else {                  /* post-indexed */
3221                         p1 = "]";
3222                         p2 = "";
3223                 }
3224         }
3225
3226         sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3227                         size, suffix, rt, rn, p1,
3228                         (opcode & 0x200) ? "" : "-",
3229                         immed, p2, immed);
3230         return ERROR_OK;
3231 }
3232
3233 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3234                 arm_instruction_t *instruction, char *cp)
3235 {
3236         int ra = (opcode >> 12) & 0xf;
3237
3238         switch (opcode & 0x007000f0) {
3239         case 0:
3240                 if (ra == 0xf)
3241                         sprintf(cp, "MUL\tr%d, r%d, r%d",
3242                                 (int) (opcode >> 8) & 0xf,
3243                                 (int) (opcode >> 16) & 0xf,
3244                                 (int) (opcode >> 0) & 0xf);
3245                 else
3246                         sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3247                                 (int) (opcode >> 8) & 0xf,
3248                                 (int) (opcode >> 16) & 0xf,
3249                                 (int) (opcode >> 0) & 0xf, ra);
3250                 break;
3251         case 0x10:
3252                 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3253                         (int) (opcode >> 8) & 0xf,
3254                         (int) (opcode >> 16) & 0xf,
3255                         (int) (opcode >> 0) & 0xf, ra);
3256                 break;
3257         default:
3258                 return ERROR_INVALID_ARGUMENTS;
3259         }
3260         return ERROR_OK;
3261 }
3262
3263 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3264                 arm_instruction_t *instruction, char *cp)
3265 {
3266         int op = (opcode >> 4) & 0xf;
3267         char *infix = "MUL";
3268
3269         op += (opcode >> 16) & 0x70;
3270         switch (op) {
3271         case 0x40:
3272         case 0x60:
3273                 infix = "MLA";
3274                 /* FALLTHROUGH */
3275         case 0:
3276         case 0x20:
3277                 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3278                                 (op & 0x20) ? 'U' : 'S',
3279                                 infix,
3280                                 (int) (opcode >> 12) & 0xf,
3281                                 (int) (opcode >> 8) & 0xf,
3282                                 (int) (opcode >> 16) & 0xf,
3283                                 (int) (opcode >> 0) & 0xf);
3284                 break;
3285         case 0x1f:
3286         case 0x3f:
3287                 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3288                                 (op & 0x20) ? 'U' : 'S',
3289                                 (int) (opcode >> 8) & 0xf,
3290                                 (int) (opcode >> 16) & 0xf,
3291                                 (int) (opcode >> 0) & 0xf);
3292                 break;
3293         default:
3294                 return ERROR_INVALID_ARGUMENTS;
3295         }
3296
3297         return ERROR_OK;
3298 }
3299
3300 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3301                 arm_instruction_t *instruction, char *cp)
3302 {
3303         int rn = (opcode >> 16) & 0xf;
3304         int op = (opcode >> 22) & 0x6;
3305         int t = (opcode >> 21) & 1;
3306         unsigned registers = opcode & 0xffff;
3307
3308         if (opcode & (1 << 20))
3309                 op |= 1;
3310
3311         switch (op) {
3312         case 2:
3313                 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3314                 break;
3315         case 3:
3316                 if (rn == 13 && t)
3317                         sprintf(cp, "POP.W\t");
3318                 else
3319                         sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3320                 break;
3321         case 4:
3322                 if (rn == 13 && t)
3323                         sprintf(cp, "PUSH.W\t");
3324                 else
3325                         sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3326                 break;
3327         case 5:
3328                 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3329                 break;
3330         default:
3331                 return ERROR_INVALID_ARGUMENTS;
3332         }
3333
3334         cp = strchr(cp, 0);
3335         *cp++ = '{';
3336         for (t = 0; registers; t++, registers >>= 1) {
3337                 if ((registers & 1) == 0)
3338                         continue;
3339                 registers &= ~1;
3340                 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3341                 cp = strchr(cp, 0);
3342         }
3343         *cp++ = '}';
3344         *cp++ = 0;
3345
3346         return ERROR_OK;
3347 }
3348
3349 /* load/store dual or exclusive, table branch */
3350 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3351                 arm_instruction_t *instruction, char *cp)
3352 {
3353         unsigned op1op2 = (opcode >> 20) & 0x3;
3354         unsigned op3 = (opcode >> 4) & 0xf;
3355         char *mnemonic;
3356         unsigned rn = (opcode >> 16) & 0xf;
3357         unsigned rt = (opcode >> 12) & 0xf;
3358         unsigned rd = (opcode >> 8) & 0xf;
3359         unsigned imm = opcode & 0xff;
3360         char *p1 = "";
3361         char *p2 = "]";
3362
3363         op1op2 |= (opcode >> 21) & 0xc;
3364         switch (op1op2) {
3365         case 0:
3366                 mnemonic = "STREX";
3367                 goto strex;
3368         case 1:
3369                 mnemonic = "LDREX";
3370                 goto ldrex;
3371         case 2:
3372         case 6:
3373         case 8:
3374         case 10:
3375         case 12:
3376         case 14:
3377                 mnemonic = "STRD";
3378                 goto immediate;
3379         case 3:
3380         case 7:
3381         case 9:
3382         case 11:
3383         case 13:
3384         case 15:
3385                 mnemonic = "LDRD";
3386                 if (rn == 15)
3387                         goto literal;
3388                 else
3389                         goto immediate;
3390         case 4:
3391                 switch (op3) {
3392                 case 4:
3393                         mnemonic = "STREXB";
3394                         break;
3395                 case 5:
3396                         mnemonic = "STREXH";
3397                         break;
3398                 default:
3399                         return ERROR_INVALID_ARGUMENTS;
3400                 }
3401                 rd = opcode & 0xf;
3402                 imm = 0;
3403                 goto strex;
3404         case 5:
3405                 switch (op3) {
3406                 case 0:
3407                         sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3408                         return ERROR_OK;
3409                 case 1:
3410                         sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3411                         return ERROR_OK;
3412                 case 4:
3413                         mnemonic = "LDREXB";
3414                         break;
3415                 case 5:
3416                         mnemonic = "LDREXH";
3417                         break;
3418                 default:
3419                         return ERROR_INVALID_ARGUMENTS;
3420                 }
3421                 imm = 0;
3422                 goto ldrex;
3423         }
3424         return ERROR_INVALID_ARGUMENTS;
3425
3426 strex:
3427         imm <<= 2;
3428         if (imm)
3429                 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3430                                 mnemonic, rd, rt, rn, imm, imm);
3431         else
3432                 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3433                                 mnemonic, rd, rt, rn);
3434         return ERROR_OK;
3435
3436 ldrex:
3437         imm <<= 2;
3438         if (imm)
3439                 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3440                                 mnemonic, rt, rn, imm, imm);
3441         else
3442                 sprintf(cp, "%s\tr%u, [r%u]",
3443                                 mnemonic, rt, rn);
3444         return ERROR_OK;
3445
3446 immediate:
3447         /* two indexed modes will write back rn */
3448         if (opcode & (1 << 21)) {
3449                 if (opcode & (1 << 24)) /* pre-indexed */
3450                         p2 = "]!";
3451                 else {                  /* post-indexed */
3452                         p1 = "]";
3453                         p2 = "";
3454                 }
3455         }
3456
3457         imm <<= 2;
3458         sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3459                         mnemonic, rt, rd, rn, p1,
3460                         (opcode & (1 << 23)) ? "" : "-",
3461                         imm, p2, imm);
3462         return ERROR_OK;
3463
3464 literal:
3465         address = thumb_alignpc4(address);
3466         imm <<= 2;
3467         if (opcode & (1 << 23))
3468                 address += imm;
3469         else
3470                 address -= imm;
3471         sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3472                         mnemonic, rt, rd, address);
3473         return ERROR_OK;
3474 }
3475
3476 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3477                 arm_instruction_t *instruction, char *cp)
3478 {
3479         int op = (opcode >> 21) & 0xf;
3480         int rd = (opcode >> 8) & 0xf;
3481         int rn = (opcode >> 16) & 0xf;
3482         int type = (opcode >> 4) & 0x3;
3483         int immed = (opcode >> 6) & 0x3;
3484         char *mnemonic;
3485         char *suffix = "";
3486
3487         immed |= (opcode >> 10) & 0x1c;
3488         if (opcode & (1 << 20))
3489                 suffix = "S";
3490
3491         switch (op) {
3492         case 0:
3493                 if (rd == 0xf) {
3494                         if (!(opcode & (1 << 20)))
3495                                 return ERROR_INVALID_ARGUMENTS;
3496                         instruction->type = ARM_TST;
3497                         mnemonic = "TST";
3498                         suffix = "";
3499                         goto two;
3500                 }
3501                 instruction->type = ARM_AND;
3502                 mnemonic = "AND";
3503                 break;
3504         case 1:
3505                 instruction->type = ARM_BIC;
3506                 mnemonic = "BIC";
3507                 break;
3508         case 2:
3509                 if (rn == 0xf) {
3510                         instruction->type = ARM_MOV;
3511                         switch (type) {
3512                         case 0:
3513                                 if (immed == 0) {
3514                                         sprintf(cp, "MOV%s.W\tr%d, r%d",
3515                                                 suffix, rd,
3516                                                 (int) (opcode & 0xf));
3517                                         return ERROR_OK;
3518                                 }
3519                                 mnemonic = "LSL";
3520                                 break;
3521                         case 1:
3522                                 mnemonic = "LSR";
3523                                 break;
3524                         case 2:
3525                                 mnemonic = "ASR";
3526                                 break;
3527                         default:
3528                                 if (immed == 0) {
3529                                         sprintf(cp, "RRX%s\tr%d, r%d",
3530                                                 suffix, rd,
3531                                                 (int) (opcode & 0xf));
3532                                         return ERROR_OK;
3533                                 }
3534                                 mnemonic = "ROR";
3535                                 break;
3536                         }
3537                         goto immediate;
3538                 } else {
3539                         instruction->type = ARM_ORR;
3540                         mnemonic = "ORR";
3541                 }
3542                 break;
3543         case 3:
3544                 if (rn == 0xf) {
3545                         instruction->type = ARM_MVN;
3546                         mnemonic = "MVN";
3547                         rn = rd;
3548                         goto two;
3549                 } else {
3550                         // instruction->type = ARM_ORN;
3551                         mnemonic = "ORN";
3552                 }
3553                 break;
3554         case 4:
3555                 if (rd == 0xf) {
3556                         if (!(opcode & (1 << 20)))
3557                                 return ERROR_INVALID_ARGUMENTS;
3558                         instruction->type = ARM_TEQ;
3559                         mnemonic = "TEQ";
3560                         suffix = "";
3561                         goto two;
3562                 }
3563                 instruction->type = ARM_EOR;
3564                 mnemonic = "EOR";
3565                 break;
3566         case 8:
3567                 if (rd == 0xf) {
3568                         if (!(opcode & (1 << 20)))
3569                                 return ERROR_INVALID_ARGUMENTS;
3570                         instruction->type = ARM_CMN;
3571                         mnemonic = "CMN";
3572                         suffix = "";
3573                         goto two;
3574                 }
3575                 instruction->type = ARM_ADD;
3576                 mnemonic = "ADD";
3577                 break;
3578         case 0xa:
3579                 instruction->type = ARM_ADC;
3580                 mnemonic = "ADC";
3581                 break;
3582         case 0xb:
3583                 instruction->type = ARM_SBC;
3584                 mnemonic = "SBC";
3585                 break;
3586         case 0xd:
3587                 if (rd == 0xf) {
3588                         if (!(opcode & (1 << 21)))
3589                                 return ERROR_INVALID_ARGUMENTS;
3590                         instruction->type = ARM_CMP;
3591                         mnemonic = "CMP";
3592                         suffix = "";
3593                         goto two;
3594                 }
3595                 instruction->type = ARM_SUB;
3596                 mnemonic = "SUB";
3597                 break;
3598         case 0xe:
3599                 instruction->type = ARM_RSB;
3600                 mnemonic = "RSB";
3601                 break;
3602         default:
3603                 return ERROR_INVALID_ARGUMENTS;
3604         }
3605
3606         sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3607                 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3608
3609 shift:
3610         cp = strchr(cp, 0);
3611
3612         switch (type) {
3613         case 0:
3614                 if (immed == 0)
3615                         return ERROR_OK;
3616                 suffix = "LSL";
3617                 break;
3618         case 1:
3619                 suffix = "LSR";
3620                 if (immed == 32)
3621                         immed = 0;
3622                 break;
3623         case 2:
3624                 suffix = "ASR";
3625                 if (immed == 32)
3626                         immed = 0;
3627                 break;
3628         case 3:
3629                 if (immed == 0) {
3630                         strcpy(cp, ", RRX");
3631                         return ERROR_OK;
3632                 }
3633                 suffix = "ROR";
3634                 break;
3635         }
3636         sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3637         return ERROR_OK;
3638
3639 two:
3640         sprintf(cp, "%s%s.W\tr%d, r%d",
3641                 mnemonic, suffix, rn, (int) (opcode & 0xf));
3642         goto shift;
3643
3644 immediate:
3645         sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3646                 mnemonic, suffix, rd,
3647                 (int) (opcode & 0xf), immed ? immed : 32);
3648         return ERROR_OK;
3649 }
3650
3651 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3652                 arm_instruction_t *instruction, char *cp)
3653 {
3654         char *mnemonic;
3655         char * suffix = "";
3656
3657         if (((opcode >> 4) & 0xf) == 0) {
3658                 switch ((opcode >> 21) & 0x7) {
3659                 case 0:
3660                         mnemonic = "LSL";
3661                         break;
3662                 case 1:
3663                         mnemonic = "LSR";
3664                         break;
3665                 case 2:
3666                         mnemonic = "ASR";
3667                         break;
3668                 case 3:
3669                         mnemonic = "ROR";
3670                         break;
3671                 default:
3672                         return ERROR_INVALID_ARGUMENTS;
3673                 }
3674
3675                 instruction->type = ARM_MOV;
3676                 if (opcode & (1 << 20))
3677                         suffix = "S";
3678                 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3679                                 mnemonic, suffix,
3680                                 (int) (opcode >> 8) & 0xf,
3681                                 (int) (opcode >> 16) & 0xf,
3682                                 (int) (opcode >> 0) & 0xf);
3683
3684         } else if (opcode & (1 << 7)) {
3685                 switch ((opcode >> 20) & 0xf) {
3686                 case 0:
3687                 case 1:
3688                 case 4:
3689                 case 5:
3690                         switch ((opcode >> 4) & 0x3) {
3691                         case 1:
3692                                 suffix = ", ROR #8";
3693                                 break;
3694                         case 2:
3695                                 suffix = ", ROR #16";
3696                                 break;
3697                         case 3:
3698                                 suffix = ", ROR #24";
3699                                 break;
3700                         }
3701                         sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3702                                         (opcode & (1 << 24)) ? 'U' : 'S',
3703                                         (opcode & (1 << 26)) ? 'B' : 'H',
3704                                         (int) (opcode >> 8) & 0xf,
3705                                         (int) (opcode >> 0) & 0xf,
3706                                         suffix);
3707                         break;
3708                 case 8:
3709                 case 9:
3710                 case 0xa:
3711                 case 0xb:
3712                         if (opcode & (1 << 6))
3713                                 return ERROR_INVALID_ARGUMENTS;
3714                         if (((opcode >> 12) & 0xf) != 0xf)
3715                                 return ERROR_INVALID_ARGUMENTS;
3716                         if (!(opcode & (1 << 20)))
3717                                 return ERROR_INVALID_ARGUMENTS;
3718
3719                         switch (((opcode >> 19) & 0x04)
3720                                 | ((opcode >> 4) & 0x3)) {
3721                         case 0:
3722                                 mnemonic = "REV.W";
3723                                 break;
3724                         case 1:
3725                                 mnemonic = "REV16.W";
3726                                 break;
3727                         case 2:
3728                                 mnemonic = "RBIT";
3729                                 break;
3730                         case 3:
3731                                 mnemonic = "REVSH.W";
3732                                 break;
3733                         case 4:
3734                                 mnemonic = "CLZ";
3735                                 break;
3736                         default:
3737                                 return ERROR_INVALID_ARGUMENTS;
3738                         }
3739                         sprintf(cp, "%s\tr%d, r%d",
3740                                         mnemonic,
3741                                         (int) (opcode >> 8) & 0xf,
3742                                         (int) (opcode >> 0) & 0xf);
3743                         break;
3744                 default:
3745                         return ERROR_INVALID_ARGUMENTS;
3746                 }
3747         }
3748
3749         return ERROR_OK;
3750 }
3751
3752 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3753                 arm_instruction_t *instruction, char *cp)
3754 {
3755         int rn = (opcode >> 16) & 0xf;
3756         int immed;
3757
3758         instruction->type = ARM_LDR;
3759
3760         if (rn == 0xf) {
3761                 immed = opcode & 0x0fff;
3762                 if ((opcode & (1 << 23)) == 0)
3763                         immed = -immed;
3764                 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3765                                 (int) (opcode >> 12) & 0xf,
3766                                 thumb_alignpc4(address) + immed);
3767                 return ERROR_OK;
3768         }
3769
3770         if (opcode & (1 << 23)) {
3771                 immed = opcode & 0x0fff;
3772                 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3773                                 (int) (opcode >> 12) & 0xf,
3774                                 rn, immed, immed);
3775                 return ERROR_OK;
3776         }
3777
3778         if (!(opcode & (0x3f << 6))) {
3779                 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3780                                 (int) (opcode >> 12) & 0xf,
3781                                 rn,
3782                                 (int) (opcode >> 0) & 0xf,
3783                                 (int) (opcode >> 4) & 0x3);
3784                 return ERROR_OK;
3785         }
3786
3787
3788         if (((opcode >> 8) & 0xf) == 0xe) {
3789                 immed = opcode & 0x00ff;
3790
3791                 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3792                                 (int) (opcode >> 12) & 0xf,
3793                                 rn, immed, immed);
3794                 return ERROR_OK;
3795         }
3796
3797         if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3798                 char *p1 = "]", *p2 = "";
3799
3800                 if (!(opcode & 0x0500))
3801                         return ERROR_INVALID_ARGUMENTS;
3802
3803                 immed = opcode & 0x00ff;
3804
3805                 /* two indexed modes will write back rn */
3806                 if (opcode & 0x100) {
3807                         if (opcode & 0x400)     /* pre-indexed */
3808                                 p2 = "]!";
3809                         else {                  /* post-indexed */
3810                                 p1 = "]";
3811                                 p2 = "";
3812                         }
3813                 }
3814
3815                 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3816                                 (int) (opcode >> 12) & 0xf,
3817                                 rn, p1,
3818                                 (opcode & 0x200) ? "" : "-",
3819                                 immed, p2, immed);
3820                 return ERROR_OK;
3821         }
3822
3823         return ERROR_INVALID_ARGUMENTS;
3824 }
3825
3826 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3827                 arm_instruction_t *instruction, char *cp)
3828 {
3829         int rn = (opcode >> 16) & 0xf;
3830         int rt = (opcode >> 12) & 0xf;
3831         int op2 = (opcode >> 6) & 0x3f;
3832         unsigned immed;
3833         char *p1 = "", *p2 = "]";
3834         char *mnemonic;
3835
3836         switch ((opcode >> 23) & 0x3) {
3837         case 0:
3838                 if ((rn & rt) == 0xf) {
3839 pld_literal:
3840                         immed = opcode & 0xfff;
3841                         address = thumb_alignpc4(address);
3842                         if (opcode & (1 << 23))
3843                                 address += immed;
3844                         else
3845                                 address -= immed;
3846                         sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
3847                                         rt, address);
3848                         return ERROR_OK;
3849                 }
3850                 if (rn == 0x0f && rt != 0x0f) {
3851 ldrb_literal:
3852                         immed = opcode & 0xfff;
3853                         address = thumb_alignpc4(address);
3854                         if (opcode & (1 << 23))
3855                                 address += immed;
3856                         else
3857                                 address -= immed;
3858                         sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3859                                         rt, address);
3860                         return ERROR_OK;
3861                 }
3862                 if (rn == 0x0f)
3863                         break;
3864                 if ((op2 & 0x3c) == 0x38) {
3865                         immed = opcode & 0xff;
3866                         sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3867                                         rt, rn, immed, immed);
3868                         return ERROR_OK;
3869                 }
3870                 if ((op2 & 0x3c) == 0x30) {
3871                         if (rt == 0x0f) {
3872                                 immed = opcode & 0xff;
3873                                 immed = -immed;
3874 preload_immediate:
3875                                 p1 = (opcode & (1 << 21)) ? "W" : "";
3876                                 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3877                                                 p1, rn, immed, immed);
3878                                 return ERROR_OK;
3879                         }
3880                         mnemonic = "LDRB";
3881 ldrxb_immediate_t3:
3882                         immed = opcode & 0xff;
3883                         if (!(opcode & 0x200))
3884                                 immed = -immed;
3885
3886                         /* two indexed modes will write back rn */
3887                         if (opcode & 0x100) {
3888                                 if (opcode & 0x400)     /* pre-indexed */
3889                                         p2 = "]!";
3890                                 else {                  /* post-indexed */
3891                                         p1 = "]";
3892                                         p2 = "";
3893                                 }
3894                         }
3895 ldrxb_immediate_t2:
3896                         sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3897                                         mnemonic, rt, rn, p1,
3898                                         immed, p2, immed);
3899                         return ERROR_OK;
3900                 }
3901                 if ((op2 & 0x24) == 0x24) {
3902                         mnemonic = "LDRB";
3903                         goto ldrxb_immediate_t3;
3904                 }
3905                 if (op2 == 0) {
3906                         int rm = opcode & 0xf;
3907
3908                         if (rt == 0x0f)
3909                                 sprintf(cp, "PLD\t");
3910                         else
3911                                 sprintf(cp, "LDRB.W\tr%d, ", rt);
3912                         immed = (opcode >> 4) & 0x3;
3913                         cp = strchr(cp, 0);
3914                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3915                         return ERROR_OK;
3916                 }
3917                 break;
3918         case 1:
3919                 if ((rn & rt) == 0xf)
3920                         goto pld_literal;
3921                 if (rt == 0xf) {
3922                         immed = opcode & 0xfff;
3923                         goto preload_immediate;
3924                 }
3925                 if (rn == 0x0f)
3926                         goto ldrb_literal;
3927                 mnemonic = "LDRB.W";
3928                 immed = opcode & 0xfff;
3929                 goto ldrxb_immediate_t2;
3930         case 2:
3931                 if ((rn & rt) == 0xf) {
3932                         immed = opcode & 0xfff;
3933                         address = thumb_alignpc4(address);
3934                         if (opcode & (1 << 23))
3935                                 address += immed;
3936                         else
3937                                 address -= immed;
3938                         sprintf(cp, "PLI\t%#8.8" PRIx32, address);
3939                         return ERROR_OK;
3940                 }
3941                 if (rn == 0xf && rt != 0xf) {
3942 ldrsb_literal:
3943                         immed = opcode & 0xfff;
3944                         address = thumb_alignpc4(address);
3945                         if (opcode & (1 << 23))
3946                                 address += immed;
3947                         else
3948                                 address -= immed;
3949                         sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
3950                         return ERROR_OK;
3951                 }
3952                 if (rn == 0xf)
3953                         break;
3954                 if ((op2 & 0x3c) == 0x38) {
3955                         immed = opcode & 0xff;
3956                         sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
3957                                         rt, rn, immed, immed);
3958                         return ERROR_OK;
3959                 }
3960                 if ((op2 & 0x3c) == 0x30) {
3961                         if (rt == 0xf) {
3962                                 immed = opcode & 0xff;
3963                                 immed = -immed; // pli
3964                                 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
3965                                                 rn, immed, -immed);
3966                                 return ERROR_OK;
3967                         }
3968                         mnemonic = "LDRSB";
3969                         goto ldrxb_immediate_t3;
3970                 }
3971                 if ((op2 & 0x24) == 0x24) {
3972                         mnemonic = "LDRSB";
3973                         goto ldrxb_immediate_t3;
3974                 }
3975                 if (op2 == 0) {
3976                         int rm = opcode & 0xf;
3977
3978                         if (rt == 0x0f)
3979                                 sprintf(cp, "PLI\t");
3980                         else
3981                                 sprintf(cp, "LDRSB.W\tr%d, ", rt);
3982                         immed = (opcode >> 4) & 0x3;
3983                         cp = strchr(cp, 0);
3984                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3985                         return ERROR_OK;
3986                 }
3987                 break;
3988         case 3:
3989                 if (rt == 0xf) {
3990                         immed = opcode & 0xfff;
3991                         sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
3992                                         rn, immed, immed);
3993                         return ERROR_OK;
3994                 }
3995                 if (rn == 0xf)
3996                         goto ldrsb_literal;
3997                 immed = opcode & 0xfff;
3998                 mnemonic = "LDRSB";
3999                 goto ldrxb_immediate_t2;
4000         }
4001
4002         return ERROR_INVALID_ARGUMENTS;
4003 }
4004
4005 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4006                 arm_instruction_t *instruction, char *cp)
4007 {
4008         int rn = (opcode >> 16) & 0xf;
4009         int rt = (opcode >> 12) & 0xf;
4010         int op2 = (opcode >> 6) & 0x3f;
4011         char *sign = "";
4012         unsigned immed;
4013
4014         if (rt == 0xf) {
4015                 sprintf(cp, "HINT (UNALLOCATED)");
4016                 return ERROR_OK;
4017         }
4018
4019         if (opcode & (1 << 24))
4020                 sign = "S";
4021
4022         if ((opcode & (1 << 23)) == 0) {
4023                 if (rn == 0xf) {
4024 ldrh_literal:
4025                         immed = opcode & 0xfff;
4026                         address = thumb_alignpc4(address);
4027                         if (opcode & (1 << 23))
4028                                 address += immed;
4029                         else
4030                                 address -= immed;
4031                         sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4032                                         sign, rt, address);
4033                         return ERROR_OK;
4034                 }
4035                 if (op2 == 0) {
4036                         int rm = opcode & 0xf;
4037
4038                         immed = (opcode >> 4) & 0x3;
4039                         sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4040                                         sign, rt, rn, rm, immed);
4041                         return ERROR_OK;
4042                 }
4043                 if ((op2 & 0x3c) == 0x38) {
4044                         immed = opcode & 0xff;
4045                         sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4046                                         sign, rt, rn, immed, immed);
4047                         return ERROR_OK;
4048                 }
4049                 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4050                         char *p1 = "", *p2 = "]";
4051
4052                         immed = opcode & 0xff;
4053                         if (!(opcode & 0x200))
4054                                 immed = -immed;
4055
4056                         /* two indexed modes will write back rn */
4057                         if (opcode & 0x100) {
4058                                 if (opcode & 0x400)     /* pre-indexed */
4059                                         p2 = "]!";
4060                                 else {                  /* post-indexed */
4061                                         p1 = "]";
4062                                         p2 = "";
4063                                 }
4064                         }
4065                         sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4066                                         sign, rt, rn, p1, immed, p2, immed);
4067                         return ERROR_OK;
4068                 }
4069         } else {
4070                 if (rn == 0xf)
4071                         goto ldrh_literal;
4072
4073                 immed = opcode & 0xfff;
4074                 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4075                                 sign, *sign ? "" : ".W",
4076                                 rt, rn, immed, immed);
4077                 return ERROR_OK;
4078         }
4079
4080         return ERROR_INVALID_ARGUMENTS;
4081 }
4082
4083 /*
4084  * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4085  * always set.  That means eventual arm_simulate_step() support for Thumb2
4086  * will need work in this area.
4087  */
4088 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
4089 {
4090         int retval;
4091         uint16_t op;
4092         uint32_t opcode;
4093         char *cp;
4094
4095         /* clear low bit ... it's set on function pointers */
4096         address &= ~1;
4097
4098         /* clear fields, to avoid confusion */
4099         memset(instruction, 0, sizeof(arm_instruction_t));
4100
4101         /* read first halfword, see if this is the only one */
4102         retval = target_read_u16(target, address, &op);
4103         if (retval != ERROR_OK)
4104                 return retval;
4105
4106         switch (op & 0xf800) {
4107         case 0xf800:
4108         case 0xf000:
4109         case 0xe800:
4110                 /* 32-bit instructions */
4111                 instruction->instruction_size = 4;
4112                 opcode = op << 16;
4113                 retval = target_read_u16(target, address + 2, &op);
4114                 if (retval != ERROR_OK)
4115                         return retval;
4116                 opcode |= op;
4117                 instruction->opcode = opcode;
4118                 break;
4119         default:
4120                 /* 16-bit:  Thumb1 + IT + CBZ/CBNZ + ... */
4121                 return thumb_evaluate_opcode(op, address, instruction);
4122         }
4123
4124         snprintf(instruction->text, 128,
4125                         "0x%8.8" PRIx32 "  0x%8.8" PRIx32 "\t",
4126                         address, opcode);
4127         cp = strchr(instruction->text, 0);
4128         retval = ERROR_FAIL;
4129
4130         /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4131         if ((opcode & 0x1a008000) == 0x10000000)
4132                 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4133
4134         /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4135         else if ((opcode & 0x1a008000) == 0x12000000)
4136                 retval = t2ev_data_immed(opcode, address, instruction, cp);
4137
4138         /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4139         else if ((opcode & 0x18008000) == 0x10008000)
4140                 retval = t2ev_b_misc(opcode, address, instruction, cp);
4141
4142         /* ARMv7-M: A5.3.5 Load/store multiple */
4143         else if ((opcode & 0x1e400000) == 0x08000000)
4144                 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4145
4146         /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4147         else if ((opcode & 0x1e400000) == 0x08400000)
4148                 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4149
4150         /* ARMv7-M: A5.3.7 Load word */
4151         else if ((opcode & 0x1f700000) == 0x18500000)
4152                 retval = t2ev_load_word(opcode, address, instruction, cp);
4153
4154         /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4155         else if ((opcode & 0x1e700000) == 0x18300000)
4156                 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4157
4158         /* ARMv7-M: A5.3.9 Load byte, memory hints */
4159         else if ((opcode & 0x1e700000) == 0x18100000)
4160                 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4161
4162         /* ARMv7-M: A5.3.10 Store single data item */
4163         else if ((opcode & 0x1f100000) == 0x18000000)
4164                 retval = t2ev_store_single(opcode, address, instruction, cp);
4165
4166         /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4167         else if ((opcode & 0x1e000000) == 0x0a000000)
4168                 retval = t2ev_data_shift(opcode, address, instruction, cp);
4169
4170         /* ARMv7-M: A5.3.12 Data processing (register)
4171          * and      A5.3.13 Miscellaneous operations
4172          */
4173         else if ((opcode & 0x1f000000) == 0x1a000000)
4174                 retval = t2ev_data_reg(opcode, address, instruction, cp);
4175
4176         /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4177         else if ((opcode & 0x1f800000) == 0x1b000000)
4178                 retval = t2ev_mul32(opcode, address, instruction, cp);
4179
4180         /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4181         else if ((opcode & 0x1f800000) == 0x1b800000)
4182                 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4183
4184         if (retval == ERROR_OK)
4185                 return retval;
4186
4187         /*
4188          * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4189          * instructions; not yet handled here.
4190          */
4191
4192         if (retval == ERROR_INVALID_ARGUMENTS) {
4193                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4194                 strcpy(cp, "UNDEFINED OPCODE");
4195                 return ERROR_OK;
4196         }
4197
4198         LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4199                         opcode);
4200
4201         strcpy(cp, "(32-bit Thumb2 ...)");
4202         return ERROR_OK;
4203 }
4204
4205 int arm_access_size(arm_instruction_t *instruction)
4206 {
4207         if ((instruction->type == ARM_LDRB)
4208                 || (instruction->type == ARM_LDRBT)
4209                 || (instruction->type == ARM_LDRSB)
4210                 || (instruction->type == ARM_STRB)
4211                 || (instruction->type == ARM_STRBT))
4212         {
4213                 return 1;
4214         }
4215         else if ((instruction->type == ARM_LDRH)
4216                 || (instruction->type == ARM_LDRSH)
4217                 || (instruction->type == ARM_STRH))
4218         {
4219                 return 2;
4220         }
4221         else if ((instruction->type == ARM_LDR)
4222                 || (instruction->type == ARM_LDRT)
4223                 || (instruction->type == ARM_STR)
4224                 || (instruction->type == ARM_STRT))
4225         {
4226                 return 4;
4227         }
4228         else if ((instruction->type == ARM_LDRD)
4229                 || (instruction->type == ARM_STRD))
4230         {
4231                 return 8;
4232         }
4233         else
4234         {
4235                 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
4236                 return 0;
4237         }
4238 }