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