David Brownell <david-b@pacbell.net> More fixes from test cases:
[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                 instruction->type = ARM_ADD;
1399                 mnemonic = "ADDS";
1400         }
1401
1402         instruction->info.data_proc.Rd = Rd;
1403         instruction->info.data_proc.Rn = Rn;
1404         instruction->info.data_proc.S = 1;
1405
1406         if (reg_imm)
1407         {
1408                 instruction->info.data_proc.variant = 0; /*immediate*/
1409                 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1410                 snprintf(instruction->text, 128,
1411                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%d",
1412                         address, opcode, mnemonic, Rd, Rn, Rm_imm);
1413         }
1414         else
1415         {
1416                 instruction->info.data_proc.variant = 1; /*immediate shift*/
1417                 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1418                 snprintf(instruction->text, 128,
1419                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, r%i",
1420                         address, opcode, mnemonic, Rd, Rn, Rm_imm);
1421         }
1422
1423         return ERROR_OK;
1424 }
1425
1426 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1427 {
1428         uint8_t Rd = (opcode >> 0) & 0x7;
1429         uint8_t Rm = (opcode >> 3) & 0x7;
1430         uint8_t imm = (opcode >> 6) & 0x1f;
1431         uint8_t opc = (opcode >> 11) & 0x3;
1432         char *mnemonic = NULL;
1433
1434         switch (opc)
1435         {
1436                 case 0:
1437                         instruction->type = ARM_MOV;
1438                         mnemonic = "LSLS";
1439                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1440                         break;
1441                 case 1:
1442                         instruction->type = ARM_MOV;
1443                         mnemonic = "LSRS";
1444                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1445                         break;
1446                 case 2:
1447                         instruction->type = ARM_MOV;
1448                         mnemonic = "ASRS";
1449                         instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1450                         break;
1451         }
1452
1453         if ((imm == 0) && (opc != 0))
1454                 imm = 32;
1455
1456         instruction->info.data_proc.Rd = Rd;
1457         instruction->info.data_proc.Rn = -1;
1458         instruction->info.data_proc.S = 1;
1459
1460         instruction->info.data_proc.variant = 1; /*immediate_shift*/
1461         instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1462         instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1463
1464         snprintf(instruction->text, 128,
1465                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%#2.2x" ,
1466                         address, opcode, mnemonic, Rd, Rm, imm);
1467
1468         return ERROR_OK;
1469 }
1470
1471 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1472 {
1473         uint8_t imm = opcode & 0xff;
1474         uint8_t Rd = (opcode >> 8) & 0x7;
1475         uint32_t opc = (opcode >> 11) & 0x3;
1476         char *mnemonic = NULL;
1477
1478         instruction->info.data_proc.Rd = Rd;
1479         instruction->info.data_proc.Rn = Rd;
1480         instruction->info.data_proc.S = 1;
1481         instruction->info.data_proc.variant = 0; /*immediate*/
1482         instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1483
1484         switch (opc)
1485         {
1486                 case 0:
1487                         instruction->type = ARM_MOV;
1488                         mnemonic = "MOVS";
1489                         instruction->info.data_proc.Rn = -1;
1490                         break;
1491                 case 1:
1492                         instruction->type = ARM_CMP;
1493                         mnemonic = "CMP";
1494                         instruction->info.data_proc.Rd = -1;
1495                         break;
1496                 case 2:
1497                         instruction->type = ARM_ADD;
1498                         mnemonic = "ADDS";
1499                         break;
1500                 case 3:
1501                         instruction->type = ARM_SUB;
1502                         mnemonic = "SUBS";
1503                         break;
1504         }
1505
1506         snprintf(instruction->text, 128,
1507                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, #%#2.2x",
1508                         address, opcode, mnemonic, Rd, imm);
1509
1510         return ERROR_OK;
1511 }
1512
1513 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1514 {
1515         uint8_t high_reg, op, Rm, Rd,H1,H2;
1516         char *mnemonic = NULL;
1517         bool nop = false;
1518
1519         high_reg = (opcode & 0x0400) >> 10;
1520         op = (opcode & 0x03C0) >> 6;
1521
1522         Rd = (opcode & 0x0007);
1523         Rm = (opcode & 0x0038) >> 3;
1524         H1 = (opcode & 0x0080) >> 7;
1525         H2 = (opcode & 0x0040) >> 6;
1526
1527         instruction->info.data_proc.Rd = Rd;
1528         instruction->info.data_proc.Rn = Rd;
1529         instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1530         instruction->info.data_proc.variant = 1 /*immediate shift*/;
1531         instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1532
1533         if (high_reg)
1534         {
1535                 Rd |= H1 << 3;
1536                 Rm |= H2 << 3;
1537                 op >>= 2;
1538
1539                 switch (op)
1540                 {
1541                         case 0x0:
1542                                 instruction->type = ARM_ADD;
1543                                 mnemonic = "ADD";
1544                                 break;
1545                         case 0x1:
1546                                 instruction->type = ARM_CMP;
1547                                 mnemonic = "CMP";
1548                                 break;
1549                         case 0x2:
1550                                 instruction->type = ARM_MOV;
1551                                 mnemonic = "MOV";
1552                                 if (Rd == Rm)
1553                                         nop = true;
1554                                 break;
1555                         case 0x3:
1556                                 if ((opcode & 0x7) == 0x0)
1557                                 {
1558                                         instruction->info.b_bl_bx_blx.reg_operand = Rm;
1559                                         if (H1)
1560                                         {
1561                                                 instruction->type = ARM_BLX;
1562                                                 snprintf(instruction->text, 128,
1563                                                         "0x%8.8" PRIx32
1564                                                         "  0x%4.4x    \tBLX\tr%i",
1565                                                         address, opcode, Rm);
1566                                         }
1567                                         else
1568                                         {
1569                                                 instruction->type = ARM_BX;
1570                                                 snprintf(instruction->text, 128,
1571                                                         "0x%8.8" PRIx32
1572                                                         "  0x%4.4x    \tBX\tr%i",
1573                                                         address, opcode, Rm);
1574                                         }
1575                                 }
1576                                 else
1577                                 {
1578                                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
1579                                         snprintf(instruction->text, 128,
1580                                                 "0x%8.8" PRIx32
1581                                                 "  0x%4.4x    \t"
1582                                                 "UNDEFINED INSTRUCTION",
1583                                                 address, opcode);
1584                                 }
1585                                 return ERROR_OK;
1586                                 break;
1587                 }
1588         }
1589         else
1590         {
1591                 switch (op)
1592                 {
1593                         case 0x0:
1594                                 instruction->type = ARM_AND;
1595                                 mnemonic = "ANDS";
1596                                 break;
1597                         case 0x1:
1598                                 instruction->type = ARM_EOR;
1599                                 mnemonic = "EORS";
1600                                 break;
1601                         case 0x2:
1602                                 instruction->type = ARM_MOV;
1603                                 mnemonic = "LSLS";
1604                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1605                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1606                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1607                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1608                                 break;
1609                         case 0x3:
1610                                 instruction->type = ARM_MOV;
1611                                 mnemonic = "LSRS";
1612                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1613                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1614                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1615                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1616                                 break;
1617                         case 0x4:
1618                                 instruction->type = ARM_MOV;
1619                                 mnemonic = "ASRS";
1620                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1621                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1622                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1623                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1624                                 break;
1625                         case 0x5:
1626                                 instruction->type = ARM_ADC;
1627                                 mnemonic = "ADCS";
1628                                 break;
1629                         case 0x6:
1630                                 instruction->type = ARM_SBC;
1631                                 mnemonic = "SBCS";
1632                                 break;
1633                         case 0x7:
1634                                 instruction->type = ARM_MOV;
1635                                 mnemonic = "RORS";
1636                                 instruction->info.data_proc.variant = 2 /*register shift*/;
1637                                 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1638                                 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1639                                 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1640                                 break;
1641                         case 0x8:
1642                                 instruction->type = ARM_TST;
1643                                 mnemonic = "TST";
1644                                 break;
1645                         case 0x9:
1646                                 instruction->type = ARM_RSB;
1647                                 mnemonic = "RSBS";
1648                                 instruction->info.data_proc.variant = 0 /*immediate*/;
1649                                 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1650                                 instruction->info.data_proc.Rn = Rm;
1651                                 break;
1652                         case 0xA:
1653                                 instruction->type = ARM_CMP;
1654                                 mnemonic = "CMP";
1655                                 break;
1656                         case 0xB:
1657                                 instruction->type = ARM_CMN;
1658                                 mnemonic = "CMN";
1659                                 break;
1660                         case 0xC:
1661                                 instruction->type = ARM_ORR;
1662                                 mnemonic = "ORRS";
1663                                 break;
1664                         case 0xD:
1665                                 instruction->type = ARM_MUL;
1666                                 mnemonic = "MULS";
1667                                 break;
1668                         case 0xE:
1669                                 instruction->type = ARM_BIC;
1670                                 mnemonic = "BICS";
1671                                 break;
1672                         case 0xF:
1673                                 instruction->type = ARM_MVN;
1674                                 mnemonic = "MVNS";
1675                                 break;
1676                 }
1677         }
1678
1679         if (nop)
1680                 snprintf(instruction->text, 128,
1681                                 "0x%8.8" PRIx32 "  0x%4.4x    \tNOP\t\t\t"
1682                                 "; (%s r%i, r%i)",
1683                                  address, opcode, mnemonic, Rd, Rm);
1684         else
1685                 snprintf(instruction->text, 128,
1686                                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i",
1687                                  address, opcode, mnemonic, Rd, Rm);
1688
1689         return ERROR_OK;
1690 }
1691
1692 /* PC-relative data addressing is word-aligned even with Thumb */
1693 static inline uint32_t thumb_alignpc4(uint32_t addr)
1694 {
1695         return (addr + 4) & ~3;
1696 }
1697
1698 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1699 {
1700         uint32_t immediate;
1701         uint8_t Rd = (opcode >> 8) & 0x7;
1702
1703         instruction->type = ARM_LDR;
1704         immediate = opcode & 0x000000ff;
1705         immediate *= 4;
1706
1707         instruction->info.load_store.Rd = Rd;
1708         instruction->info.load_store.Rn = 15 /*PC*/;
1709         instruction->info.load_store.index_mode = 0; /*offset*/
1710         instruction->info.load_store.offset_mode = 0; /*immediate*/
1711         instruction->info.load_store.offset.offset = immediate;
1712
1713         snprintf(instruction->text, 128,
1714                 "0x%8.8" PRIx32 "  0x%4.4x    \t"
1715                 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
1716                 address, opcode, Rd, immediate,
1717                 thumb_alignpc4(address) + immediate);
1718
1719         return ERROR_OK;
1720 }
1721
1722 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1723 {
1724         uint8_t Rd = (opcode >> 0) & 0x7;
1725         uint8_t Rn = (opcode >> 3) & 0x7;
1726         uint8_t Rm = (opcode >> 6) & 0x7;
1727         uint8_t opc = (opcode >> 9) & 0x7;
1728         char *mnemonic = NULL;
1729
1730         switch (opc)
1731         {
1732                 case 0:
1733                         instruction->type = ARM_STR;
1734                         mnemonic = "STR";
1735                         break;
1736                 case 1:
1737                         instruction->type = ARM_STRH;
1738                         mnemonic = "STRH";
1739                         break;
1740                 case 2:
1741                         instruction->type = ARM_STRB;
1742                         mnemonic = "STRB";
1743                         break;
1744                 case 3:
1745                         instruction->type = ARM_LDRSB;
1746                         mnemonic = "LDRSB";
1747                         break;
1748                 case 4:
1749                         instruction->type = ARM_LDR;
1750                         mnemonic = "LDR";
1751                         break;
1752                 case 5:
1753                         instruction->type = ARM_LDRH;
1754                         mnemonic = "LDRH";
1755                         break;
1756                 case 6:
1757                         instruction->type = ARM_LDRB;
1758                         mnemonic = "LDRB";
1759                         break;
1760                 case 7:
1761                         instruction->type = ARM_LDRSH;
1762                         mnemonic = "LDRSH";
1763                         break;
1764         }
1765
1766         snprintf(instruction->text, 128,
1767                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [r%i, r%i]",
1768                         address, opcode, mnemonic, Rd, Rn, Rm);
1769
1770         instruction->info.load_store.Rd = Rd;
1771         instruction->info.load_store.Rn = Rn;
1772         instruction->info.load_store.index_mode = 0; /*offset*/
1773         instruction->info.load_store.offset_mode = 1; /*register*/
1774         instruction->info.load_store.offset.reg.Rm = Rm;
1775
1776         return ERROR_OK;
1777 }
1778
1779 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1780 {
1781         uint32_t offset = (opcode >> 6) & 0x1f;
1782         uint8_t Rd = (opcode >> 0) & 0x7;
1783         uint8_t Rn = (opcode >> 3) & 0x7;
1784         uint32_t L = opcode & (1 << 11);
1785         uint32_t B = opcode & (1 << 12);
1786         char *mnemonic;
1787         char suffix = ' ';
1788         uint32_t shift = 2;
1789
1790         if (L)
1791         {
1792                 instruction->type = ARM_LDR;
1793                 mnemonic = "LDR";
1794         }
1795         else
1796         {
1797                 instruction->type = ARM_STR;
1798                 mnemonic = "STR";
1799         }
1800
1801         if ((opcode&0xF000) == 0x8000)
1802         {
1803                 suffix = 'H';
1804                 shift = 1;
1805         }
1806         else if (B)
1807         {
1808                 suffix = 'B';
1809                 shift = 0;
1810         }
1811
1812         snprintf(instruction->text, 128,
1813                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1814                 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1815
1816         instruction->info.load_store.Rd = Rd;
1817         instruction->info.load_store.Rn = Rn;
1818         instruction->info.load_store.index_mode = 0; /*offset*/
1819         instruction->info.load_store.offset_mode = 0; /*immediate*/
1820         instruction->info.load_store.offset.offset = offset << shift;
1821
1822         return ERROR_OK;
1823 }
1824
1825 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1826 {
1827         uint32_t offset = opcode  & 0xff;
1828         uint8_t Rd = (opcode >> 8) & 0x7;
1829         uint32_t L = opcode & (1 << 11);
1830         char *mnemonic;
1831
1832         if (L)
1833         {
1834                 instruction->type = ARM_LDR;
1835                 mnemonic = "LDR";
1836         }
1837         else
1838         {
1839                 instruction->type = ARM_STR;
1840                 mnemonic = "STR";
1841         }
1842
1843         snprintf(instruction->text, 128,
1844                 "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [SP, #%#" PRIx32 "]",
1845                 address, opcode, mnemonic, Rd, offset*4);
1846
1847         instruction->info.load_store.Rd = Rd;
1848         instruction->info.load_store.Rn = 13 /*SP*/;
1849         instruction->info.load_store.index_mode = 0; /*offset*/
1850         instruction->info.load_store.offset_mode = 0; /*immediate*/
1851         instruction->info.load_store.offset.offset = offset*4;
1852
1853         return ERROR_OK;
1854 }
1855
1856 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1857 {
1858         uint32_t imm = opcode  & 0xff;
1859         uint8_t Rd = (opcode >> 8) & 0x7;
1860         uint8_t Rn;
1861         uint32_t SP = opcode & (1 << 11);
1862         char *reg_name;
1863
1864         instruction->type = ARM_ADD;
1865
1866         if (SP)
1867         {
1868                 reg_name = "SP";
1869                 Rn = 13;
1870         }
1871         else
1872         {
1873                 reg_name = "PC";
1874                 Rn = 15;
1875         }
1876
1877         snprintf(instruction->text, 128,
1878                 "0x%8.8" PRIx32 "  0x%4.4x  \tADD\tr%i, %s, #%#" PRIx32,
1879                 address, opcode, Rd, reg_name, imm * 4);
1880
1881         instruction->info.data_proc.variant = 0 /* immediate */;
1882         instruction->info.data_proc.Rd = Rd;
1883         instruction->info.data_proc.Rn = Rn;
1884         instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1885
1886         return ERROR_OK;
1887 }
1888
1889 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1890 {
1891         uint32_t imm = opcode  & 0x7f;
1892         uint8_t opc = opcode & (1 << 7);
1893         char *mnemonic;
1894
1895
1896         if (opc)
1897         {
1898                 instruction->type = ARM_SUB;
1899                 mnemonic = "SUB";
1900         }
1901         else
1902         {
1903                 instruction->type = ARM_ADD;
1904                 mnemonic = "ADD";
1905         }
1906
1907         snprintf(instruction->text, 128,
1908                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tSP, #%#" PRIx32,
1909                         address, opcode, mnemonic, imm*4);
1910
1911         instruction->info.data_proc.variant = 0 /* immediate */;
1912         instruction->info.data_proc.Rd = 13 /*SP*/;
1913         instruction->info.data_proc.Rn = 13 /*SP*/;
1914         instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1915
1916         return ERROR_OK;
1917 }
1918
1919 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1920 {
1921         uint32_t imm = opcode  & 0xff;
1922
1923         instruction->type = ARM_BKPT;
1924
1925         snprintf(instruction->text, 128,
1926                         "0x%8.8" PRIx32 "  0x%4.4x  \tBKPT\t%#2.2" PRIx32 "",
1927                         address, opcode, imm);
1928
1929         return ERROR_OK;
1930 }
1931
1932 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1933 {
1934         uint32_t reg_list = opcode  & 0xff;
1935         uint32_t L = opcode & (1 << 11);
1936         uint32_t R = opcode & (1 << 8);
1937         uint8_t Rn = (opcode >> 8) & 7;
1938         uint8_t addr_mode = 0 /* IA */;
1939         char reg_names[40];
1940         char *reg_names_p;
1941         char *mnemonic;
1942         char ptr_name[7] = "";
1943         int i;
1944
1945         if ((opcode & 0xf000) == 0xc000)
1946         { /* generic load/store multiple */
1947                 char *wback = "!";
1948
1949                 if (L)
1950                 {
1951                         instruction->type = ARM_LDM;
1952                         mnemonic = "LDM";
1953                         if (opcode & (1 << Rn))
1954                                 wback = "";
1955                 }
1956                 else
1957                 {
1958                         instruction->type = ARM_STM;
1959                         mnemonic = "STM";
1960                 }
1961                 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
1962         }
1963         else
1964         { /* push/pop */
1965                 Rn = 13; /* SP */
1966                 if (L)
1967                 {
1968                         instruction->type = ARM_LDM;
1969                         mnemonic = "POP";
1970                         if (R)
1971                                 reg_list |= (1 << 15) /*PC*/;
1972                 }
1973                 else
1974                 {
1975                         instruction->type = ARM_STM;
1976                         mnemonic = "PUSH";
1977                         addr_mode = 3; /*DB*/
1978                         if (R)
1979                                 reg_list |= (1 << 14) /*LR*/;
1980                 }
1981         }
1982
1983         reg_names_p = reg_names;
1984         for (i = 0; i <= 15; i++)
1985         {
1986                 if (reg_list & (1 << i))
1987                         reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1988         }
1989         if (reg_names_p > reg_names)
1990                 reg_names_p[-2] = '\0';
1991         else /* invalid op : no registers */
1992                 reg_names[0] = '\0';
1993
1994         snprintf(instruction->text, 128,
1995                         "0x%8.8" PRIx32 "  0x%4.4x  \t%s\t%s{%s}",
1996                         address, opcode, mnemonic, ptr_name, reg_names);
1997
1998         instruction->info.load_store_multiple.register_list = reg_list;
1999         instruction->info.load_store_multiple.Rn = Rn;
2000         instruction->info.load_store_multiple.addressing_mode = addr_mode;
2001
2002         return ERROR_OK;
2003 }
2004
2005 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2006 {
2007         uint32_t offset = opcode  & 0xff;
2008         uint8_t cond = (opcode >> 8) & 0xf;
2009         uint32_t target_address;
2010
2011         if (cond == 0xf)
2012         {
2013                 instruction->type = ARM_SWI;
2014                 snprintf(instruction->text, 128,
2015                                 "0x%8.8" PRIx32 "  0x%4.4x    \tSVC\t%#2.2" PRIx32,
2016                                 address, opcode, offset);
2017                 return ERROR_OK;
2018         }
2019         else if (cond == 0xe)
2020         {
2021                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2022                 snprintf(instruction->text, 128,
2023                         "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
2024                         address, opcode);
2025                 return ERROR_OK;
2026         }
2027
2028         /* sign extend 8-bit offset */
2029         if (offset & 0x00000080)
2030                 offset = 0xffffff00 | offset;
2031
2032         target_address = address + 4 + (offset << 1);
2033
2034         snprintf(instruction->text, 128,
2035                         "0x%8.8" PRIx32 "  0x%4.4x    \tB%s\t%#8.8" PRIx32,
2036                         address, opcode,
2037                         arm_condition_strings[cond], target_address);
2038
2039         instruction->type = ARM_B;
2040         instruction->info.b_bl_bx_blx.reg_operand = -1;
2041         instruction->info.b_bl_bx_blx.target_address = target_address;
2042
2043         return ERROR_OK;
2044 }
2045
2046 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2047                 arm_instruction_t *instruction)
2048 {
2049         unsigned offset;
2050
2051         /* added in Thumb2 */
2052         offset = (opcode >> 3) & 0x1f;
2053         offset |= (opcode & 0x0200) >> 4;
2054
2055         snprintf(instruction->text, 128,
2056                         "0x%8.8" PRIx32 "  0x%4.4x    \tCB%sZ\tr%d, %#8.8" PRIx32,
2057                         address, opcode,
2058                         (opcode & 0x0800) ? "N" : "",
2059                         opcode & 0x7, address + 4 + (offset << 1));
2060
2061         return ERROR_OK;
2062 }
2063
2064 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2065                 arm_instruction_t *instruction)
2066 {
2067         /* added in ARMv6 */
2068         snprintf(instruction->text, 128,
2069                         "0x%8.8" PRIx32 "  0x%4.4x    \t%cXT%c\tr%d, r%d",
2070                         address, opcode,
2071                         (opcode & 0x0080) ? 'U' : 'S',
2072                         (opcode & 0x0040) ? 'B' : 'H',
2073                         opcode & 0x7, (opcode >> 3) & 0x7);
2074
2075         return ERROR_OK;
2076 }
2077
2078 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2079                 arm_instruction_t *instruction)
2080 {
2081         /* added in ARMv6 */
2082         if ((opcode & 0x0ff0) == 0x0650)
2083                 snprintf(instruction->text, 128,
2084                                 "0x%8.8" PRIx32 "  0x%4.4x    \tSETEND %s",
2085                                 address, opcode,
2086                                 (opcode & 0x80) ? "BE" : "LE");
2087         else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2088                 snprintf(instruction->text, 128,
2089                                 "0x%8.8" PRIx32 "  0x%4.4x    \tCPSI%c\t%s%s%s",
2090                                 address, opcode,
2091                                 (opcode & 0x0010) ? 'D' : 'E',
2092                                 (opcode & 0x0004) ? "A" : "",
2093                                 (opcode & 0x0002) ? "I" : "",
2094                                 (opcode & 0x0001) ? "F" : "");
2095
2096         return ERROR_OK;
2097 }
2098
2099 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2100                 arm_instruction_t *instruction)
2101 {
2102         char *suffix;
2103
2104         /* added in ARMv6 */
2105         switch ((opcode >> 6) & 3) {
2106         case 0:
2107                 suffix = "";
2108                 break;
2109         case 1:
2110                 suffix = "16";
2111                 break;
2112         default:
2113                 suffix = "SH";
2114                 break;
2115         }
2116         snprintf(instruction->text, 128,
2117                         "0x%8.8" PRIx32 "  0x%4.4x    \tREV%s\tr%d, r%d",
2118                         address, opcode, suffix,
2119                         opcode & 0x7, (opcode >> 3) & 0x7);
2120
2121         return ERROR_OK;
2122 }
2123
2124 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2125                 arm_instruction_t *instruction)
2126 {
2127         char *hint;
2128
2129         switch ((opcode >> 4) & 0x0f) {
2130         case 0:
2131                 hint = "NOP";
2132                 break;
2133         case 1:
2134                 hint = "YIELD";
2135                 break;
2136         case 2:
2137                 hint = "WFE";
2138                 break;
2139         case 3:
2140                 hint = "WFI";
2141                 break;
2142         case 4:
2143                 hint = "SEV";
2144                 break;
2145         default:
2146                 hint = "HINT (UNRECOGNIZED)";
2147                 break;
2148         }
2149
2150         snprintf(instruction->text, 128,
2151                         "0x%8.8" PRIx32 "  0x%4.4x    \t%s",
2152                         address, opcode, hint);
2153
2154         return ERROR_OK;
2155 }
2156
2157 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2158                 arm_instruction_t *instruction)
2159 {
2160         unsigned cond = (opcode >> 4) & 0x0f;
2161         char *x = "", *y = "", *z = "";
2162
2163         if (opcode & 0x01)
2164                 z = (opcode & 0x02) ? "T" : "E";
2165         if (opcode & 0x03)
2166                 y = (opcode & 0x04) ? "T" : "E";
2167         if (opcode & 0x07)
2168                 x = (opcode & 0x08) ? "T" : "E";
2169
2170         snprintf(instruction->text, 128,
2171                         "0x%8.8" PRIx32 "  0x%4.4x    \tIT%s%s%s\t%s",
2172                         address, opcode,
2173                         x, y, z, arm_condition_strings[cond]);
2174
2175         /* NOTE:  strictly speaking, the next 1-4 instructions should
2176          * now be displayed with the relevant conditional suffix...
2177          */
2178
2179         return ERROR_OK;
2180 }
2181
2182 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2183 {
2184         /* clear fields, to avoid confusion */
2185         memset(instruction, 0, sizeof(arm_instruction_t));
2186         instruction->opcode = opcode;
2187         instruction->instruction_size = 2;
2188
2189         if ((opcode & 0xe000) == 0x0000)
2190         {
2191                 /* add/substract register or immediate */
2192                 if ((opcode & 0x1800) == 0x1800)
2193                         return evaluate_add_sub_thumb(opcode, address, instruction);
2194                 /* shift by immediate */
2195                 else
2196                         return evaluate_shift_imm_thumb(opcode, address, instruction);
2197         }
2198
2199         /* Add/substract/compare/move immediate */
2200         if ((opcode & 0xe000) == 0x2000)
2201         {
2202                 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2203         }
2204
2205         /* Data processing instructions */
2206         if ((opcode & 0xf800) == 0x4000)
2207         {
2208                 return evaluate_data_proc_thumb(opcode, address, instruction);
2209         }
2210
2211         /* Load from literal pool */
2212         if ((opcode & 0xf800) == 0x4800)
2213         {
2214                 return evaluate_load_literal_thumb(opcode, address, instruction);
2215         }
2216
2217         /* Load/Store register offset */
2218         if ((opcode & 0xf000) == 0x5000)
2219         {
2220                 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2221         }
2222
2223         /* Load/Store immediate offset */
2224         if (((opcode & 0xe000) == 0x6000)
2225                 ||((opcode & 0xf000) == 0x8000))
2226         {
2227                 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2228         }
2229
2230         /* Load/Store from/to stack */
2231         if ((opcode & 0xf000) == 0x9000)
2232         {
2233                 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2234         }
2235
2236         /* Add to SP/PC */
2237         if ((opcode & 0xf000) == 0xa000)
2238         {
2239                 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2240         }
2241
2242         /* Misc */
2243         if ((opcode & 0xf000) == 0xb000)
2244         {
2245                 switch ((opcode >> 8) & 0x0f) {
2246                 case 0x0:
2247                         return evaluate_adjust_stack_thumb(opcode, address, instruction);
2248                 case 0x1:
2249                 case 0x3:
2250                 case 0x9:
2251                 case 0xb:
2252                         return evaluate_cb_thumb(opcode, address, instruction);
2253                 case 0x2:
2254                         return evaluate_extend_thumb(opcode, address, instruction);
2255                 case 0x4:
2256                 case 0x5:
2257                 case 0xc:
2258                 case 0xd:
2259                         return evaluate_load_store_multiple_thumb(opcode, address,
2260                                                 instruction);
2261                 case 0x6:
2262                         return evaluate_cps_thumb(opcode, address, instruction);
2263                 case 0xa:
2264                         if ((opcode & 0x00c0) == 0x0080)
2265                                 break;
2266                         return evaluate_byterev_thumb(opcode, address, instruction);
2267                 case 0xe:
2268                         return evaluate_breakpoint_thumb(opcode, address, instruction);
2269                 case 0xf:
2270                         if (opcode & 0x000f)
2271                                 return evaluate_ifthen_thumb(opcode, address,
2272                                                 instruction);
2273                         else
2274                                 return evaluate_hint_thumb(opcode, address,
2275                                                 instruction);
2276                 }
2277
2278                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2279                 snprintf(instruction->text, 128,
2280                         "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
2281                         address, opcode);
2282                 return ERROR_OK;
2283         }
2284
2285         /* Load/Store multiple */
2286         if ((opcode & 0xf000) == 0xc000)
2287         {
2288                 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2289         }
2290
2291         /* Conditional branch + SWI */
2292         if ((opcode & 0xf000) == 0xd000)
2293         {
2294                 return evaluate_cond_branch_thumb(opcode, address, instruction);
2295         }
2296
2297         if ((opcode & 0xe000) == 0xe000)
2298         {
2299                 /* Undefined instructions */
2300                 if ((opcode & 0xf801) == 0xe801)
2301                 {
2302                         instruction->type = ARM_UNDEFINED_INSTRUCTION;
2303                         snprintf(instruction->text, 128,
2304                                         "0x%8.8" PRIx32 "  0x%8.8x\t"
2305                                         "UNDEFINED INSTRUCTION",
2306                                         address, opcode);
2307                         return ERROR_OK;
2308                 }
2309                 else
2310                 { /* Branch to offset */
2311                         return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2312                 }
2313         }
2314
2315         LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2316         return -1;
2317 }
2318
2319 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2320                 arm_instruction_t *instruction, char *cp)
2321 {
2322         unsigned offset;
2323         unsigned b21 = 1 << 21;
2324         unsigned b22 = 1 << 22;
2325
2326         /* instead of combining two smaller 16-bit branch instructions,
2327          * Thumb2 uses only one larger 32-bit instruction.
2328          */
2329         offset = opcode & 0x7ff;
2330         offset |= (opcode & 0x03ff0000) >> 5;
2331         if (opcode & (1 << 26)) {
2332                 offset |= 0xff << 23;
2333                 if ((opcode & (1 << 11)) == 0)
2334                         b21 = 0;
2335                 if ((opcode & (1 << 13)) == 0)
2336                         b22 = 0;
2337         } else {
2338                 if (opcode & (1 << 11))
2339                         b21 = 0;
2340                 if (opcode & (1 << 13))
2341                         b22 = 0;
2342         }
2343         offset |= b21;
2344         offset |= b22;
2345
2346
2347         address += 4;
2348         address += offset << 1;
2349
2350         instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2351         instruction->info.b_bl_bx_blx.reg_operand = -1;
2352         instruction->info.b_bl_bx_blx.target_address = address;
2353         sprintf(cp, "%s\t%#8.8" PRIx32,
2354                         (opcode & (1 << 14)) ? "BL" : "B.W",
2355                         address);
2356
2357         return ERROR_OK;
2358 }
2359
2360 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2361                 arm_instruction_t *instruction, char *cp)
2362 {
2363         unsigned offset;
2364         unsigned b17 = 1 << 17;
2365         unsigned b18 = 1 << 18;
2366         unsigned cond = (opcode >> 22) & 0x0f;
2367
2368         offset = opcode & 0x7ff;
2369         offset |= (opcode & 0x003f0000) >> 5;
2370         if (opcode & (1 << 26)) {
2371                 offset |= 0xffff << 19;
2372                 if ((opcode & (1 << 11)) == 0)
2373                         b17 = 0;
2374                 if ((opcode & (1 << 13)) == 0)
2375                         b18 = 0;
2376         } else {
2377                 if (opcode & (1 << 11))
2378                         b17 = 0;
2379                 if (opcode & (1 << 13))
2380                         b18 = 0;
2381         }
2382         offset |= b17;
2383         offset |= b18;
2384
2385         address += 4;
2386         address += offset << 1;
2387
2388         instruction->type = ARM_B;
2389         instruction->info.b_bl_bx_blx.reg_operand = -1;
2390         instruction->info.b_bl_bx_blx.target_address = address;
2391         sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2392                         arm_condition_strings[cond],
2393                         address);
2394
2395         return ERROR_OK;
2396 }
2397
2398 static const char *special_name(int number)
2399 {
2400         char *special = "(RESERVED)";
2401
2402         switch (number) {
2403         case 0:
2404                 special = "apsr";
2405                 break;
2406         case 1:
2407                 special = "iapsr";
2408                 break;
2409         case 2:
2410                 special = "eapsr";
2411                 break;
2412         case 3:
2413                 special = "xpsr";
2414                 break;
2415         case 5:
2416                 special = "ipsr";
2417                 break;
2418         case 6:
2419                 special = "epsr";
2420                 break;
2421         case 7:
2422                 special = "iepsr";
2423                 break;
2424         case 8:
2425                 special = "msp";
2426                 break;
2427         case 9:
2428                 special = "psp";
2429                 break;
2430         case 16:
2431                 special = "primask";
2432                 break;
2433         case 17:
2434                 special = "basepri";
2435                 break;
2436         case 18:
2437                 special = "basepri_max";
2438                 break;
2439         case 19:
2440                 special = "faultmask";
2441                 break;
2442         case 20:
2443                 special = "control";
2444                 break;
2445         }
2446         return special;
2447 }
2448
2449 static int t2ev_hint(uint32_t opcode, uint32_t address,
2450                 arm_instruction_t *instruction, char *cp)
2451 {
2452         const char *mnemonic;
2453
2454         if (opcode & 0x0700) {
2455                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2456                 strcpy(cp, "UNDEFINED");
2457                 return ERROR_OK;
2458         }
2459
2460         if (opcode & 0x00f0) {
2461                 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2462                 return ERROR_OK;
2463         }
2464
2465         switch (opcode & 0x0f) {
2466         case 0:
2467                 mnemonic = "NOP.W";
2468                 break;
2469         case 1:
2470                 mnemonic = "YIELD.W";
2471                 break;
2472         case 2:
2473                 mnemonic = "WFE.W";
2474                 break;
2475         case 3:
2476                 mnemonic = "WFI.W";
2477                 break;
2478         case 4:
2479                 mnemonic = "SEV.W";
2480                 break;
2481         default:
2482                 mnemonic = "HINT.W (UNRECOGNIZED)";
2483                 break;
2484         }
2485         strcpy(cp, mnemonic);
2486         return ERROR_OK;
2487 }
2488
2489 static int t2ev_misc(uint32_t opcode, uint32_t address,
2490                 arm_instruction_t *instruction, char *cp)
2491 {
2492         const char *mnemonic;
2493
2494         switch ((opcode >> 4) & 0x0f) {
2495         case 2:
2496                 mnemonic = "CLREX";
2497                 break;
2498         case 4:
2499                 mnemonic = "DSB";
2500                 break;
2501         case 5:
2502                 mnemonic = "DMB";
2503                 break;
2504         case 6:
2505                 mnemonic = "ISB";
2506                 break;
2507         default:
2508                 return ERROR_INVALID_ARGUMENTS;
2509         }
2510         strcpy(cp, mnemonic);
2511         return ERROR_OK;
2512 }
2513
2514 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2515                 arm_instruction_t *instruction, char *cp)
2516 {
2517         /* permanently undefined */
2518         if ((opcode & 0x07f07000) == 0x07f02000) {
2519                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2520                 strcpy(cp, "UNDEFINED");
2521                 return ERROR_OK;
2522         }
2523
2524         switch ((opcode >> 12) & 0x5) {
2525         case 0x1:
2526         case 0x5:
2527                 return t2ev_b_bl(opcode, address, instruction, cp);
2528         case 0x4:
2529                 goto undef;
2530         case 0:
2531                 if (((opcode >> 23) & 0x07) != 0x07)
2532                         return t2ev_cond_b(opcode, address, instruction, cp);
2533                 if (opcode & (1 << 26))
2534                         goto undef;
2535                 break;
2536         }
2537
2538         switch ((opcode >> 20) & 0x7f) {
2539         case 0x38:
2540         case 0x39:
2541                 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2542                                 (int) (opcode >> 16) & 0x0f);
2543                 return ERROR_OK;
2544         case 0x3a:
2545                 return t2ev_hint(opcode, address, instruction, cp);
2546         case 0x3b:
2547                 return t2ev_misc(opcode, address, instruction, cp);
2548         case 0x3e:
2549         case 0x3f:
2550                 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2551                                 special_name(opcode & 0xff));
2552                 return ERROR_OK;
2553         }
2554
2555 undef:
2556         return ERROR_INVALID_ARGUMENTS;
2557 }
2558
2559 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2560                 arm_instruction_t *instruction, char *cp)
2561 {
2562         char *mnemonic = NULL;
2563         int rn = (opcode >> 16) & 0xf;
2564         int rd = (opcode >> 8) & 0xf;
2565         unsigned immed = opcode & 0xff;
2566         unsigned func;
2567         bool one = false;
2568         char *suffix = "";
2569         char *suffix2 = "";
2570
2571         /* ARMv7-M: A5.3.2 Modified immediate constants */
2572         func = (opcode >> 11) & 0x0e;
2573         if (immed & 0x80)
2574                 func |= 1;
2575         if (opcode & (1 << 26))
2576                 func |= 0x10;
2577
2578         /* "Modified" immediates */
2579         switch (func >> 1) {
2580         case 0:
2581                 break;
2582         case 2:
2583                 immed <<= 8;
2584                 /* FALLTHROUGH */
2585         case 1:
2586                 immed += immed << 16;
2587                 break;
2588         case 3:
2589                 immed += immed << 8;
2590                 immed += immed << 16;
2591                 break;
2592         default:
2593                 immed |= 0x80;
2594                 immed = ror(immed, func);
2595         }
2596
2597         if (opcode & (1 << 20))
2598                 suffix = "S";
2599
2600         switch ((opcode >> 21) & 0xf) {
2601         case 0:
2602                 if (rd == 0xf) {
2603                         instruction->type = ARM_TST;
2604                         mnemonic = "TST";
2605                         one = true;
2606                         suffix = "";
2607                         rd = rn;
2608                 } else {
2609                         instruction->type = ARM_AND;
2610                         mnemonic = "AND";
2611                 }
2612                 break;
2613         case 1:
2614                 instruction->type = ARM_BIC;
2615                 mnemonic = "BIC";
2616                 break;
2617         case 2:
2618                 if (rn == 0xf) {
2619                         instruction->type = ARM_MOV;
2620                         mnemonic = "MOV";
2621                         one = true;
2622                         suffix2 = ".W";
2623                 } else {
2624                         instruction->type = ARM_ORR;
2625                         mnemonic = "ORR";
2626                 }
2627                 break;
2628         case 3:
2629                 if (rn == 0xf) {
2630                         instruction->type = ARM_MVN;
2631                         mnemonic = "MVN";
2632                         one = true;
2633                 } else {
2634                         // instruction->type = ARM_ORN;
2635                         mnemonic = "ORN";
2636                 }
2637                 break;
2638         case 4:
2639                 if (rd == 0xf) {
2640                         instruction->type = ARM_TEQ;
2641                         mnemonic = "TEQ";
2642                         one = true;
2643                         suffix = "";
2644                         rd = rn;
2645                 } else {
2646                         instruction->type = ARM_EOR;
2647                         mnemonic = "EOR";
2648                 }
2649                 break;
2650         case 8:
2651                 if (rd == 0xf) {
2652                         instruction->type = ARM_CMN;
2653                         mnemonic = "CMN";
2654                         one = true;
2655                         suffix = "";
2656                         rd = rn;
2657                 } else {
2658                         instruction->type = ARM_ADD;
2659                         mnemonic = "ADD";
2660                         suffix2 = ".W";
2661                 }
2662                 break;
2663         case 10:
2664                 instruction->type = ARM_ADC;
2665                 mnemonic = "ADC";
2666                 suffix2 = ".W";
2667                 break;
2668         case 11:
2669                 instruction->type = ARM_SBC;
2670                 mnemonic = "SBC";
2671                 break;
2672         case 13:
2673                 if (rd == 0xf) {
2674                         instruction->type = ARM_CMP;
2675                         mnemonic = "CMP";
2676                         one = true;
2677                         suffix = "";
2678                         rd = rn;
2679                 } else {
2680                         instruction->type = ARM_SUB;
2681                         mnemonic = "SUB";
2682                 }
2683                 suffix2 = ".W";
2684                 break;
2685         case 14:
2686                 instruction->type = ARM_RSB;
2687                 mnemonic = "RSB";
2688                 suffix2 = ".W";
2689                 break;
2690         default:
2691                 return ERROR_INVALID_ARGUMENTS;
2692         }
2693
2694         if (one)
2695                 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
2696                                 mnemonic, suffix2 ,rd, immed, immed);
2697         else
2698                 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
2699                                 mnemonic, suffix, suffix2,
2700                                 rd, rn, immed, immed);
2701
2702         return ERROR_OK;
2703 }
2704
2705 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2706                 arm_instruction_t *instruction, char *cp)
2707 {
2708         char *mnemonic = NULL;
2709         int rn = (opcode >> 16) & 0xf;
2710         int rd = (opcode >> 8) & 0xf;
2711         unsigned immed;
2712         bool add = false;
2713         bool is_signed = false;
2714
2715         immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
2716         if (opcode & (1 << 26))
2717                 immed |= (1 << 11);
2718
2719         switch ((opcode >> 20) & 0x1f) {
2720         case 0:
2721                 if (rn == 0xf) {
2722                         add = true;
2723                         goto do_adr;
2724                 }
2725                 mnemonic = "ADDW";
2726                 break;
2727         case 4:
2728                 immed |= (opcode >> 4) & 0xf000;
2729                 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
2730                 return ERROR_OK;
2731         case 0x0a:
2732                 if (rn == 0xf)
2733                         goto do_adr;
2734                 mnemonic = "SUBW";
2735                 break;
2736         case 0x0c:
2737                 /* move constant to top 16 bits of register */
2738                 immed |= (opcode >> 4) & 0xf000;
2739                 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2740                 return ERROR_OK;
2741         case 0x10:
2742         case 0x12:
2743                 is_signed = true;
2744         case 0x18:
2745         case 0x1a:
2746                 /* signed/unsigned saturated add */
2747                 immed = (opcode >> 6) & 0x03;
2748                 immed |= (opcode >> 10) & 0x1c;
2749                 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2750                                 is_signed ? "S" : "U",
2751                                 rd, (int) (opcode & 0x1f) + is_signed, rn,
2752                                 (opcode & (1 << 21)) ? "ASR" : "LSL",
2753                                 immed ? immed : 32);
2754                 return ERROR_OK;
2755         case 0x14:
2756                 is_signed = true;
2757                 /* FALLTHROUGH */
2758         case 0x1c:
2759                 /* signed/unsigned bitfield extract */
2760                 immed = (opcode >> 6) & 0x03;
2761                 immed |= (opcode >> 10) & 0x1c;
2762                 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2763                                 is_signed ? "S" : "U",
2764                                 rd, rn, immed,
2765                                 (int) (opcode & 0x1f) + 1);
2766                 return ERROR_OK;
2767         case 0x16:
2768                 immed = (opcode >> 6) & 0x03;
2769                 immed |= (opcode >> 10) & 0x1c;
2770                 if (rn == 0xf)          /* bitfield clear */
2771                         sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2772                                         rd, immed,
2773                                         (int) (opcode & 0x1f) + 1 - immed);
2774                 else                    /* bitfield insert */
2775                         sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2776                                         rd, rn, immed,
2777                                         (int) (opcode & 0x1f) + 1 - immed);
2778                 return ERROR_OK;
2779         default:
2780                 return ERROR_INVALID_ARGUMENTS;
2781         }
2782
2783         sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2784                         rd, rn, immed, immed);
2785         return ERROR_OK;
2786
2787 do_adr:
2788         address = thumb_alignpc4(address);
2789         if (add)
2790                 address += immed;
2791         else
2792                 address -= immed;
2793         /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2794          * not hiding the pc-relative stuff will sometimes be useful.
2795          */
2796         sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2797         return ERROR_OK;
2798 }
2799
2800 static int t2ev_store_single(uint32_t opcode, uint32_t address,
2801                 arm_instruction_t *instruction, char *cp)
2802 {
2803         unsigned op = (opcode >> 20) & 0xf;
2804         char *size = "";
2805         char *suffix = "";
2806         char *p1 = "";
2807         char *p2 = "]";
2808         unsigned immed;
2809         unsigned rn = (opcode >> 16) & 0x0f;
2810         unsigned rt = (opcode >> 12) & 0x0f;
2811
2812         if (rn == 0xf)
2813                 return ERROR_INVALID_ARGUMENTS;
2814
2815         if (opcode & 0x0800)
2816                 op |= 1;
2817         switch (op) {
2818         /* byte */
2819         case 0x8:
2820         case 0x9:
2821                 size = "B";
2822                 goto imm12;
2823         case 0x1:
2824                 size = "B";
2825                 goto imm8;
2826         case 0x0:
2827                 size = "B";
2828                 break;
2829         /* halfword */
2830         case 0xa:
2831         case 0xb:
2832                 size = "H";
2833                 goto imm12;
2834         case 0x3:
2835                 size = "H";
2836                 goto imm8;
2837         case 0x2:
2838                 size = "H";
2839                 break;
2840         /* word */
2841         case 0xc:
2842         case 0xd:
2843                 goto imm12;
2844         case 0x5:
2845                 goto imm8;
2846         case 0x4:
2847                 break;
2848         /* error */
2849         default:
2850                 return ERROR_INVALID_ARGUMENTS;
2851         }
2852
2853         sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
2854                         size, rt, rn, (int) opcode & 0x0f,
2855                         (int) (opcode >> 4) & 0x03);
2856
2857 imm12:
2858         immed = opcode & 0x0fff;
2859         sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
2860                         size, rt, rn, immed, immed);
2861         return ERROR_OK;
2862
2863 imm8:
2864         immed = opcode & 0x00ff;
2865
2866         switch (opcode & 0x700) {
2867         case 0x600:
2868                 suffix = "T";
2869                 break;
2870         case 0x000:
2871         case 0x200:
2872                 return ERROR_INVALID_ARGUMENTS;
2873         }
2874
2875         /* two indexed modes will write back rn */
2876         if (opcode & 0x100) {
2877                 if (opcode & 0x400)     /* pre-indexed */
2878                         p2 = "]!";
2879                 else {                  /* post-indexed */
2880                         p1 = "]";
2881                         p2 = "";
2882                 }
2883         }
2884
2885         sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
2886                         size, suffix, rt, rn, p1,
2887                         (opcode & 0x200) ? "" : "-",
2888                         immed, p2, immed);
2889         return ERROR_OK;
2890 }
2891
2892 static int t2ev_mul32(uint32_t opcode, uint32_t address,
2893                 arm_instruction_t *instruction, char *cp)
2894 {
2895         int ra = (opcode >> 12) & 0xf;
2896
2897         switch (opcode & 0x007000f0) {
2898         case 0:
2899                 if (ra == 0xf)
2900                         sprintf(cp, "MUL\tr%d, r%d, r%d",
2901                                 (int) (opcode >> 8) & 0xf,
2902                                 (int) (opcode >> 16) & 0xf,
2903                                 (int) (opcode >> 0) & 0xf);
2904                 else
2905                         sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
2906                                 (int) (opcode >> 8) & 0xf,
2907                                 (int) (opcode >> 16) & 0xf,
2908                                 (int) (opcode >> 0) & 0xf, ra);
2909                 break;
2910         case 0x10:
2911                 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
2912                         (int) (opcode >> 8) & 0xf,
2913                         (int) (opcode >> 16) & 0xf,
2914                         (int) (opcode >> 0) & 0xf, ra);
2915                 break;
2916         default:
2917                 return ERROR_INVALID_ARGUMENTS;
2918         }
2919         return ERROR_OK;
2920 }
2921
2922 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
2923                 arm_instruction_t *instruction, char *cp)
2924 {
2925         int op = (opcode >> 4) & 0xf;
2926         char *infix = "MUL";
2927
2928         op += (opcode >> 16) & 0x70;
2929         switch (op) {
2930         case 0x40:
2931         case 0x60:
2932                 infix = "MLA";
2933                 /* FALLTHROUGH */
2934         case 0:
2935         case 0x20:
2936                 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
2937                                 (op & 0x20) ? 'U' : 'S',
2938                                 infix,
2939                                 (int) (opcode >> 12) & 0xf,
2940                                 (int) (opcode >> 8) & 0xf,
2941                                 (int) (opcode >> 16) & 0xf,
2942                                 (int) (opcode >> 0) & 0xf);
2943                 break;
2944         case 0x1f:
2945         case 0x3f:
2946                 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
2947                                 (op & 0x20) ? 'U' : 'S',
2948                                 (int) (opcode >> 8) & 0xf,
2949                                 (int) (opcode >> 16) & 0xf,
2950                                 (int) (opcode >> 0) & 0xf);
2951                 break;
2952         default:
2953                 return ERROR_INVALID_ARGUMENTS;
2954         }
2955
2956         return ERROR_OK;
2957 }
2958
2959 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
2960                 arm_instruction_t *instruction, char *cp)
2961 {
2962         int rn = (opcode >> 16) & 0xf;
2963         int op = (opcode >> 22) & 0x6;
2964         int t = (opcode >> 21) & 1;
2965         unsigned registers = opcode & 0xffff;
2966
2967         if (opcode & (1 << 20))
2968                 op |= 1;
2969
2970         switch (op) {
2971         case 2:
2972                 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
2973                 break;
2974         case 3:
2975                 if (rn == 13 && t)
2976                         sprintf(cp, "POP.W\t");
2977                 else
2978                         sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
2979                 break;
2980         case 4:
2981                 if (rn == 13 && t)
2982                         sprintf(cp, "PUSH.W\t");
2983                 else
2984                         sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
2985                 break;
2986         case 5:
2987                 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
2988                 break;
2989         default:
2990                 return ERROR_INVALID_ARGUMENTS;
2991         }
2992
2993         cp = strchr(cp, 0);
2994         *cp++ = '{';
2995         for (t = 0; registers; t++, registers >>= 1) {
2996                 if ((registers & 1) == 0)
2997                         continue;
2998                 registers &= ~1;
2999                 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3000                 cp = strchr(cp, 0);
3001         }
3002         *cp++ = '}';
3003         *cp++ = 0;
3004
3005         return ERROR_OK;
3006 }
3007
3008 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3009                 arm_instruction_t *instruction, char *cp)
3010 {
3011         int op = (opcode >> 21) & 0xf;
3012         int rd = (opcode >> 8) & 0xf;
3013         int rn = (opcode >> 16) & 0xf;
3014         int type = (opcode >> 4) & 0x3;
3015         int immed = (opcode >> 6) & 0x3;
3016         char *mnemonic;
3017         char *suffix = "";
3018
3019         immed |= (opcode >> 10) & 0x7;
3020         if (opcode & (1 << 21))
3021                 suffix = "S";
3022
3023         switch (op) {
3024         case 0:
3025                 if (rd == 0xf) {
3026                         if (!(opcode & (1 << 21)))
3027                                 return ERROR_INVALID_ARGUMENTS;
3028                         instruction->type = ARM_TST;
3029                         mnemonic = "TST";
3030                         goto two;
3031                 }
3032                 instruction->type = ARM_AND;
3033                 mnemonic = "AND";
3034                 break;
3035         case 1:
3036                 instruction->type = ARM_BIC;
3037                 mnemonic = "BIC";
3038                 break;
3039         case 2:
3040                 if (rn == 0xf) {
3041                         instruction->type = ARM_MOV;
3042                         switch (type) {
3043                         case 0:
3044                                 if (immed == 0) {
3045                                         sprintf(cp, "MOV%s.W\tr%d, r%d",
3046                                                 suffix, rd,
3047                                                 (int) (opcode & 0xf));
3048                                         return ERROR_OK;
3049                                 }
3050                                 mnemonic = "LSL";
3051                                 break;
3052                         case 1:
3053                                 mnemonic = "LSR";
3054                                 break;
3055                         case 2:
3056                                 mnemonic = "ASR";
3057                                 break;
3058                         default:
3059                                 if (immed == 0) {
3060                                         sprintf(cp, "RRX%s.W\tr%d, r%d",
3061                                                 suffix, rd,
3062                                                 (int) (opcode & 0xf));
3063                                         return ERROR_OK;
3064                                 }
3065                                 mnemonic = "ROR";
3066                                 break;
3067                         }
3068                         goto immediate;
3069                 } else {
3070                         instruction->type = ARM_ORR;
3071                         mnemonic = "ORR";
3072                 }
3073                 break;
3074         case 3:
3075                 if (rn == 0xf) {
3076                         instruction->type = ARM_MVN;
3077                         mnemonic = "MVN";
3078                         rn = rd;
3079                         goto two;
3080                 } else {
3081                         // instruction->type = ARM_ORN;
3082                         mnemonic = "ORN";
3083                 }
3084                 break;
3085         case 4:
3086                 if (rd == 0xf) {
3087                         if (!(opcode & (1 << 21)))
3088                                 return ERROR_INVALID_ARGUMENTS;
3089                         instruction->type = ARM_TEQ;
3090                         mnemonic = "TEQ";
3091                         goto two;
3092                 }
3093                 instruction->type = ARM_EOR;
3094                 mnemonic = "EOR";
3095                 break;
3096         case 8:
3097                 if (rd == 0xf) {
3098                         if (!(opcode & (1 << 21)))
3099                                 return ERROR_INVALID_ARGUMENTS;
3100                         instruction->type = ARM_CMN;
3101                         mnemonic = "CMN";
3102                         goto two;
3103                 }
3104                 instruction->type = ARM_ADD;
3105                 mnemonic = "ADD";
3106                 break;
3107         case 0xa:
3108                 instruction->type = ARM_ADC;
3109                 mnemonic = "ADC";
3110                 break;
3111         case 0xb:
3112                 instruction->type = ARM_SBC;
3113                 mnemonic = "SBC";
3114                 break;
3115         case 0xd:
3116                 if (rd == 0xf) {
3117                         if (!(opcode & (1 << 21)))
3118                                 return ERROR_INVALID_ARGUMENTS;
3119                         instruction->type = ARM_CMP;
3120                         mnemonic = "CMP";
3121                         goto two;
3122                 }
3123                 instruction->type = ARM_SUB;
3124                 mnemonic = "SUB";
3125                 break;
3126         case 0xe:
3127                 instruction->type = ARM_RSB;
3128                 mnemonic = "RSB";
3129                 break;
3130         default:
3131                 return ERROR_INVALID_ARGUMENTS;
3132         }
3133
3134         sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3135                 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3136
3137 shift:
3138         cp = strchr(cp, 0);
3139
3140         switch (type) {
3141         case 0:
3142                 if (immed == 0)
3143                         return ERROR_OK;
3144                 suffix = "LSL";
3145                 break;
3146         case 1:
3147                 suffix = "LSR";
3148                 break;
3149         case 2:
3150                 suffix = "ASR";
3151                 break;
3152         case 3:
3153                 if (immed == 0) {
3154                         strcpy(cp, "RRX");
3155                         return ERROR_OK;
3156                 }
3157                 suffix = "ROR";
3158                 break;
3159         }
3160         sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3161         return ERROR_OK;
3162
3163 two:
3164         sprintf(cp, "%s%s.W\tr%d, r%d",
3165                 mnemonic, suffix, rn, (int) (opcode & 0xf));
3166         goto shift;
3167
3168 immediate:
3169         sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3170                 mnemonic, suffix, rd,
3171                 (int) (opcode & 0xf), immed ? immed : 32);
3172         return ERROR_OK;
3173 }
3174
3175 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3176                 arm_instruction_t *instruction, char *cp)
3177 {
3178         char *mnemonic;
3179         char * suffix = "";
3180
3181         if (((opcode >> 4) & 0xf) == 0) {
3182                 switch ((opcode >> 21) & 0x7) {
3183                 case 0:
3184                         mnemonic = "LSL";
3185                         break;
3186                 case 1:
3187                         mnemonic = "LSR";
3188                         break;
3189                 case 2:
3190                         mnemonic = "ASR";
3191                         break;
3192                 case 3:
3193                         mnemonic = "ROR";
3194                         break;
3195                 default:
3196                         return ERROR_INVALID_ARGUMENTS;
3197                 }
3198
3199                 instruction->type = ARM_MOV;
3200                 if (opcode & (1 << 20))
3201                         suffix = "S";
3202                 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3203                                 mnemonic, suffix,
3204                                 (int) (opcode >> 8) & 0xf,
3205                                 (int) (opcode >> 16) & 0xf,
3206                                 (int) (opcode >> 0) & 0xf);
3207
3208         } else if (opcode & (1 << 7)) {
3209                 switch ((opcode >> 20) & 0xf) {
3210                 case 0:
3211                 case 1:
3212                 case 4:
3213                 case 5:
3214                         switch ((opcode >> 4) & 0x3) {
3215                         case 1:
3216                                 suffix = ", ROR #8";
3217                                 break;
3218                         case 2:
3219                                 suffix = ", ROR #16";
3220                                 break;
3221                         case 3:
3222                                 suffix = ", ROR #24";
3223                                 break;
3224                         }
3225                         sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3226                                         (opcode & (1 << 24)) ? 'U' : 'S',
3227                                         (opcode & (1 << 26)) ? 'B' : 'H',
3228                                         (int) (opcode >> 8) & 0xf,
3229                                         (int) (opcode >> 0) & 0xf,
3230                                         suffix);
3231                         break;
3232                 case 8:
3233                 case 9:
3234                 case 0xa:
3235                 case 0xb:
3236                         if (opcode & (1 << 6))
3237                                 return ERROR_INVALID_ARGUMENTS;
3238                         if (((opcode >> 12) & 0xf) != 0xf)
3239                                 return ERROR_INVALID_ARGUMENTS;
3240                         if (!(opcode & (1 << 20)))
3241                                 return ERROR_INVALID_ARGUMENTS;
3242
3243                         switch (((opcode >> 19) & 0x04)
3244                                 | ((opcode >> 4) & 0x3)) {
3245                         case 0:
3246                                 mnemonic = "REV.W";
3247                                 break;
3248                         case 1:
3249                                 mnemonic = "REV16.W";
3250                                 break;
3251                         case 2:
3252                                 mnemonic = "RBIT";
3253                                 break;
3254                         case 3:
3255                                 mnemonic = "REVSH.W";
3256                                 break;
3257                         case 4:
3258                                 mnemonic = "CLZ";
3259                                 break;
3260                         default:
3261                                 return ERROR_INVALID_ARGUMENTS;
3262                         }
3263                         sprintf(cp, "%s\tr%d, r%d",
3264                                         mnemonic,
3265                                         (int) (opcode >> 8) & 0xf,
3266                                         (int) (opcode >> 0) & 0xf);
3267                         break;
3268                 default:
3269                         return ERROR_INVALID_ARGUMENTS;
3270                 }
3271         }
3272
3273         return ERROR_OK;
3274 }
3275
3276 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3277                 arm_instruction_t *instruction, char *cp)
3278 {
3279         int rn = (opcode >> 16) & 0xf;
3280         int immed;
3281
3282         instruction->type = ARM_LDR;
3283
3284         if (rn == 0xf) {
3285                 immed = opcode & 0x0fff;
3286                 if ((opcode & (1 << 23)) == 0)
3287                         immed = -immed;
3288                 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3289                                 (int) (opcode >> 12) & 0xf,
3290                                 thumb_alignpc4(address) + immed);
3291                 return ERROR_OK;
3292         }
3293
3294         if (opcode & (1 << 23)) {
3295                 immed = opcode & 0x0fff;
3296                 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3297                                 (int) (opcode >> 12) & 0xf,
3298                                 rn, immed, immed);
3299                 return ERROR_OK;
3300         }
3301
3302         if (!(opcode & (0x3f << 6))) {
3303                 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3304                                 (int) (opcode >> 12) & 0xf,
3305                                 rn,
3306                                 (int) (opcode >> 0) & 0xf,
3307                                 (int) (opcode >> 4) & 0x3);
3308                 return ERROR_OK;
3309         }
3310
3311
3312         if (((opcode >> 8) & 0xf) == 0xe) {
3313                 immed = opcode & 0x00ff;
3314
3315                 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3316                                 (int) (opcode >> 12) & 0xf,
3317                                 rn, immed, immed);
3318                 return ERROR_OK;
3319         }
3320
3321         if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3322                 char *p1 = "]", *p2 = "";
3323
3324                 if (!(opcode & 0x0500))
3325                         return ERROR_INVALID_ARGUMENTS;
3326
3327                 immed = opcode & 0x00ff;
3328
3329                 /* two indexed modes will write back rn */
3330                 if (opcode & 0x100) {
3331                         if (opcode & 0x400)     /* pre-indexed */
3332                                 p2 = "]!";
3333                         else {                  /* post-indexed */
3334                                 p1 = "]";
3335                                 p2 = "";
3336                         }
3337                 }
3338
3339                 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3340                                 (int) (opcode >> 12) & 0xf,
3341                                 rn, p1,
3342                                 (opcode & 0x200) ? "" : "-",
3343                                 immed, p2, immed);
3344                 return ERROR_OK;
3345         }
3346
3347         return ERROR_INVALID_ARGUMENTS;
3348 }
3349
3350 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3351                 arm_instruction_t *instruction, char *cp)
3352 {
3353         int rn = (opcode >> 16) & 0xf;
3354         int rt = (opcode >> 12) & 0xf;
3355         int op2 = (opcode >> 6) & 0x3f;
3356         unsigned immed;
3357         char *p1 = "]", *p2 = "";
3358         char *mnemonic;
3359
3360         switch ((opcode >> 23) & 0x3) {
3361         case 0:
3362                 if ((rn & rt) == 0xf) {
3363 preload_immediate_t2:
3364                         immed = opcode & 0xfff;
3365 preload_immediate_t1:
3366                         p1 = (opcode & (1 << 21)) ? "W" : "";
3367                         sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3368                                         p1, rn, immed, immed);
3369                         return ERROR_OK;
3370                 }
3371                 if (rn == 0x0f && rt != 0x0f) {
3372 ldrb_literal:
3373                         immed = opcode & 0xfff;
3374                         address = thumb_alignpc4(address);
3375                         if (opcode & (1 << 23))
3376                                 address += immed;
3377                         else
3378                                 address -= immed;
3379                         sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3380                                         rt, address);
3381                         return ERROR_OK;
3382                 }
3383                 if (rn == 0x0f)
3384                         break;
3385                 if ((op2 & 0x3c) == 0x38) {
3386                         immed = opcode & 0xff;
3387                         sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3388                                         rt, rn, immed, immed);
3389                         return ERROR_OK;
3390                 }
3391                 if ((op2 & 0x3c) == 0x30) {
3392                         if (rt == 0x0f) {
3393                                 immed = opcode & 0xff;
3394                                 goto preload_immediate_t1;
3395                         }
3396                         mnemonic = "LDRB";
3397 ldrxb_immediate_t3:
3398                         immed = opcode & 0xff;
3399                         if (opcode & 0x200)
3400                                 immed = -immed;
3401
3402                         /* two indexed modes will write back rn */
3403                         if (opcode & 0x100) {
3404                                 if (opcode & 0x400)     /* pre-indexed */
3405                                         p2 = "]!";
3406                                 else {                  /* post-indexed */
3407                                         p1 = "]";
3408                                         p2 = "";
3409                                 }
3410                         }
3411 ldrxb_immediate_t2:
3412                         sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3413                                         mnemonic, rt, rn, p1,
3414                                         immed, p2, immed);
3415                         return ERROR_OK;
3416                 }
3417                 if ((op2 & 0x24) == 0x24) {
3418                         mnemonic = "LDRB";
3419                         goto ldrxb_immediate_t3;
3420                 }
3421                 if (op2 == 0) {
3422                         int rm = opcode & 0xf;
3423
3424                         if (rt == 0x0f)
3425                                 sprintf(cp, "PLD\t");
3426                         else
3427                                 sprintf(cp, "LDRB.W\tr%d, ", rt);
3428                         immed = (opcode >> 4) & 0x3;
3429                         cp = strchr(cp, 0);
3430                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3431                         return ERROR_OK;
3432                 }
3433                 break;
3434         case 1:
3435                 if (rt == 0xf)
3436                         goto preload_immediate_t2;
3437                 if (rn == 0x0f)
3438                         goto ldrb_literal;
3439                 mnemonic = "LDRB.W";
3440                 immed = opcode & 0xfff;
3441                 goto ldrxb_immediate_t2;
3442         case 2:
3443                 if ((rn & rt) == 0xf) {
3444 pli_immediate:
3445                         immed = opcode & 0xfff;
3446                         address = thumb_alignpc4(address);
3447                         if (opcode & (1 << 23))
3448                                 address += immed;
3449                         else
3450                                 address -= immed;
3451                         sprintf(cp, "PLI\t%#8.8" PRIx32, address);
3452                         return ERROR_OK;
3453                 }
3454                 if (rn == 0xf && rt != 0xf) {
3455 ldrsb_literal:
3456                         immed = opcode & 0xfff;
3457                         address = thumb_alignpc4(address);
3458                         if (opcode & (1 << 23))
3459                                 address += immed;
3460                         else
3461                                 address -= immed;
3462                         sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
3463                         return ERROR_OK;
3464                 }
3465                 if (rn == 0xf)
3466                         break;
3467                 if ((op2 & 0x3c) == 0x38) {
3468                         immed = opcode & 0xff;
3469                         sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %2.2x",
3470                                         rt, rn, immed, immed);
3471                         return ERROR_OK;
3472                 }
3473                 if ((op2 & 0x3c) == 0x30) {
3474                         if (rt == 0xf) {
3475                                 immed = opcode & 0xff;
3476                                 immed = -immed; // pli
3477                                 sprintf(cp, "PLI\t[r%d, #-%d]\t; %2.2x",
3478                                                 rn, immed, immed);
3479                                 return ERROR_OK;
3480                         }
3481                         mnemonic = "LDRSB";
3482                         goto ldrxb_immediate_t3;
3483                 }
3484                 if ((op2 & 0x24) == 0x24) {
3485                         mnemonic = "LDRSB";
3486                         goto ldrxb_immediate_t3;
3487                 }
3488                 if (op2 == 0) {
3489                         int rm = opcode & 0xf;
3490
3491                         if (rt == 0x0f)
3492                                 sprintf(cp, "PLI\t");
3493                         else
3494                                 sprintf(cp, "LDRSB.W\tr%d, ", rt);
3495                         immed = (opcode >> 4) & 0x3;
3496                         cp = strchr(cp, 0);
3497                         sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3498                         return ERROR_OK;
3499                 }
3500                 break;
3501         case 3:
3502                 if (rt == 0xf)
3503                         goto pli_immediate;
3504                 if (rn == 0xf)
3505                         goto ldrsb_literal;
3506                 immed = opcode & 0xfff;
3507                 mnemonic = "LDRSB";
3508                 goto ldrxb_immediate_t2;
3509         }
3510
3511         return ERROR_INVALID_ARGUMENTS;
3512 }
3513
3514 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
3515                 arm_instruction_t *instruction, char *cp)
3516 {
3517         int rn = (opcode >> 16) & 0xf;
3518         int rt = (opcode >> 12) & 0xf;
3519         int op2 = (opcode >> 6) & 0x3f;
3520         char *sign = "";
3521         unsigned immed;
3522
3523         if (rt == 0xf) {
3524                 sprintf(cp, "HINT (UNALLOCATED)");
3525                 return ERROR_OK;
3526         }
3527
3528         if (opcode & (1 << 24))
3529                 sign = "S";
3530
3531         if ((opcode & (1 << 23)) == 0) {
3532                 if (rn == 0xf) {
3533 ldrh_literal:
3534                         immed = opcode & 0xfff;
3535                         address = thumb_alignpc4(address);
3536                         if (opcode & (1 << 23))
3537                                 address += immed;
3538                         else
3539                                 address -= immed;
3540                         sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
3541                                         sign, rt, address);
3542                         return ERROR_OK;
3543                 }
3544                 if (op2 == 0) {
3545                         int rm = opcode & 0xf;
3546
3547                         immed = (opcode >> 4) & 0x3;
3548                         sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
3549                                         sign, rt, rn, rm, immed);
3550                         return ERROR_OK;
3551                 }
3552                 if ((op2 & 0x3c) == 0x38) {
3553                         immed = opcode & 0xff;
3554                         sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
3555                                         sign, rt, rn, immed, immed);
3556                         return ERROR_OK;
3557                 }
3558                 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
3559                         char *p1 = "", *p2 = "]";
3560
3561                         immed = opcode & 0xff;
3562                         if (!(opcode & 0x200))
3563                                 immed = -immed;
3564
3565                         /* two indexed modes will write back rn */
3566                         if (opcode & 0x100) {
3567                                 if (opcode & 0x400)     /* pre-indexed */
3568                                         p2 = "]!";
3569                                 else {                  /* post-indexed */
3570                                         p1 = "]";
3571                                         p2 = "";
3572                                 }
3573                         }
3574                         sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3575                                         sign, rt, rn, p1, immed, p2, immed);
3576                         return ERROR_OK;
3577                 }
3578         } else {
3579                 if (rn == 0xf)
3580                         goto ldrh_literal;
3581
3582                 immed = opcode & 0xfff;
3583                 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
3584                                 sign, *sign ? "" : ".W",
3585                                 rt, rn, immed, immed);
3586                 return ERROR_OK;
3587         }
3588
3589         return ERROR_INVALID_ARGUMENTS;
3590 }
3591
3592 /*
3593  * REVISIT for Thumb2 instructions, instruction->type and friends aren't
3594  * always set.  That means eventual arm_simulate_step() support for Thumb2
3595  * will need work in this area.
3596  */
3597 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
3598 {
3599         int retval;
3600         uint16_t op;
3601         uint32_t opcode;
3602         char *cp;
3603
3604         /* clear low bit ... it's set on function pointers */
3605         address &= ~1;
3606
3607         /* clear fields, to avoid confusion */
3608         memset(instruction, 0, sizeof(arm_instruction_t));
3609
3610         /* read first halfword, see if this is the only one */
3611         retval = target_read_u16(target, address, &op);
3612         if (retval != ERROR_OK)
3613                 return retval;
3614
3615         switch (op & 0xf800) {
3616         case 0xf800:
3617         case 0xf000:
3618         case 0xe800:
3619                 /* 32-bit instructions */
3620                 instruction->instruction_size = 4;
3621                 opcode = op << 16;
3622                 retval = target_read_u16(target, address + 2, &op);
3623                 if (retval != ERROR_OK)
3624                         return retval;
3625                 opcode |= op;
3626                 instruction->opcode = opcode;
3627                 break;
3628         default:
3629                 /* 16-bit:  Thumb1 + IT + CBZ/CBNZ + ... */
3630                 return thumb_evaluate_opcode(op, address, instruction);
3631         }
3632
3633         snprintf(instruction->text, 128,
3634                         "0x%8.8" PRIx32 "  0x%8.8" PRIx32 "\t",
3635                         address, opcode);
3636         cp = strchr(instruction->text, 0);
3637         retval = ERROR_FAIL;
3638
3639         /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3640         if ((opcode & 0x1a008000) == 0x10000000)
3641                 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3642
3643         /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3644         else if ((opcode & 0x1a008000) == 0x12000000)
3645                 retval = t2ev_data_immed(opcode, address, instruction, cp);
3646
3647         /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3648         else if ((opcode & 0x18008000) == 0x10008000)
3649                 retval = t2ev_b_misc(opcode, address, instruction, cp);
3650
3651         /* ARMv7-M: A5.3.5 Load/store multiple */
3652         else if ((opcode & 0x1e400000) == 0x08000000)
3653                 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3654
3655         /* ARMv7-M: A5.3.7 Load word */
3656         else if ((opcode & 0x1f700000) == 0x18500000)
3657                 retval = t2ev_load_word(opcode, address, instruction, cp);
3658
3659         /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
3660         else if ((opcode & 0x1e700000) == 0x18300000)
3661                 retval = t2ev_load_halfword(opcode, address, instruction, cp);
3662
3663         /* ARMv7-M: A5.3.9 Load byte, memory hints */
3664         else if ((opcode & 0x1e700000) == 0x18100000)
3665                 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
3666
3667         /* ARMv7-M: A5.3.10 Store single data item */
3668         else if ((opcode & 0x1f100000) == 0x18000000)
3669                 retval = t2ev_store_single(opcode, address, instruction, cp);
3670
3671         /* ARMv7-M: A5.3.11 Data processing (shifted register) */
3672         else if ((opcode & 0x1e000000) == 0x0a000000)
3673                 retval = t2ev_data_shift(opcode, address, instruction, cp);
3674
3675         /* ARMv7-M: A5.3.12 Data processing (register)
3676          * and      A5.3.13 Miscellaneous operations
3677          */
3678         else if ((opcode & 0x1f000000) == 0x1a000000)
3679                 retval = t2ev_data_reg(opcode, address, instruction, cp);
3680
3681         /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3682         else if ((opcode & 0x1f800000) == 0x1b000000)
3683                 retval = t2ev_mul32(opcode, address, instruction, cp);
3684
3685         /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3686         else if ((opcode & 0x1f800000) == 0x1b800000)
3687                 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3688
3689         /* FIXME decode more 32-bit instructions */
3690
3691         if (retval == ERROR_OK)
3692                 return retval;
3693
3694         if (retval == ERROR_INVALID_ARGUMENTS) {
3695                 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3696                 strcpy(cp, "UNDEFINED OPCODE");
3697                 return ERROR_OK;
3698         }
3699
3700         LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
3701                         opcode);
3702
3703         strcpy(cp, "(32-bit Thumb2 ...)");
3704         return ERROR_OK;
3705 }
3706
3707 int arm_access_size(arm_instruction_t *instruction)
3708 {
3709         if ((instruction->type == ARM_LDRB)
3710                 || (instruction->type == ARM_LDRBT)
3711                 || (instruction->type == ARM_LDRSB)
3712                 || (instruction->type == ARM_STRB)
3713                 || (instruction->type == ARM_STRBT))
3714         {
3715                 return 1;
3716         }
3717         else if ((instruction->type == ARM_LDRH)
3718                 || (instruction->type == ARM_LDRSH)
3719                 || (instruction->type == ARM_STRH))
3720         {
3721                 return 2;
3722         }
3723         else if ((instruction->type == ARM_LDR)
3724                 || (instruction->type == ARM_LDRT)
3725                 || (instruction->type == ARM_STR)
3726                 || (instruction->type == ARM_STRT))
3727         {
3728                 return 4;
3729         }
3730         else if ((instruction->type == ARM_LDRD)
3731                 || (instruction->type == ARM_STRD))
3732         {
3733                 return 8;
3734         }
3735         else
3736         {
3737                 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
3738                 return 0;
3739         }
3740 }