David Brownell <david-b@pacbell.net> More testcase work:
[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 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3011                 arm_instruction_t *instruction, char *cp)
3012 {
3013         int op = (opcode >> 21) & 0xf;
3014         int rd = (opcode >> 8) & 0xf;
3015         int rn = (opcode >> 16) & 0xf;
3016         int type = (opcode >> 4) & 0x3;
3017         int immed = (opcode >> 6) & 0x3;
3018         char *mnemonic;
3019         char *suffix = "";
3020
3021         immed |= (opcode >> 10) & 0x1c;
3022         if (opcode & (1 << 20))
3023                 suffix = "S";
3024
3025         switch (op) {
3026         case 0:
3027                 if (rd == 0xf) {
3028                         if (!(opcode & (1 << 20)))
3029                                 return ERROR_INVALID_ARGUMENTS;
3030                         instruction->type = ARM_TST;
3031                         mnemonic = "TST";
3032                         suffix = "";
3033                         goto two;
3034                 }
3035                 instruction->type = ARM_AND;
3036                 mnemonic = "AND";
3037                 break;
3038         case 1:
3039                 instruction->type = ARM_BIC;
3040                 mnemonic = "BIC";
3041                 break;
3042         case 2:
3043                 if (rn == 0xf) {
3044                         instruction->type = ARM_MOV;
3045                         switch (type) {
3046                         case 0:
3047                                 if (immed == 0) {
3048                                         sprintf(cp, "MOV%s.W\tr%d, r%d",
3049                                                 suffix, rd,
3050                                                 (int) (opcode & 0xf));
3051                                         return ERROR_OK;
3052                                 }
3053                                 mnemonic = "LSL";
3054                                 break;
3055                         case 1:
3056                                 mnemonic = "LSR";
3057                                 break;
3058                         case 2:
3059                                 mnemonic = "ASR";
3060                                 break;
3061                         default:
3062                                 if (immed == 0) {
3063                                         sprintf(cp, "RRX%s\tr%d, r%d",
3064                                                 suffix, rd,
3065                                                 (int) (opcode & 0xf));
3066                                         return ERROR_OK;
3067                                 }
3068                                 mnemonic = "ROR";
3069                                 break;
3070                         }
3071                         goto immediate;
3072                 } else {
3073                         instruction->type = ARM_ORR;
3074                         mnemonic = "ORR";
3075                 }
3076                 break;
3077         case 3:
3078                 if (rn == 0xf) {
3079                         instruction->type = ARM_MVN;
3080                         mnemonic = "MVN";
3081                         rn = rd;
3082                         goto two;
3083                 } else {
3084                         // instruction->type = ARM_ORN;
3085                         mnemonic = "ORN";
3086                 }
3087                 break;
3088         case 4:
3089                 if (rd == 0xf) {
3090                         if (!(opcode & (1 << 20)))
3091                                 return ERROR_INVALID_ARGUMENTS;
3092                         instruction->type = ARM_TEQ;
3093                         mnemonic = "TEQ";
3094                         suffix = "";
3095                         goto two;
3096                 }
3097                 instruction->type = ARM_EOR;
3098                 mnemonic = "EOR";
3099                 break;
3100         case 8:
3101                 if (rd == 0xf) {
3102                         if (!(opcode & (1 << 20)))
3103                                 return ERROR_INVALID_ARGUMENTS;
3104                         instruction->type = ARM_CMN;
3105                         mnemonic = "CMN";
3106                         suffix = "";
3107                         goto two;
3108                 }
3109                 instruction->type = ARM_ADD;
3110                 mnemonic = "ADD";
3111                 break;
3112         case 0xa:
3113                 instruction->type = ARM_ADC;
3114                 mnemonic = "ADC";
3115                 break;
3116         case 0xb:
3117                 instruction->type = ARM_SBC;
3118                 mnemonic = "SBC";
3119                 break;
3120         case 0xd:
3121                 if (rd == 0xf) {
3122                         if (!(opcode & (1 << 21)))
3123                                 return ERROR_INVALID_ARGUMENTS;
3124                         instruction->type = ARM_CMP;
3125                         mnemonic = "CMP";
3126                         suffix = "";
3127                         goto two;
3128                 }
3129                 instruction->type = ARM_SUB;
3130                 mnemonic = "SUB";
3131                 break;
3132         case 0xe:
3133                 instruction->type = ARM_RSB;
3134                 mnemonic = "RSB";
3135                 break;
3136         default:
3137                 return ERROR_INVALID_ARGUMENTS;
3138         }
3139
3140         sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3141                 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3142
3143 shift:
3144         cp = strchr(cp, 0);
3145
3146         switch (type) {
3147         case 0:
3148                 if (immed == 0)
3149                         return ERROR_OK;
3150                 suffix = "LSL";
3151                 break;
3152         case 1:
3153                 suffix = "LSR";
3154                 if (immed == 32)
3155                         immed = 0;
3156                 break;
3157         case 2:
3158                 suffix = "ASR";
3159                 if (immed == 32)
3160                         immed = 0;
3161                 break;
3162         case 3:
3163                 if (immed == 0) {
3164                         strcpy(cp, ", RRX");
3165                         return ERROR_OK;
3166                 }
3167                 suffix = "ROR";
3168                 break;
3169         }
3170         sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3171         return ERROR_OK;
3172
3173 two:
3174         sprintf(cp, "%s%s.W\tr%d, r%d",
3175                 mnemonic, suffix, rn, (int) (opcode & 0xf));
3176         goto shift;
3177
3178 immediate:
3179         sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3180                 mnemonic, suffix, rd,
3181                 (int) (opcode & 0xf), immed ? immed : 32);
3182         return ERROR_OK;
3183 }
3184
3185 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3186                 arm_instruction_t *instruction, char *cp)
3187 {
3188         char *mnemonic;
3189         char * suffix = "";
3190
3191         if (((opcode >> 4) & 0xf) == 0) {
3192                 switch ((opcode >> 21) & 0x7) {
3193                 case 0:
3194                         mnemonic = "LSL";
3195                         break;
3196                 case 1:
3197                         mnemonic = "LSR";
3198                         break;
3199                 case 2:
3200                         mnemonic = "ASR";
3201                         break;
3202                 case 3:
3203                         mnemonic = "ROR";
3204                         break;
3205                 default:
3206                         return ERROR_INVALID_ARGUMENTS;
3207                 }
3208
3209                 instruction->type = ARM_MOV;
3210                 if (opcode & (1 << 20))
3211                         suffix = "S";
3212                 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3213                                 mnemonic, suffix,
3214                                 (int) (opcode >> 8) & 0xf,
3215                                 (int) (opcode >> 16) & 0xf,
3216                                 (int) (opcode >> 0) & 0xf);
3217
3218         } else if (opcode & (1 << 7)) {
3219                 switch ((opcode >> 20) & 0xf) {
3220                 case 0:
3221                 case 1:
3222                 case 4:
3223                 case 5:
3224                         switch ((opcode >> 4) & 0x3) {
3225                         case 1:
3226                                 suffix = ", ROR #8";
3227                                 break;
3228                         case 2:
3229                                 suffix = ", ROR #16";
3230                                 break;
3231                         case 3:
3232                                 suffix = ", ROR #24";
3233                                 break;
3234                         }
3235                         sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3236                                         (opcode & (1 << 24)) ? 'U' : 'S',
3237                                         (opcode & (1 << 26)) ? 'B' : 'H',
3238                                         (int) (opcode >> 8) & 0xf,
3239                                         (int) (opcode >> 0) & 0xf,
3240                                         suffix);
3241                         break;
3242                 case 8:
3243                 case 9:
3244                 case 0xa:
3245                 case 0xb:
3246                         if (opcode & (1 << 6))
3247                                 return ERROR_INVALID_ARGUMENTS;
3248                         if (((opcode >> 12) & 0xf) != 0xf)
3249                                 return ERROR_INVALID_ARGUMENTS;
3250                         if (!(opcode & (1 << 20)))
3251                                 return ERROR_INVALID_ARGUMENTS;
3252
3253                         switch (((opcode >> 19) & 0x04)
3254                                 | ((opcode >> 4) & 0x3)) {
3255                         case 0:
3256                                 mnemonic = "REV.W";
3257                                 break;
3258                         case 1:
3259                                 mnemonic = "REV16.W";
3260                                 break;
3261                         case 2:
3262                                 mnemonic = "RBIT";
3263                                 break;
3264                         case 3:
3265                                 mnemonic = "REVSH.W";
3266                                 break;
3267                         case 4:
3268                                 mnemonic = "CLZ";
3269                                 break;
3270                         default:
3271                                 return ERROR_INVALID_ARGUMENTS;
3272                         }
3273                         sprintf(cp, "%s\tr%d, r%d",
3274                                         mnemonic,
3275                                         (int) (opcode >> 8) & 0xf,
3276                                         (int) (opcode >> 0) & 0xf);
3277                         break;
3278                 default:
3279                         return ERROR_INVALID_ARGUMENTS;
3280                 }
3281         }
3282
3283         return ERROR_OK;
3284 }
3285
3286 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3287                 arm_instruction_t *instruction, char *cp)
3288 {
3289         int rn = (opcode >> 16) & 0xf;
3290         int immed;
3291
3292         instruction->type = ARM_LDR;
3293
3294         if (rn == 0xf) {
3295                 immed = opcode & 0x0fff;
3296                 if ((opcode & (1 << 23)) == 0)
3297                         immed = -immed;
3298                 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3299                                 (int) (opcode >> 12) & 0xf,
3300                                 thumb_alignpc4(address) + immed);
3301                 return ERROR_OK;
3302         }
3303
3304         if (opcode & (1 << 23)) {
3305                 immed = opcode & 0x0fff;
3306                 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3307                                 (int) (opcode >> 12) & 0xf,
3308                                 rn, immed, immed);
3309                 return ERROR_OK;
3310         }
3311
3312         if (!(opcode & (0x3f << 6))) {
3313                 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3314                                 (int) (opcode >> 12) & 0xf,
3315                                 rn,
3316                                 (int) (opcode >> 0) & 0xf,
3317                                 (int) (opcode >> 4) & 0x3);
3318                 return ERROR_OK;
3319         }
3320
3321
3322         if (((opcode >> 8) & 0xf) == 0xe) {
3323                 immed = opcode & 0x00ff;
3324
3325                 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3326                                 (int) (opcode >> 12) & 0xf,
3327                                 rn, immed, immed);
3328                 return ERROR_OK;
3329         }
3330
3331         if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3332                 char *p1 = "]", *p2 = "";
3333
3334                 if (!(opcode & 0x0500))
3335                         return ERROR_INVALID_ARGUMENTS;
3336
3337                 immed = opcode & 0x00ff;
3338
3339                 /* two indexed modes will write back rn */
3340                 if (opcode & 0x100) {
3341                         if (opcode & 0x400)     /* pre-indexed */
3342                                 p2 = "]!";
3343                         else {                  /* post-indexed */
3344                                 p1 = "]";
3345                                 p2 = "";
3346                         }
3347                 }
3348
3349                 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3350                                 (int) (opcode >> 12) & 0xf,
3351                                 rn, p1,
3352                                 (opcode & 0x200) ? "" : "-",
3353                                 immed, p2, immed);
3354                 return ERROR_OK;
3355         }
3356
3357         return ERROR_INVALID_ARGUMENTS;
3358 }
3359
3360 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3361                 arm_instruction_t *instruction, char *cp)
3362 {
3363         int rn = (opcode >> 16) & 0xf;
3364         int rt = (opcode >> 12) & 0xf;
3365         int op2 = (opcode >> 6) & 0x3f;
3366         unsigned immed;
3367         char *p1 = "", *p2 = "]";
3368         char *mnemonic;
3369
3370         switch ((opcode >> 23) & 0x3) {
3371         case 0:
3372                 if ((rn & rt) == 0xf) {
3373 pld_literal:
3374                         immed = opcode & 0xfff;
3375                         address = thumb_alignpc4(address);
3376                         if (opcode & (1 << 23))
3377                                 address += immed;
3378                         else
3379                                 address -= immed;
3380                         sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
3381                                         rt, address);
3382                         return ERROR_OK;
3383                 }
3384                 if (rn == 0x0f && rt != 0x0f) {
3385 ldrb_literal:
3386                         immed = opcode & 0xfff;
3387                         address = thumb_alignpc4(address);
3388                         if (opcode & (1 << 23))
3389                                 address += immed;
3390                         else
3391                                 address -= immed;
3392                         sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3393                                         rt, address);
3394                         return ERROR_OK;
3395                 }
3396                 if (rn == 0x0f)
3397                         break;
3398                 if ((op2 & 0x3c) == 0x38) {
3399                         immed = opcode & 0xff;
3400                         sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3401                                         rt, rn, immed, immed);
3402                         return ERROR_OK;
3403                 }
3404                 if ((op2 & 0x3c) == 0x30) {
3405                         if (rt == 0x0f) {
3406                                 immed = opcode & 0xff;
3407                                 immed = -immed;
3408 preload_immediate:
3409                                 p1 = (opcode & (1 << 21)) ? "W" : "";
3410                                 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3411                                                 p1, rn, immed, immed);
3412                                 return ERROR_OK;
3413                         }
3414                         mnemonic = "LDRB";
3415 ldrxb_immediate_t3:
3416                         immed = opcode & 0xff;
3417                         if (!(opcode & 0x200))
3418                                 immed = -immed;
3419
3420                         /* two indexed modes will write back rn */
3421                         if (opcode & 0x100) {
3422                                 if (opcode & 0x400)     /* pre-indexed */
3423                                         p2 = "]!";
3424                                 else {                  /* post-indexed */
3425                                         p1 = "]";
3426                                         p2 = "";
3427                                 }
3428                         }
3429 ldrxb_immediate_t2:
3430                         sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3431                                         mnemonic, rt, rn, p1,
3432                                         immed, p2, immed);
3433                         return ERROR_OK;
3434                 }
3435                 if ((op2 & 0x24) == 0x24) {
3436                         mnemonic = "LDRB";
3437                         goto ldrxb_immediate_t3;
3438                 }
3439                 if (op2 == 0) {
3440                         int rm = opcode & 0xf;
3441
3442                         if (rt == 0x0f)
3443                                 sprintf(cp, "PLD\t");
3444                         else
3445                                 sprintf(cp, "LDRB.W\tr%d, ", rt);
3446                         immed = (opcode >> 4) & 0x3;
3447                         cp = strchr(cp, 0);
3448                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3449                         return ERROR_OK;
3450                 }
3451                 break;
3452         case 1:
3453                 if ((rn & rt) == 0xf)
3454                         goto pld_literal;
3455                 if (rt == 0xf) {
3456                         immed = opcode & 0xfff;
3457                         goto preload_immediate;
3458                 }
3459                 if (rn == 0x0f)
3460                         goto ldrb_literal;
3461                 mnemonic = "LDRB.W";
3462                 immed = opcode & 0xfff;
3463                 goto ldrxb_immediate_t2;
3464         case 2:
3465                 if ((rn & rt) == 0xf) {
3466                         immed = opcode & 0xfff;
3467                         address = thumb_alignpc4(address);
3468                         if (opcode & (1 << 23))
3469                                 address += immed;
3470                         else
3471                                 address -= immed;
3472                         sprintf(cp, "PLI\t%#8.8" PRIx32, address);
3473                         return ERROR_OK;
3474                 }
3475                 if (rn == 0xf && rt != 0xf) {
3476 ldrsb_literal:
3477                         immed = opcode & 0xfff;
3478                         address = thumb_alignpc4(address);
3479                         if (opcode & (1 << 23))
3480                                 address += immed;
3481                         else
3482                                 address -= immed;
3483                         sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
3484                         return ERROR_OK;
3485                 }
3486                 if (rn == 0xf)
3487                         break;
3488                 if ((op2 & 0x3c) == 0x38) {
3489                         immed = opcode & 0xff;
3490                         sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
3491                                         rt, rn, immed, immed);
3492                         return ERROR_OK;
3493                 }
3494                 if ((op2 & 0x3c) == 0x30) {
3495                         if (rt == 0xf) {
3496                                 immed = opcode & 0xff;
3497                                 immed = -immed; // pli
3498                                 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
3499                                                 rn, immed, -immed);
3500                                 return ERROR_OK;
3501                         }
3502                         mnemonic = "LDRSB";
3503                         goto ldrxb_immediate_t3;
3504                 }
3505                 if ((op2 & 0x24) == 0x24) {
3506                         mnemonic = "LDRSB";
3507                         goto ldrxb_immediate_t3;
3508                 }
3509                 if (op2 == 0) {
3510                         int rm = opcode & 0xf;
3511
3512                         if (rt == 0x0f)
3513                                 sprintf(cp, "PLI\t");
3514                         else
3515                                 sprintf(cp, "LDRSB.W\tr%d, ", rt);
3516                         immed = (opcode >> 4) & 0x3;
3517                         cp = strchr(cp, 0);
3518                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3519                         return ERROR_OK;
3520                 }
3521                 break;
3522         case 3:
3523                 if (rt == 0xf) {
3524                         immed = opcode & 0xfff;
3525                         sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3" PRIx32,
3526                                         rn, immed, immed);
3527                         return ERROR_OK;
3528                 }
3529                 if (rn == 0xf)
3530                         goto ldrsb_literal;
3531                 immed = opcode & 0xfff;
3532                 mnemonic = "LDRSB";
3533                 goto ldrxb_immediate_t2;
3534         }
3535
3536         return ERROR_INVALID_ARGUMENTS;
3537 }
3538
3539 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
3540                 arm_instruction_t *instruction, char *cp)
3541 {
3542         int rn = (opcode >> 16) & 0xf;
3543         int rt = (opcode >> 12) & 0xf;
3544         int op2 = (opcode >> 6) & 0x3f;
3545         char *sign = "";
3546         unsigned immed;
3547
3548         if (rt == 0xf) {
3549                 sprintf(cp, "HINT (UNALLOCATED)");
3550                 return ERROR_OK;
3551         }
3552
3553         if (opcode & (1 << 24))
3554                 sign = "S";
3555
3556         if ((opcode & (1 << 23)) == 0) {
3557                 if (rn == 0xf) {
3558 ldrh_literal:
3559                         immed = opcode & 0xfff;
3560                         address = thumb_alignpc4(address);
3561                         if (opcode & (1 << 23))
3562                                 address += immed;
3563                         else
3564                                 address -= immed;
3565                         sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
3566                                         sign, rt, address);
3567                         return ERROR_OK;
3568                 }
3569                 if (op2 == 0) {
3570                         int rm = opcode & 0xf;
3571
3572                         immed = (opcode >> 4) & 0x3;
3573                         sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
3574                                         sign, rt, rn, rm, immed);
3575                         return ERROR_OK;
3576                 }
3577                 if ((op2 & 0x3c) == 0x38) {
3578                         immed = opcode & 0xff;
3579                         sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
3580                                         sign, rt, rn, immed, immed);
3581                         return ERROR_OK;
3582                 }
3583                 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
3584                         char *p1 = "", *p2 = "]";
3585
3586                         immed = opcode & 0xff;
3587                         if (!(opcode & 0x200))
3588                                 immed = -immed;
3589
3590                         /* two indexed modes will write back rn */
3591                         if (opcode & 0x100) {
3592                                 if (opcode & 0x400)     /* pre-indexed */
3593                                         p2 = "]!";
3594                                 else {                  /* post-indexed */
3595                                         p1 = "]";
3596                                         p2 = "";
3597                                 }
3598                         }
3599                         sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3600                                         sign, rt, rn, p1, immed, p2, immed);
3601                         return ERROR_OK;
3602                 }
3603         } else {
3604                 if (rn == 0xf)
3605                         goto ldrh_literal;
3606
3607                 immed = opcode & 0xfff;
3608                 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
3609                                 sign, *sign ? "" : ".W",
3610                                 rt, rn, immed, immed);
3611                 return ERROR_OK;
3612         }
3613
3614         return ERROR_INVALID_ARGUMENTS;
3615 }
3616
3617 /*
3618  * REVISIT for Thumb2 instructions, instruction->type and friends aren't
3619  * always set.  That means eventual arm_simulate_step() support for Thumb2
3620  * will need work in this area.
3621  */
3622 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
3623 {
3624         int retval;
3625         uint16_t op;
3626         uint32_t opcode;
3627         char *cp;
3628
3629         /* clear low bit ... it's set on function pointers */
3630         address &= ~1;
3631
3632         /* clear fields, to avoid confusion */
3633         memset(instruction, 0, sizeof(arm_instruction_t));
3634
3635         /* read first halfword, see if this is the only one */
3636         retval = target_read_u16(target, address, &op);
3637         if (retval != ERROR_OK)
3638                 return retval;
3639
3640         switch (op & 0xf800) {
3641         case 0xf800:
3642         case 0xf000:
3643         case 0xe800:
3644                 /* 32-bit instructions */
3645                 instruction->instruction_size = 4;
3646                 opcode = op << 16;
3647                 retval = target_read_u16(target, address + 2, &op);
3648                 if (retval != ERROR_OK)
3649                         return retval;
3650                 opcode |= op;
3651                 instruction->opcode = opcode;
3652                 break;
3653         default:
3654                 /* 16-bit:  Thumb1 + IT + CBZ/CBNZ + ... */
3655                 return thumb_evaluate_opcode(op, address, instruction);
3656         }
3657
3658         snprintf(instruction->text, 128,
3659                         "0x%8.8" PRIx32 "  0x%8.8" PRIx32 "\t",
3660                         address, opcode);
3661         cp = strchr(instruction->text, 0);
3662         retval = ERROR_FAIL;
3663
3664         /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3665         if ((opcode & 0x1a008000) == 0x10000000)
3666                 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3667
3668         /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3669         else if ((opcode & 0x1a008000) == 0x12000000)
3670                 retval = t2ev_data_immed(opcode, address, instruction, cp);
3671
3672         /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3673         else if ((opcode & 0x18008000) == 0x10008000)
3674                 retval = t2ev_b_misc(opcode, address, instruction, cp);
3675
3676         /* ARMv7-M: A5.3.5 Load/store multiple */
3677         else if ((opcode & 0x1e400000) == 0x08000000)
3678                 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3679
3680         /* ARMv7-M: A5.3.7 Load word */
3681         else if ((opcode & 0x1f700000) == 0x18500000)
3682                 retval = t2ev_load_word(opcode, address, instruction, cp);
3683
3684         /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
3685         else if ((opcode & 0x1e700000) == 0x18300000)
3686                 retval = t2ev_load_halfword(opcode, address, instruction, cp);
3687
3688         /* ARMv7-M: A5.3.9 Load byte, memory hints */
3689         else if ((opcode & 0x1e700000) == 0x18100000)
3690                 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
3691
3692         /* ARMv7-M: A5.3.10 Store single data item */
3693         else if ((opcode & 0x1f100000) == 0x18000000)
3694                 retval = t2ev_store_single(opcode, address, instruction, cp);
3695
3696         /* ARMv7-M: A5.3.11 Data processing (shifted register) */
3697         else if ((opcode & 0x1e000000) == 0x0a000000)
3698                 retval = t2ev_data_shift(opcode, address, instruction, cp);
3699
3700         /* ARMv7-M: A5.3.12 Data processing (register)
3701          * and      A5.3.13 Miscellaneous operations
3702          */
3703         else if ((opcode & 0x1f000000) == 0x1a000000)
3704                 retval = t2ev_data_reg(opcode, address, instruction, cp);
3705
3706         /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3707         else if ((opcode & 0x1f800000) == 0x1b000000)
3708                 retval = t2ev_mul32(opcode, address, instruction, cp);
3709
3710         /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3711         else if ((opcode & 0x1f800000) == 0x1b800000)
3712                 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3713
3714         /* FIXME decode more 32-bit instructions */
3715
3716         if (retval == ERROR_OK)
3717                 return retval;
3718
3719         if (retval == ERROR_INVALID_ARGUMENTS) {
3720                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3721                 strcpy(cp, "UNDEFINED OPCODE");
3722                 return ERROR_OK;
3723         }
3724
3725         LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
3726                         opcode);
3727
3728         strcpy(cp, "(32-bit Thumb2 ...)");
3729         return ERROR_OK;
3730 }
3731
3732 int arm_access_size(arm_instruction_t *instruction)
3733 {
3734         if ((instruction->type == ARM_LDRB)
3735                 || (instruction->type == ARM_LDRBT)
3736                 || (instruction->type == ARM_LDRSB)
3737                 || (instruction->type == ARM_STRB)
3738                 || (instruction->type == ARM_STRBT))
3739         {
3740                 return 1;
3741         }
3742         else if ((instruction->type == ARM_LDRH)
3743                 || (instruction->type == ARM_LDRSH)
3744                 || (instruction->type == ARM_STRH))
3745         {
3746                 return 2;
3747         }
3748         else if ((instruction->type == ARM_LDR)
3749                 || (instruction->type == ARM_LDRT)
3750                 || (instruction->type == ARM_STR)
3751                 || (instruction->type == ARM_STRT))
3752         {
3753                 return 4;
3754         }
3755         else if ((instruction->type == ARM_LDRD)
3756                 || (instruction->type == ARM_STRD))
3757         {
3758                 return 8;
3759         }
3760         else
3761         {
3762                 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
3763                 return 0;
3764         }
3765 }