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