1 /* radare - LGPL - Copyright 2010-2018 - pancake */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <r_util.h>
8 #include "armass16_const.h"
9
10 // TODO: only lo registers accessible in thumb arm
11
12 typedef struct {
13 ut64 off;
14 ut32 o;
15 char op[128];
16 char opstr[128];
17 char *a[16]; /* only 15 arguments can be used! */
18 } ArmOpcode;
19
20 typedef struct {
21 const char *name;
22 int code;
23 int type;
24 } ArmOp;
25
26 enum {
27 TYPE_MOV = 1,
28 TYPE_TST = 2,
29 TYPE_SWI = 3,
30 TYPE_HLT = 4,
31 TYPE_BRA = 5,
32 TYPE_BRR = 6,
33 TYPE_ARI = 7,
34 TYPE_IMM = 8,
35 TYPE_MEM = 9,
36 TYPE_BKP = 10,
37 TYPE_SWP = 11,
38 TYPE_MOVW = 12,
39 TYPE_MOVT = 13,
40 TYPE_UDF = 14,
41 TYPE_SHFT = 15,
42 TYPE_COPROC = 16,
43 TYPE_ENDIAN = 17,
44 TYPE_MUL = 18,
45 TYPE_CLZ = 19,
46 TYPE_REV = 20,
47 TYPE_NEG = 21
48 };
49
strcmpnull(const char * a,const char * b)50 static int strcmpnull(const char *a, const char *b) {
51 return (a && b) ? strcmp (a, b) : -1;
52 }
53
54 // static const char *const arm_shift[] = {"lsl", "lsr", "asr", "ror"};
55
56 static ArmOp ops[] = {
57 { "adc", 0xa000, TYPE_ARI },
58 { "adcs", 0xb000, TYPE_ARI },
59 { "adds", 0x9000, TYPE_ARI },
60 { "add", 0x8000, TYPE_ARI },
61 { "bkpt", 0x2001, TYPE_BKP },
62 { "subs", 0x5000, TYPE_ARI },
63 { "sub", 0x4000, TYPE_ARI },
64 { "sbcs", 0xd000, TYPE_ARI },
65 { "sbc", 0xc000, TYPE_ARI },
66 { "rsb", 0x6000, TYPE_ARI },
67 { "rsbs", 0x7000, TYPE_ARI },
68 { "rsc", 0xe000, TYPE_ARI },
69 { "rscs", 0xf000, TYPE_ARI },
70 { "bic", 0x0000c0e1, TYPE_ARI },
71
72 { "udf", 0xf000f000, TYPE_UDF },
73
74 { "push", 0x2d09, TYPE_IMM },
75 { "pop", 0xbd08, TYPE_IMM },
76
77 { "cps", 0xb1, TYPE_IMM },
78 { "nop", 0xa0e1, -1 },
79
80 { "ldrex", 0x9f0f9000, TYPE_MEM },
81 { "ldr", 0x9000, TYPE_MEM },
82
83 { "strexh", 0x900fe000, TYPE_MEM },
84 { "strexb", 0x900fc000, TYPE_MEM },
85 { "strex", 0x900f8000, TYPE_MEM },
86 { "strbt", 0x0000e0e4, TYPE_MEM },
87 { "strb", 0x0000c0e5, TYPE_MEM },
88 { "strd", 0xf000c0e1, TYPE_MEM },
89 { "strh", 0xb00080e1, TYPE_MEM },
90 { "str", 0x8000, TYPE_MEM },
91
92 { "blx", 0x30ff2fe1, TYPE_BRR },
93 { "bx", 0x10ff2fe1, TYPE_BRR },
94
95 { "bl", 0xb, TYPE_BRA },
96 // bx/blx - to register, b, bne,.. justjust offset
97 // 2220: e12fff1e bx lr
98 // 2224: e12fff12 bx r2
99 // 2228: e12fff13 bx r3
100
101 //{ "bx", 0xb, TYPE_BRA },
102 { "b", 0xa, TYPE_BRA },
103
104 //{ "mov", 0x3, TYPE_MOV },
105 //{ "mov", 0x0a3, TYPE_MOV },
106 { "movw", 0x3, TYPE_MOVW },
107 { "movt", 0x4003, TYPE_MOVT },
108 { "mov", 0xa001, TYPE_MOV },
109 { "mvn", 0xe000, TYPE_MOV },
110 { "svc", 0xf, TYPE_SWI }, // ???
111 { "hlt", 0x70000001, TYPE_HLT }, // ???u
112
113 { "mul", 0x900000e0, TYPE_MUL},
114 { "smull", 0x9000c0e0, TYPE_MUL},
115 { "umull", 0x900080e0, TYPE_MUL},
116 { "smlal", 0x9000e0e0, TYPE_MUL},
117 { "smlabb", 0x800000e1, TYPE_MUL},
118 { "smlabt", 0xc00000e1, TYPE_MUL},
119 { "smlatb", 0xa00000e1, TYPE_MUL},
120 { "smlatt", 0xe00000e1, TYPE_MUL},
121 { "smlawb", 0x800020e1, TYPE_MUL},
122 { "smlawt", 0xc00020e1, TYPE_MUL},
123
124
125 { "ands", 0x1000, TYPE_ARI },
126 { "and", 0x0000, TYPE_ARI },
127 { "eors", 0x3000, TYPE_ARI },
128 { "eor", 0x2000, TYPE_ARI },
129 { "orrs", 0x9001, TYPE_ARI },
130 { "orr", 0x8001, TYPE_ARI },
131
132 { "cmp", 0x5001, TYPE_TST },
133 { "swp", 0xe1, TYPE_SWP },
134 { "cmn", 0x0, TYPE_TST },
135 { "teq", 0x0, TYPE_TST },
136 { "tst", 0xe1, TYPE_TST },
137
138 {"lsr", 0x3000a0e1, TYPE_SHFT},
139 {"asr", 0x5000a0e1, TYPE_SHFT},
140 {"lsl", 0x1000a0e1, TYPE_SHFT},
141 {"ror", 0x7000a0e1, TYPE_SHFT},
142
143 {"rev16", 0xb00fbf06, TYPE_REV},
144 {"revsh", 0xb00fff06, TYPE_REV},
145 {"rev", 0x300fbf06, TYPE_REV},
146 {"rbit", 0x300fff06, TYPE_REV},
147
148 {"mrc", 0x100010ee, TYPE_COPROC},
149 {"setend", 0x000001f1, TYPE_ENDIAN},
150 { "clz", 0x000f6f01, TYPE_CLZ},
151 { "neg", 0x7000, TYPE_NEG },
152
153 { NULL }
154 };
155
156 static const ut64 M_BIT = 0x1;
157 static const ut64 S_BIT = 0x2;
158 static const ut64 C_BITS = 0x3c;
159 static const ut64 DOTN_BIT = 0x40;
160 static const ut64 DOTW_BIT = 0x80;
161 static const ut64 L_BIT = 0x100;
162 static const ut64 X_BIT = 0x200;
163 static const ut64 TWO_BIT = 0x400;
164 static const ut64 IE_BIT = 0x800;
165 static const ut64 ID_BIT = 0x1000;
166 static const ut64 EA_BIT = 0x2000;
167 static const ut64 FD_BIT = 0x4000;
168 static const ut64 T_BIT = 0x8000;
169 static const ut64 B_BIT = 0x10000;
170 static const ut64 H_BIT = 0x20000;
171 static const ut64 D_BIT = 0x40000;
172 static const ut64 W_BIT = 0x80000;
173 static const ut64 EIGHT_BIT = 0x100000;
174 static const ut64 SIXTEEN_BIT = 0x200000;
175 static const ut64 BB_BIT = 0x400000;
176 static const ut64 BT_BIT = 0x800000;
177 static const ut64 TB_BIT = 0x1000000;
178 static const ut64 TT_BIT = 0x2000000;
179 static const ut64 R_BIT = 0x4000000;
180 static const ut64 IA_BIT = 0x8000000;
181 static const ut64 DB_BIT = 0x10000000;
182 static const ut64 SH_BIT = 0x20000000;
183 static const ut64 WB_BIT = 0x40000000;
184 static const ut64 WT_BIT = 0x80000000;
185 static const ut64 C_MATCH_BIT = 0x100000000;
186
parse_hints(char * input)187 static char *parse_hints(char *input) {
188 if (!strcmpnull (input, "unst")) {
189 return "6";
190 }
191 if (!strcmpnull (input, "un")) {
192 return "7";
193 }
194 if (!strcmpnull (input, "st")) {
195 return "14";
196 }
197 if (!strcmpnull (input, "sy")) {
198 return "15";
199 }
200 return "-1";
201 }
202
iflag(char * input)203 static st8 iflag(char *input) {
204 st8 res = 0;
205 r_str_case (input, false);
206
207 for (; *input; input++) {
208 switch (*input) {
209 case 'a':
210 res |= 0x4;
211 break;
212 case 'i':
213 res |= 0x2;
214 break;
215 case 'f':
216 res |= 0x1;
217 break;
218 default:
219 return -1;
220 }
221 }
222 return res;
223 }
224
cqcheck(char ** input)225 static ut64 cqcheck(char **input) {
226 ut64 res = 0;
227 int i;
228 ut8 offset = 0;
229
230 const char *conds[] = {
231 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
232 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
233 };
234 for (i = 0; conds[i]; i++) {
235 if (r_str_startswith (*input, conds[i])) {
236 res |= C_MATCH_BIT;
237 res |= i << 2;
238 *input += 2;
239 offset += 2;
240 break;
241 }
242 }
243 if (r_str_startswith (*input, ".n")) {
244 res |= DOTN_BIT;
245 *input += 2;
246 offset += 2;
247 } else
248 if (r_str_startswith (*input, ".w")) {
249 res |= DOTW_BIT;
250 *input += 2;
251 offset += 2;
252 }
253
254 if (**input == '\0') {
255 return res;
256 }
257 *input -= offset;
258 return 0;
259 }
260
opmask(char * input,char * opcode,ut64 allowed_mask)261 static ut64 opmask(char *input, char *opcode, ut64 allowed_mask) {
262 ut64 res = 0;
263
264 r_str_case (input, false);
265 if (strlen (opcode) > strlen (input)) {
266 return 0;
267 }
268 if (r_str_startswith (input, opcode)) {
269 input += strlen (opcode);
270 res |= M_BIT;
271 res |= cqcheck (&input);
272
273 if ((*input == 's') && (S_BIT & allowed_mask)) {
274 res |= S_BIT;
275 input++;
276 }
277 res |= cqcheck (&input);
278
279 if ((r_str_startswith (input, "wb")) && (WB_BIT & allowed_mask)) {
280 res |= WB_BIT;
281 input += 2;
282 }
283 if ((r_str_startswith (input, "wt")) && (WT_BIT & allowed_mask)) {
284 res |= WT_BIT;
285 input += 2;
286 }
287 res |= cqcheck (&input);
288 if ((r_str_startswith (input, "db")) && (DB_BIT & allowed_mask)) {
289 res |= DB_BIT;
290 input += 2;
291 }
292 if ((r_str_startswith (input, "ea")) && (EA_BIT & allowed_mask)) {
293 res |= EA_BIT;
294 input += 2;
295 }
296 if ((r_str_startswith (input, "ia")) && (IA_BIT & allowed_mask)) {
297 res |= IA_BIT;
298 input += 2;
299 }
300 if ((r_str_startswith (input, "fd")) && (FD_BIT & allowed_mask)) {
301 res |= FD_BIT;
302 input += 2;
303 }
304 res |= cqcheck (&input);
305 if ((*input == 'l') && (L_BIT & allowed_mask)) {
306 res |= L_BIT;
307 input++;
308 }
309 res |= cqcheck (&input);
310 if ((r_str_startswith (input, "bb")) && (BB_BIT & allowed_mask)) {
311 res |= BB_BIT;
312 input += 2;
313 }
314 if ((r_str_startswith (input, "tt")) && (TT_BIT & allowed_mask)) {
315 res |= TT_BIT;
316 input += 2;
317 }
318 if ((r_str_startswith (input, "bt")) && (BT_BIT & allowed_mask)) {
319 res |= BT_BIT;
320 input += 2;
321 }
322 if ((r_str_startswith (input, "tb")) && (TB_BIT & allowed_mask)) {
323 res |= TB_BIT;
324 input += 2;
325 }
326 res |= cqcheck (&input);
327 if ((*input == 'w') && (W_BIT & allowed_mask)) {
328 res |= W_BIT;
329 input++;
330 }
331 if ((*input == 'b') && (B_BIT & allowed_mask)) {
332 res |= B_BIT;
333 input++;
334 } else
335 if ((*input == 'h') && (H_BIT & allowed_mask)) {
336 res |= H_BIT;
337 input++;
338 } else
339 if ((*input == 'd') && (D_BIT & allowed_mask)) {
340 res |= D_BIT;
341 input++;
342 }
343 if ((*input == 't') && (T_BIT & allowed_mask)) {
344 res |= T_BIT;
345 input++;
346 }
347 if ((*input == 's') && (S_BIT & allowed_mask)) {
348 res |= S_BIT;
349 input++;
350 }
351 res |= cqcheck (&input);
352 if ((*input == 'r') && (R_BIT & allowed_mask)) {
353 res |= R_BIT;
354 input++;
355 }
356 res |= cqcheck (&input);
357 if ((*input == '2') && (TWO_BIT & allowed_mask)) {
358 res |= TWO_BIT;
359 input++;
360 }
361 if ((*input == '8') && (EIGHT_BIT & allowed_mask)) {
362 res |= EIGHT_BIT;
363 input++;
364 }
365 if ((r_str_startswith (input, "16")) && (SIXTEEN_BIT & allowed_mask)) {
366 res |= SIXTEEN_BIT;
367 input += 2;
368 }
369 res |= cqcheck (&input);
370 if ((*input == 'l') && (L_BIT & allowed_mask)) {
371 res |= L_BIT;
372 input++;
373 }
374 if ((*input == 'x') && (X_BIT & allowed_mask)) {
375 res |= X_BIT;
376 input++;
377 }
378 res |= cqcheck (&input);
379 if ((r_str_startswith (input, "id")) && (ID_BIT & allowed_mask)) {
380 res |= ID_BIT;
381 input += 2;
382 }
383 if ((r_str_startswith (input, "ie")) && (IE_BIT & allowed_mask)) {
384 res |= IE_BIT;
385 input += 2;
386 }
387 res |= cqcheck (&input);
388 if ((r_str_startswith (input, "sh")) && (SH_BIT & allowed_mask)) {
389 res |= SH_BIT;
390 input += 2;
391 }
392 res |= cqcheck (&input);
393 if (!(res & C_MATCH_BIT)) {
394 res |= 15 << 2; // nv is the default condition
395 }
396 if (*input == 0) {
397 return res;
398 }
399 }
400 return 0;
401 }
402
itmask(char * input)403 static ut32 itmask(char *input) {
404 ut32 res = 0;
405 ut32 i, length;
406 r_str_case (input, false);
407 if (2 > strlen (input)) {
408 return 0;
409 }
410 if (r_str_startswith (input, "it")) {
411 input += 2;
412 res |= 1; // matched
413 if (strlen(input) > 3) {
414 return 0;
415 }
416 res |= (strlen (input) & 0x3) << 4;
417 length = strlen (input);
418 for (i = 0; i < length; i++, input++ ) {
419 if (*input == 'e') {
420 res |= 1 << (3 - i);
421 continue;
422 }
423 if (*input == 't') {
424 continue;
425 }
426 return 0;
427 }
428 return res;
429 }
430 return 0;
431 }
432
433 static bool err;
434 //decode str as number
getnum(const char * str)435 static ut64 getnum(const char *str) {
436 char *endptr;
437 err = false;
438 ut64 val;
439
440 if (!str) {
441 err = true;
442 return 0;
443 }
444 while (*str == '$' || *str == '#') {
445 str++;
446 }
447 val = strtoll (str, &endptr, 0);
448 if (str != endptr && *endptr == '\0') {
449 return val;
450 }
451 err = true;
452 return 0;
453 }
454
getnumbang(const char * str)455 static ut64 getnumbang(const char *str) {
456 ut64 res;
457
458 if (!str || !*str || !r_str_endswith (str, "!")) {
459 err = true;
460 return 0;
461 }
462 char *temp = r_str_ndup (str, strlen (str) - 1);
463 if (!temp) {
464 return -1;
465 }
466 err = false;
467 res = getnum (temp);
468 free (temp);
469 return res; // err propagates
470 }
471
getimmed8(const char * str)472 static ut32 getimmed8(const char *str) {
473 ut32 num = getnum (str);
474 if (err) {
475 return 0;
476 }
477 ut32 rotate;
478 if (num <= 0xff) {
479 return num;
480 } else {
481 for (rotate = 1; rotate < 16; rotate++) {
482 // rol 2
483 num = ((num << 2) | (num >> 30));
484 if (num == (num & 0xff)) {
485 return (num | (rotate << 8));
486 }
487 }
488 err = 1;
489 return 0;
490 }
491 }
492
firstsigdigit(ut32 num)493 static st32 firstsigdigit (ut32 num) {
494 st32 f = -1;
495 st32 b = -1;
496 ut32 forwardmask = 0x80000000;
497 ut32 backwardmask = 0x1;
498 ut32 i;
499 for (i = 0; i < 32; i++ ) {
500 if ( (forwardmask & num) && (f == -1)) {
501 f = i;
502 }
503 if ( (backwardmask & num) && (b == -1)) {
504 b = 32-i;
505 }
506 forwardmask >>= 1;
507 backwardmask <<= 1;
508 }
509
510 if ((b-f) < 9) {
511 return f;
512 }
513 return -1;
514 }
515
getthbimmed(st32 number)516 static ut32 getthbimmed(st32 number) {
517 ut32 res = 0;
518 if (number < 0) {
519 res |= 1 << 18;
520 }
521 number >>= 1;
522 res |= (( number & 0xff) << 8);
523 number >>= 8;
524 res |= ( number & 0x07);
525 number >>= 3;
526 res |= (( number & 0xff) << 24);
527 number >>= 8;
528 res |= (( number & 0x3) << 16);
529 number >>= 2;
530 if (number < 0) {
531 res |= (( number & 0x1) << 3);
532 number >>= 1;
533 res |= (( number & 0x1) << 5);
534 } else {
535 res |= ((!( number & 0x1)) << 3);
536 number >>= 1;
537 res |= ((!( number & 0x1)) << 5);
538 }
539 return res;
540 }
541
getthzeroimmed12(ut32 number)542 static ut32 getthzeroimmed12(ut32 number) {
543 ut32 res = 0;
544 res |= (number & 0x800) << 7;
545 res |= (number & 0x700) >> 4;
546 res |= (number & 0x0ff) << 8;
547 return res;
548 }
549
getthzeroimmed16(ut32 number)550 static ut32 getthzeroimmed16(ut32 number) {
551 ut32 res = 0;
552 res |= (number & 0xf000) << 12;
553 res |= (number & 0x0800) << 7;
554 res |= (number & 0x0700) >> 4;
555 res |= (number & 0x00ff) << 8;
556 return res;
557 }
558
getthimmed12(const char * str)559 static ut32 getthimmed12(const char *str) {
560 ut64 num = getnum (str);
561 if (err) {
562 return 0;
563 }
564
565 st32 FSD = 0;
566 ut64 result = 0;
567 if (num <= 0xff) {
568 return num << 8;
569 } else if ( ((num & 0xff00ff00) == 0) && ((num & 0x00ff0000) == ((num & 0x000000ff) << 16)) ) {
570 result |= (num & 0x000000ff) << 8;
571 result |= 0x00000010;
572 return result;
573 } else if ( ((num & 0x00ff00ff) == 0) && ((num & 0xff000000) == ((num & 0x0000ff00) << 16)) ) {
574 result |= num & 0x0000ff00;
575 result |= 0x00000020;
576 return result;
577 } else if ( ((num & 0xff000000) == ((num & 0x00ff0000) << 8)) && ((num & 0xff000000) == ((num & 0x0000ff00) << 16)) && ((num &0xff000000) == ((num & 0x000000ff) << 24)) ) {
578 result |= num & 0x0000ff00;
579 result |= 0x00000030;
580 return result;
581 } else {
582 FSD = firstsigdigit(num);
583 if (FSD != -1) {
584 result |= ((num >> (24-FSD)) & 0x0000007f) << 8;
585 result |= ((8+FSD) & 0x1) << 15;
586 result |= ((8+FSD) & 0xe) << 3;
587 result |= ((8+FSD) & 0x10) << 14;
588 return result;
589 } else {
590 err = true;
591 return 0;
592 }
593 }
594 }
595
getrange(char * s)596 static char *getrange(char *s) {
597 char *p = NULL;
598 while (s && *s) {
599 if (*s == ',') {
600 p = s+1;
601 *p=0;
602 }
603 if (*s == '[' || *s == ']') {
604 memmove (s, s + 1, strlen (s + 1) + 1);
605 }
606 if (*s == '}') {
607 *s = 0;
608 }
609 s++;
610 }
611 while (p && *p == ' ') {
612 p++;
613 }
614 return p;
615 }
616
617 //ret register #; -1 if failed
getreg(const char * str)618 static int getreg(const char *str) {
619 int i;
620 char *ep;
621 const char *aliases[] = { "sl", "fp", "ip", "sp", "lr", "pc", NULL };
622 if (!str || !*str) {
623 return -1;
624 }
625 if (*str == 'r') {
626 int reg = strtol (str + 1, &ep, 10);
627 if ((ep[0] != '\0') || (str[1] == '\0')) {
628 return -1;
629 }
630 if (reg < 16 && reg >= 0) {
631 return reg;
632 }
633 }
634 for (i=0; aliases[i]; i++) {
635 if (!strcmpnull (str, aliases[i])) {
636 return 10 + i;
637 }
638 }
639 return -1;
640 }
641
642
getlistmask(char * input)643 static st32 getlistmask(char *input) {
644 st32 tempres, res = 0;
645 int i, j, start, end;
646 char *temp = NULL;
647 char *otemp = NULL;
648 char *temp2 = malloc (strlen (input) + 1);
649 if (!temp2) {
650 res = -1;
651 goto end;
652 }
653 temp = (char *)malloc (strlen (input) + 1);
654 if (!temp) {
655 res = -1;
656 goto end;
657 }
658 otemp = temp;
659 while (*input != '\0') {
660 for (; *input == ' '; input++) {
661 ;
662 }
663 for (i = 0; input[i] != ',' && input[i] != '\0'; i++) {
664 ;
665 }
666 r_str_ncpy (temp, input, i + 1);
667
668 input += i;
669 if (*input != '\0') {
670 input++;
671 }
672
673 for (i = 0; temp[i] != '-' && temp[i] != '\0'; i++) {
674 ;
675 }
676 if (i == strlen (temp)) {
677 tempres = getreg (temp);
678 if (tempres == -1 || tempres > 15) {
679 res = -1;
680 goto end;
681 }
682 res |= 1 << tempres;
683 } else {
684 strncpy (temp2, temp, i);
685 temp2[i] = 0;
686 temp += i + 1;
687 start = getreg (temp2);
688 if (start == -1 || start > 15) {
689 res = -1;
690 goto end;
691 }
692 end = getreg (temp);
693 if (end == -1 || end > 15) {
694 res = -1;
695 goto end;
696 }
697
698 for (j = start; j <= end; j++ ) {
699 res |= 1 << j;
700 }
701 }
702 }
703 end:
704 free (otemp);
705 free (temp2);
706 return res;
707 }
708
getregmemstart(const char * input)709 static st32 getregmemstart(const char *input) {
710 if ((strlen (input) < 1) || (!(*input == '['))) {
711 return -1;
712 }
713 input++;
714 return getreg (input);
715 }
716
getregmemstartend(const char * input)717 static st32 getregmemstartend(const char *input) {
718 st32 res;
719 if (!input || (strlen (input) < 2) || (*input != '[') || !r_str_endswith (input, "]")) {
720 return -1;
721 }
722 input++;
723 char *temp = r_str_ndup (input, strlen (input) - 1);
724 if (!temp) {
725 return -1;
726 }
727 res = getreg (temp);
728 free (temp);
729 return res;
730 }
731
getregmemend(const char * input)732 static st32 getregmemend(const char *input) {
733 st32 res;
734 if (!input || !*input || !r_str_endswith (input, "]")) {
735 return -1;
736 }
737
738 char *temp = r_str_ndup (input, strlen (input) - 1);
739 if (!temp) {
740 return -1;
741 }
742 res = getreg (temp);
743 free (temp);
744 return res;
745 }
746
getreglist(const char * input)747 static st32 getreglist(const char *input) {
748 st32 res;
749
750 if (!input || (strlen (input) < 2) || (*input != '{') || !r_str_endswith (input, "}")) {
751 return -1;
752 }
753 if (*input) {
754 input++;
755 }
756 char *temp = r_str_ndup (input, strlen (input) - 1);
757 if (!temp) {
758 return -1;
759 }
760 res = getlistmask (temp);
761 free (temp);
762 return res;
763 }
764
getnummemend(const char * input)765 static st32 getnummemend (const char *input) {
766 st32 res;
767 err = false;
768 if (!input || !*input || !r_str_endswith (input, "]")) {
769 err = true;
770 return -1;
771 }
772 char *temp = r_str_ndup (input, strlen (input) - 1);
773 if (!temp) {
774 err = true;
775 return -1;
776 }
777 res = getnum (temp);
778 free (temp);
779 return res;
780 }
781
getnummemendbang(const char * input)782 static st32 getnummemendbang (const char *input) {
783 st32 res;
784 err = false;
785 if (!input || (strlen (input) < 2) || (input[strlen(input) - 2] != ']' || !r_str_endswith (input, "!"))) {
786 err = true;
787 return 0;
788 }
789 char *temp = r_str_ndup (input, strlen (input) - 2);
790 if (!temp) {
791 err = true;
792 return 0;
793 }
794 res = getnum (temp);
795 free (temp);
796 return res;
797 }
798
getregmembang(const char * input)799 static st32 getregmembang(const char *input) {
800 st32 res;
801 if (!input || !*input || !r_str_endswith (input, "!")) {
802 return -1;
803 }
804 char *temp = r_str_ndup (input, strlen (input) - 1);
805 if (!temp) {
806 return -1;
807 }
808 res = getreg (temp);
809 free (temp);
810 return res;
811 }
812
getcoproc(const char * str)813 static int getcoproc(const char *str) {
814 char *ep;
815 if (!str || !*str) {
816 return -1;
817 }
818 if (*str == 'p') {
819 int coproc = strtol (str + 1, &ep, 10);
820 if ((ep[0] != '\0') || (str[1] == '\0')) {
821 return -1;
822 }
823 if (coproc < 16 && coproc >= 0) {
824 return coproc;
825 }
826 }
827 return -1;
828 }
829
getcoprocreg(const char * str)830 static int getcoprocreg(const char *str) {
831 char *ep;
832
833 if (!str || !*str) {
834 return -1;
835 }
836 if (r_str_startswith (str, "c")) {
837 int reg = strtol (str + 1, &ep, 10);
838 if ((ep[0] != '\0') || (str[1] == '\0')) {
839 return -1;
840 }
841 if (reg < 16 && reg >= 0) {
842 return reg;
843 }
844 }
845 return -1;
846 }
847
interpret_msrbank(char * str,ut8 * spsr)848 static ut8 interpret_msrbank (char *str, ut8 *spsr) {
849 const char fields[] = {'c', 'x', 's', 'f', 0};
850 int res = 0;
851 int i, j;
852 if (r_str_startswith (str, "spsr_")) {
853 *spsr = 1;
854 } else {
855 *spsr = 0;
856 }
857
858 if (r_str_startswith (str, "apsr_")) {
859 if (!(strcmp (str+5, "g"))) {
860 return 0x4;
861 }
862 if (!(strcmp (str+5, "nzcvq"))) {
863 return 0x8;
864 }
865 if (!(strcmp (str+5, "nzcvqg"))) {
866 return 0xc;
867 }
868 }
869 if (r_str_startswith (str, "cpsr_") || r_str_startswith (str, "spsr_")) {
870 for (i = 0; str[5+i]; i++) {
871 for (j = 0; fields[j]; j++) {
872 if (str[5+i] == fields[j]) {
873 break;
874 }
875 }
876 if (!(fields[j])) {
877 return 0;
878 }
879 res |= 1 << j;
880 }
881 return res;
882 }
883 return 0;
884 }
885
thumb_getshift(const char * str)886 static ut32 thumb_getshift(const char *str) {
887 // only immediate shifts are ever used by thumb-2. Bit positions are different from ARM.
888 const char *shifts[] = {
889 "LSL", "LSR", "ASR", "ROR", 0, "RRX"
890 };
891 char *type = strdup (str);
892 char *arg;
893 char *space;
894 ut32 res = 0;
895 ut32 shift = false;
896 err = false;
897 ut32 argn;
898 ut32 i;
899
900 r_str_case (type,true);
901
902 if (!strcmp (type, shifts[5])) {
903 // handle RRX alias case
904 res |= 3 << 12;
905 free (type);
906 return res;
907 }
908
909 space = strchr (type, ' ');
910 if (!space) {
911 free (type);
912 err = true;
913 return 0;
914 }
915 *space = 0;
916 arg = strdup (++space);
917
918 for (i = 0; shifts[i]; i++) {
919 if (!strcmp (type, shifts[i])) {
920 shift = true;
921 break;
922 }
923 }
924 if (!shift) {
925 err = true;
926 free (type);
927 free (arg);
928 return 0;
929 }
930 res |= i << 12;
931
932 argn = getnum (arg);
933 if (err || argn > 32) {
934 err = true;
935 free (type);
936 free (arg);
937 return 0;
938 }
939 res |= ( (argn & 0x1c) << 2);
940 res |= ( (argn & 0x3) << 14);
941
942 free (type);
943 free (arg);
944 return res;
945 }
946
getshiftmemend(const char * input)947 static st32 getshiftmemend(const char *input) {
948 st32 res;
949 if (!input || !*input || !r_str_endswith (input, "]")) {
950 return -1;
951 }
952
953 char *temp = r_str_ndup (input, strlen (input) - 1);
954 if (!temp) {
955 return -1;
956 }
957 res = thumb_getshift (temp);
958 free (temp);
959 return res;
960 }
961
collect_list(char * input[])962 void collect_list(char *input[]) {
963 if (input[0] == NULL) {
964 return;
965 }
966 char *temp = malloc (500);
967 if (!temp) {
968 return;
969 }
970 temp[0] = 0;
971 int i;
972 int conc = 0;
973 int start, end = 0;
974 int arrsz;
975 for (arrsz = 1; input[arrsz] != NULL; arrsz++) {
976 ;
977 }
978
979 for (i = 0; input[i]; i++) {
980 if (conc) {
981 strcat (temp, ", ");
982 strcat (temp, input[i]);
983 }
984 if (input[i][0] == '{') {
985 conc = 1;
986 strcat (temp, input[i]);
987 start = i;
988 }
989 if ((conc) & (input[i][strlen (input[i]) - 1] == '}')) {
990 conc = 0;
991 end = i;
992 }
993 }
994 if (end == 0) {
995 free (temp);
996 return;
997 }
998 input[start] = temp;
999 for (i = start + 1; i < arrsz; i++) {
1000 input[i] = input[(end-start) + i];
1001 }
1002 input[i] = NULL;
1003 }
1004
thumb_selector(char * args[])1005 static ut64 thumb_selector(char *args[]) {
1006 collect_list(args);
1007 ut64 res = 0;
1008 ut8 i;
1009 for (i = 0; i < 15; i++) {
1010 if (args[i] == NULL) {
1011 break;
1012 }
1013 if (getreg (args[i]) != -1) {
1014 res |= 1 << (i*4);
1015 continue;
1016 }
1017 err = false;
1018 getnum (args[i]);
1019 if (!err) {
1020 res |= 2 << (i*4);
1021 continue;
1022 }
1023 err = false;
1024 thumb_getshift (args[i]);
1025 if (!err) {
1026 res |= 3 << (i*4);
1027 continue;
1028 }
1029 if (getcoproc (args[i]) != -1) {
1030 res |= 4 << (i*4);
1031 continue;
1032 }
1033 if (getcoprocreg (args[i]) != -1) {
1034 res |= 5 << (i*4);
1035 continue;
1036 }
1037 if (getregmemstart (args[i]) != -1) {
1038 res |= 6 << (i*4);
1039 continue;
1040 }
1041 if (getregmemstartend (args[i]) != -1) {
1042 res |= 7 << (i*4);
1043 continue;
1044 }
1045 err = false;
1046 getnummemend(args[i]);
1047 if (!err) {
1048 res |= 8 << (i*4);
1049 continue;
1050 }
1051 err = false;
1052 getnummemendbang(args[i]);
1053 if (!err) {
1054 res |= 9 << (i*4);
1055 continue;
1056 }
1057 if (getregmembang (args[i]) != -1) {
1058 res |= 0xa << (i*4);
1059 continue;
1060 }
1061 if (getreglist (args[i]) != -1) {
1062 res |= 0xb << (i*4);
1063 continue;
1064 }
1065 if (getregmemend (args[i]) != -1) {
1066 res |= 0xc << (i*4);
1067 continue;
1068 }
1069 if (getshiftmemend (args[i]) != -1) {
1070 res |= 0xd << (i*4);
1071 continue;
1072 }
1073 err = false;
1074 getnumbang(args[i]);
1075 if (!err) {
1076 res |= 0xe << (i*4);
1077 continue;
1078 }
1079 res |= 0xf << (i*4);
1080 }
1081 err = false;
1082 return res;
1083 }
1084
getshift(const char * str)1085 static ut32 getshift(const char *str) {
1086 char type[128];
1087 char arg[128];
1088 char *space;
1089 ut32 i=0, shift=0;
1090 const char *shifts[] = {
1091 "LSL", "LSR", "ASR", "ROR",
1092 0, "RRX" // alias for ROR #0
1093 };
1094
1095 strncpy (type, str, sizeof (type) - 1);
1096 // XXX strcaecmp is probably unportable
1097 if (!r_str_casecmp (type, shifts[5])) {
1098 // handle RRX alias case
1099 shift = 6;
1100 } else { // all other shift types
1101 space = strchr (type, ' ');
1102 if (!space) {
1103 return 0;
1104 }
1105 *space = 0;
1106 strncpy (arg, ++space, sizeof(arg) - 1);
1107
1108 for (i = 0; shifts[i]; i++) {
1109 if (!r_str_casecmp (type, shifts[i])) {
1110 shift = 1;
1111 break;
1112 }
1113 }
1114 if (!shift) {
1115 return 0;
1116 }
1117 shift = i * 2;
1118 if ((i = getreg (arg)) != -1) {
1119 i <<= 8; // set reg
1120 // i|=1; // use reg
1121 i |= (1 << 4); // bitshift
1122 i |= shift << 4; // set shift mode
1123 if (shift == 6) {
1124 i |= (1 << 20);
1125 }
1126 } else {
1127 char *bracket = strchr (arg, ']');
1128 if (bracket) {
1129 *bracket = '\0';
1130 }
1131 // ensure only the bottom 5 bits are used
1132 i &= 0x1f;
1133 if (!i) {
1134 i = 32;
1135 }
1136 i = (i * 8);
1137 i |= shift; // lsl, ror, ...
1138 i = i << 4;
1139 }
1140 }
1141
1142 return i;
1143 }
1144
arm_opcode_parse(ArmOpcode * ao,const char * str)1145 static void arm_opcode_parse(ArmOpcode *ao, const char *str) {
1146 int i;
1147 memset (ao, 0, sizeof (ArmOpcode));
1148 if (strlen (str) + 1 >= sizeof (ao->op)) {
1149 return;
1150 }
1151 strncpy (ao->op, str, sizeof (ao->op)-1);
1152 strcpy (ao->opstr, ao->op);
1153 ao->a[0] = strchr (ao->op, ' ');
1154 for (i=0; i<15; i++) {
1155 if (ao->a[i]) {
1156 *ao->a[i] = 0;
1157 ao->a[i+1] = strchr (++ao->a[i], ',');
1158 } else {
1159 break;
1160 }
1161 }
1162 if (ao->a[i]) {
1163 *ao->a[i] = 0;
1164 ao->a[i]++;
1165 }
1166 for (i=0; i<16; i++) {
1167 while (ao->a[i] && *ao->a[i] == ' ') {
1168 ao->a[i]++;
1169 }
1170 }
1171 }
1172
arm_opcode_cond(ArmOpcode * ao,int delta)1173 static inline int arm_opcode_cond(ArmOpcode *ao, int delta) {
1174 const char *conds[] = {
1175 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
1176 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
1177 };
1178 int i, cond = 14; // 'always' is default
1179 char *c = ao->op+delta;
1180 for (i=0; conds[i]; i++) {
1181 if (!strcmpnull (c, conds[i])) {
1182 cond = i;
1183 break;
1184 }
1185 }
1186 ao->o |= cond << 4;
1187 return cond;
1188 }
1189
thumb_getoffset(char * label,ut64 cur)1190 static st32 thumb_getoffset(char *label, ut64 cur) {
1191 st32 res = r_num_math (NULL, label);
1192 res -= 4;
1193 res -= cur; // possible integer underflow
1194 //printf("thumb_getoffset: %s, %lld, %lld\n", label, res, cur);
1195 return res;
1196 }
1197
std_16bit_2reg(ArmOpcode * ao,ut64 m)1198 static st8 std_16bit_2reg(ArmOpcode *ao, ut64 m) {
1199 ut8 rd = getreg (ao->a[0]);
1200 ut8 rn = getreg (ao->a[1]);
1201 if ( (rd < 8) && (rn < 8) && !(m & DOTW_BIT)) {
1202 ao->o |= rd << 8;
1203 ao->o |= rn << 11;
1204 return 2;
1205 }
1206 return 0;
1207 }
1208
mem_16bit_2reg(ArmOpcode * ao,ut64 m)1209 static st8 mem_16bit_2reg(ArmOpcode *ao, ut64 m) {
1210 ut8 rd = getreg (ao->a[0]);
1211 ut8 rn = getregmemstart (ao->a[1]);
1212 if ( (rd < 8) && (rn < 8) && !(m & DOTW_BIT)) {
1213 ao->o |= rd << 8;
1214 ao->o |= rn << 11;
1215 return 2;
1216 }
1217 return 0;
1218 }
1219
std_32bit_2reg(ArmOpcode * ao,ut64 m,bool shift)1220 static st8 std_32bit_2reg(ArmOpcode *ao, ut64 m, bool shift) {
1221 ut8 rd = getreg (ao->a[0]);
1222 ut8 rn = getreg (ao->a[1]);
1223 if ((rd > 15) || (rn > 15) || (m & DOTN_BIT)) {
1224 return -1;
1225 }
1226 if (m & S_BIT) {
1227 ao->o |= 1 << 28;
1228 }
1229 if (shift) {
1230 err = false;
1231 ut32 shiftnum = thumb_getshift (ao->a[2]);
1232 if (err) {
1233 return -1;
1234 }
1235 ao->o |= shiftnum;
1236 ao->o |= rd << 24;
1237 ao->o |= rn << 8;
1238 } else {
1239 ao->o |= rd;
1240 ao->o |= rn << 24;
1241 }
1242 return 4;
1243 }
1244
mem_32bit_2reg(ArmOpcode * ao,ut64 m)1245 static st8 mem_32bit_2reg(ArmOpcode *ao, ut64 m) {
1246 ut8 rd = getreg (ao->a[0]);
1247 ut8 rn = getregmemstart (ao->a[1]);
1248 if ((rd > 15) || (rn > 15) || (m & DOTN_BIT)) {
1249 return -1;
1250 }
1251 ao->o |= rd << 4;
1252 ao->o |= rn << 24;
1253 return 4;
1254 }
1255
std_32bit_3reg(ArmOpcode * ao,ut64 m,bool shift)1256 static st8 std_32bit_3reg(ArmOpcode *ao, ut64 m, bool shift) {
1257 ut8 rd = getreg (ao->a[0]);
1258 ut8 rn = getreg (ao->a[1]);
1259 ut8 rm = getreg (ao->a[2]);
1260 if ((rd > 15) || (rn > 15) || (rm > 15) || (m & DOTN_BIT)) {
1261 return -1;
1262 }
1263 ao->o |= rd;
1264 ao->o |= rn << 24;
1265 ao->o |= rm << 8;
1266 if (shift) {
1267 err = false;
1268 ut32 shiftnum = thumb_getshift (ao->a[3]);
1269 if (err) {
1270 return -1;
1271 }
1272 ao->o |= shiftnum;
1273 }
1274 if (m & S_BIT) {
1275 ao->o |= 1 << 28;
1276 }
1277 return 4;
1278 }
1279
std_opt_2(ArmOpcode * ao)1280 static void std_opt_2(ArmOpcode *ao) {
1281 ao->a[2] = ao->a[1];
1282 ao->a[1] = ao->a[0];
1283 }
1284
std_opt_3(ArmOpcode * ao)1285 static void std_opt_3(ArmOpcode *ao) {
1286 ao->a[3] = ao->a[2];
1287 ao->a[2] = ao->a[1];
1288 ao->a[1] = ao->a[0];
1289 }
1290
1291 // TODO: group similar instructions like for non-thumb
thumb_assemble(ArmOpcode * ao,ut64 off,const char * str)1292 static int thumb_assemble(ArmOpcode *ao, ut64 off, const char *str) {
1293 ut64 m;
1294 ao->o = UT32_MAX;
1295 if (!strcmpnull (ao->op, "udf")) {
1296 ao->o = 0xde;
1297 ao->o |= getnum (ao->a[0]) << 8;
1298 return 2;
1299 } else
1300 if ((m = opmask (ao->op, "add", S_BIT | W_BIT))) {
1301 ut64 argt = thumb_selector (ao->a);
1302 switch (argt) {
1303 case THUMB_REG_CONST: {
1304 std_opt_2 (ao);
1305 }
1306 // intentional fallthrough
1307 case THUMB_REG_REG_CONST: {
1308 ut8 reg1 = getreg (ao->a[0]);
1309 ut8 reg2 = getreg (ao->a[1]);
1310 ut32 num = getnum (ao->a[2]);
1311
1312 if ((reg1 > 15) || (reg2 > 15)) {
1313 return -1;
1314 }
1315
1316 if (reg2 == 13) {
1317 if ((reg1 < 8) && (num < 1024) && (num % 4 == 0) && (!(m & DOTW_BIT)) && (!(m & W_BIT))) {
1318 ao->o = 0x00a8;
1319 ao->o |= reg1;
1320 ao->o |= (num >> 2) << 8;
1321 return 2;
1322 }
1323
1324 if ((reg1 == 13) && (num < 512) && (num % 4 == 0) && (!(m & DOTW_BIT)) && (!(m & W_BIT))) {
1325 ao->o = 0x00b0;
1326 ao->o |= (num >> 2) << 8;
1327 return 2;
1328 }
1329
1330 err = false;
1331 ut32 thnum = getthimmed12 (ao->a[2]);
1332 if (!err && (!(m & W_BIT))) {
1333 ao->o = 0x0df10000;
1334 ao->o |= reg1;
1335 ao->o |= thnum;
1336 if (m & S_BIT) {
1337 ao->o |= 1 << 28;
1338 }
1339 return 4;
1340 }
1341
1342 if (num > 4095) {
1343 return -1;
1344 }
1345
1346 ao->o = 0x0df20000;
1347 ao->o |= reg1;
1348 ao->o |= getthzeroimmed12 (num);
1349 return 4;
1350 }
1351
1352 if (num < 8) {
1353 ao->o = 0x001c;
1354 ao->o |= (num & 0x3) << 14;
1355 ao->o |= (num >> 2);
1356 if (std_16bit_2reg (ao, m)) {
1357 return 2;
1358 }
1359 }
1360
1361 if ((reg1 < 8) && (reg1 == reg2) && (num < 256)) {
1362 ao->o = 0x0030;
1363 ao->o |= reg1;
1364 ao->o |= num << 8;
1365 return 2;
1366 }
1367
1368 err = false;
1369 ut32 thnum = getthimmed12 (ao->a[2]);
1370 if (!err && (!(m & W_BIT))) {
1371 ao->o = 0x00f10000;
1372 ao->o |= thnum;
1373 return std_32bit_2reg (ao, m, false);
1374 }
1375
1376 if (num > 4095) {
1377 return -1;
1378 }
1379
1380 ao->o = 0x00f20000;
1381 ao->o |= getthzeroimmed12 (num);
1382 return std_32bit_2reg (ao, m, false);
1383 }
1384 break;
1385 case THUMB_REG_REG: {
1386 std_opt_2 (ao);
1387 }
1388 // intentional fallthrough
1389 case THUMB_REG_REG_REG: {
1390 ao->a[3] = "lsl 0";
1391 }
1392 // intentional fallthrough
1393 case THUMB_REG_REG_SHIFT: {
1394 if (ao->a[3] == NULL) { // double fallthrough
1395 std_opt_3 (ao);
1396 }
1397 }
1398 // intentional fallthrough
1399 case THUMB_REG_REG_REG_SHIFT: {
1400 ut8 reg1 = getreg (ao->a[0]);
1401 ut8 reg2 = getreg (ao->a[1]);
1402 ut8 reg3 = getreg (ao->a[2]);
1403 ut32 shift = thumb_getshift (ao->a[3]);
1404
1405 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
1406 return -1;
1407 }
1408
1409 if (reg2 == 13) {
1410 if ((reg1 == reg3) && (!(m & DOTW_BIT)) && (shift == 0)) {
1411 ao->o = 0x6844;
1412 ao->o |= (reg1 & 0x7) << 8;
1413 ao->o |= (reg1 >> 3) << 15;
1414 return 2;
1415 }
1416
1417 if ((reg1 == 13) && (!(m & DOTW_BIT)) && (shift == 0)) {
1418 ao->o = 0x8544;
1419 ao->o |= reg3 << 11;
1420 return 2;
1421 }
1422
1423 ao->o = 0x0deb0000;
1424 ao->o |= reg1;
1425 ao->o |= reg3 << 8;
1426 ao->o |= shift;
1427 if (m & S_BIT) {
1428 ao->o |= 1 << 28;
1429 }
1430 return 4;
1431 }
1432
1433 if ((reg3 < 8) && (!(m & DOTW_BIT)) && (shift == 0)) {
1434 ao->o = 0x0018;
1435 ao->o |= (reg3 >> 2);
1436 ao->o |= (reg3 & 0x3) << 14;
1437 if (std_16bit_2reg (ao, m)) {
1438 return 2;
1439 }
1440 }
1441
1442 if ((reg1 == reg2) && (!(m & DOTW_BIT)) && (shift == 0)) {
1443 ao->o = 0x0044;
1444 ao->o |= (reg1 & 0x7) << 8;
1445 ao->o |= (reg1 >> 3) << 15;
1446 ao->o |= reg3 << 11;
1447 return 2;
1448 }
1449
1450 ao->o = 0x00eb0000;
1451 return std_32bit_3reg (ao, m, true);
1452 }
1453 break;
1454 default:
1455 return -1;
1456 }
1457 } else
1458 if ((m = opmask (ao->op, "adc", S_BIT))) {
1459 ut64 argt = thumb_selector (ao->a);
1460 switch (argt) {
1461 case THUMB_REG_CONST: {
1462 std_opt_2 (ao);
1463 }
1464 // intentional fallthrough
1465 case THUMB_REG_REG_CONST: {
1466 ao->o = 0x40f10000;
1467 ao->o |= getthimmed12 (ao->a[2]);
1468 return std_32bit_2reg (ao, m, false);
1469 }
1470 break;
1471 case THUMB_REG_REG: {
1472 ao->o = 0x4041;
1473 if (std_16bit_2reg (ao, m)) {
1474 return 2;
1475 }
1476 std_opt_2 (ao);
1477 }
1478 // intentional fallthrough
1479 case THUMB_REG_REG_REG: {
1480 ao->o = 0x40eb0000;
1481 return std_32bit_3reg (ao, m, false);
1482 }
1483 break;
1484 case THUMB_REG_REG_SHIFT: {
1485 std_opt_3 (ao);
1486 }
1487 // intentional fallthrough
1488 // a bit naughty, perhaps?
1489 case THUMB_REG_REG_REG_SHIFT: {
1490 ao->o = 0x40eb0000;
1491 return std_32bit_3reg(ao, m, true);
1492 }
1493 break;
1494 default:
1495 return -1;
1496 }
1497 } else
1498 if ((m = opmask (ao->op, "adr", 0))) {
1499 ut64 argt = thumb_selector (ao->a);
1500 switch (argt) {
1501 case THUMB_REG_CONST: {
1502 ut8 reg = getreg (ao->a[0]);
1503 st32 label = getnum (ao->a[1]);
1504 if ( !(m & DOTW_BIT) && (reg < 8) && (label < 1024) && (label >= 0) && (label % 4 == 0)) {
1505 ao->o = 0x00a0;
1506 ao->o |= reg;
1507 ao->o |= (label / 4) << 8;
1508 return 2;
1509 } else if ((label < 0) && (label > -4096)) {
1510 if (m & DOTN_BIT) {
1511 // this is explicitly an error
1512 return -1;
1513 }
1514 ao->o = 0xaff20000;
1515 ao->o |= reg;
1516 ao->o |= getthzeroimmed12 (-label);
1517 return 4;
1518 } else if ((label > 0) && (label < 4096)) {
1519 if (m & DOTN_BIT) {
1520 // this is explicitly an error
1521 return -1;
1522 }
1523 ao->o = 0x0ff20000;
1524 ao->o |= reg;
1525 ao->o |= getthzeroimmed12 (label);
1526 return 4;
1527 }
1528 return -1;
1529 }
1530 break;
1531 default:
1532 return -1;
1533 }
1534 } else
1535 if ((m = opmask (ao->op, "and", S_BIT))) {
1536 ut64 argt = thumb_selector (ao->a);
1537 switch (argt) {
1538 case THUMB_REG_REG: {
1539 ao->o = 0x0040;
1540 if (std_16bit_2reg (ao, m)) {
1541 return 2;
1542 }
1543 std_opt_2 (ao);
1544 }
1545 // intentional fallthrough
1546 case THUMB_REG_REG_REG: {
1547 ao->o = 0x00ea0000;
1548 return std_32bit_3reg (ao, m, false);
1549 }
1550 break;
1551 case THUMB_REG_CONST: {
1552 std_opt_2 (ao);
1553 }
1554 // intentional fallthrough
1555 case THUMB_REG_REG_CONST: {
1556 ut32 imm = getthimmed12 (ao->a[2]);
1557 ao->o = 0x00f00000;
1558 ao->o |= imm;
1559 return std_32bit_2reg (ao, m, false);
1560 }
1561 break;
1562 case THUMB_REG_REG_SHIFT: {
1563 std_opt_3 (ao);
1564 }
1565 // intentional fallthrough
1566 case THUMB_REG_REG_REG_SHIFT: {
1567 ao->o = 0x00ea0000;
1568 return std_32bit_3reg (ao, m, true);
1569 }
1570 break;
1571 default:
1572 return -1;
1573 }
1574 } else
1575 if ((m = opmask (ao->op, "asr", S_BIT))) {
1576 ut64 argt = thumb_selector (ao->a);
1577 switch (argt) {
1578 case THUMB_REG_REG_CONST: {
1579 ut8 reg1 = getreg (ao->a[0]);
1580 ut8 reg2 = getreg (ao->a[1]);
1581 ut32 imm = getnum (ao->a[2]);
1582 if (((int)imm < 1) && ((int)imm > 32)) {
1583 return -1;
1584 }
1585 ao->o = 0x0010;
1586 ao->o |= (imm & 0x3) << 14;
1587 ao->o |= (imm & 0x1c) >> 2;
1588 if (std_16bit_2reg (ao, m)) {
1589 return 2;
1590 }
1591 ao->o = 0x4fea2000;
1592 ao->o |= reg1;
1593 ao->o |= reg2 << 8;
1594 ao->o |= (imm & 0x3) << 14;
1595 ao->o |= (imm & 0x1c) << 2;
1596 if (m & S_BIT) {
1597 ao->o |= 1 << 28;
1598 }
1599 return 4;
1600 }
1601 break;
1602 case THUMB_REG_REG: {
1603 ao->o = 0x0041;
1604 if (std_16bit_2reg (ao, m)) {
1605 return 2;
1606 }
1607 std_opt_2 (ao);
1608 }
1609 // intentional fallthrough
1610 case THUMB_REG_REG_REG: {
1611 ao->o = 0x40fa00f0;
1612 return std_32bit_3reg (ao, m, false);
1613 }
1614 break;
1615 default:
1616 return -1;
1617 }
1618 } else
1619 if (( m = opmask (ao->op, "b", 0) )) {
1620 ut64 argt = thumb_selector (ao->a);
1621 switch (argt) {
1622 case THUMB_CONST: {
1623 st32 offset = thumb_getoffset (ao->a[0], off);
1624 if (offset % 2 != 0) {
1625 return -1;
1626 }
1627
1628 if ((m & C_BITS) == C_BITS) {
1629 if ((offset >= -2048) && (offset <= 2046) && (!(m & DOTW_BIT))) {
1630 ao->o = 0x00e0;
1631 ao->o |= ((offset/2 & 0xff) << 8);
1632 ao->o |= ((offset/2 & 0x700) >> 8);
1633 return 2;
1634 }
1635 if ((offset < -16777216) || (offset > 16777214) || (offset % 2 != 0)) {
1636 return -1;
1637 }
1638 ao->o = 0x00f00090;
1639 ao->o |= getthbimmed(offset);
1640 return 4;
1641 } else {
1642 if ((offset >= -256) && (offset <= 254) && (!(m & DOTW_BIT))) {
1643 ao->o = 0x00d0;
1644 ao->o |= (ut16) ((offset/2) << 8);
1645 ao->o |= ((m & C_BITS) >> 2);
1646 return 2;
1647 }
1648 if ((offset < -1048576) || (offset > 1048574) || (offset % 2 != 0)) {
1649 return -1;
1650 }
1651
1652 ao->o = 0x00f00080;
1653 ao->o |= (ut32)(offset & 0x80000) >> 16;
1654 ao->o |= (ut32)(offset & 0x40000) >> 13;
1655 ao->o |= (ut32)(offset & 0x3f000) << 12;
1656 ao->o |= (ut32)(offset & 0xe00) >> 9;
1657 ao->o |= (ut32)(offset & 0x1fe) << 7;
1658 if (offset < 0) {
1659 ao->o |= 1 << 18;
1660 }
1661 ao->o |= (((m & C_BITS) & 0xc) << 28);
1662 ao->o |= (((m & C_BITS) & 0x30) << 12);
1663 return 4;
1664 }
1665 }
1666 break;
1667 default:
1668 return -1;
1669 }
1670 } else
1671 if (( m = opmask (ao->op, "bl", 0) )) {
1672 ut64 argt = thumb_selector (ao->a);
1673 switch (argt) {
1674 case THUMB_CONST: {
1675 st32 offset = thumb_getoffset (ao->a[0], off);
1676 ao->o = 0x00f000d0;
1677 if ((offset > 16777214) || (offset < -16777216) || (offset % 2 != 0)) {
1678 return -1;
1679 }
1680 ao->o |= getthbimmed(offset);
1681 return 4;
1682 }
1683 break;
1684 default:
1685 return -1;
1686 }
1687 } else
1688 if (( m = opmask (ao->op, "bx", 0) )) {
1689 ut64 argt = thumb_selector (ao->a);
1690 switch (argt) {
1691 case THUMB_REG: {
1692 ut32 reg1 = getreg (ao->a[0]);
1693 ao->o = 0x0047;
1694 ao->o |= reg1 << 11;
1695 return 2;
1696 }
1697 break;
1698 default:
1699 return -1;
1700 }
1701 } else
1702 if (( m = opmask (ao->op, "blx", 0) )) {
1703 ut64 argt = thumb_selector (ao->a);
1704 switch (argt) {
1705 case THUMB_REG: {
1706 ut32 reg1 = getreg (ao->a[0]);
1707 ao->o = 0x8047;
1708 ao->o |= reg1 << 11;
1709 return 2;
1710 }
1711 break;
1712 case THUMB_CONST: {
1713 st32 offset = thumb_getoffset (ao->a[0], off);
1714 ao->o = 0x00f000c0;
1715 if ((offset > 16777214) || (offset < -16777216) || (offset % 2 != 0)) {
1716 return -1;
1717 }
1718 offset += off & 0x2; // (Align(PC,4)
1719 ao->o |= getthbimmed (offset);
1720 return 4;
1721 }
1722 break;
1723 default:
1724 return -1;
1725 }
1726 } else
1727 if (( m = opmask (ao->op, "bfc", 0) )) {
1728 ut64 argt = thumb_selector (ao->a);
1729 switch (argt) {
1730 case THUMB_REG_CONST_CONST: {
1731 if (m & DOTN_BIT) {
1732 // this is explicitly an error
1733 return -1;
1734 }
1735 ut8 reg1 = getreg (ao->a[0]);
1736 ut32 lsb = getnum (ao->a[1]);
1737 ut32 width = getnum (ao->a[2]);
1738 ut32 msb = lsb + width - 1;
1739 if ((lsb > 31) || (msb > 31)) {
1740 return -1;
1741 }
1742 ao->o = 0x6ff30000;
1743 ao->o |= reg1;
1744 ao->o |= ((lsb & 0x1c) << 2);
1745 ao->o |= ((lsb & 0x3) << 14);
1746 ao->o |= (msb << 8);
1747 return 4;
1748 }
1749 break;
1750 default:
1751 return -1;
1752 }
1753 } else
1754 if (( m = opmask (ao->op, "bfi", 0) )) {
1755 ut64 argt = thumb_selector (ao->a);
1756 switch (argt) {
1757 case THUMB_REG_REG_CONST_CONST: {
1758 ut32 lsb = getnum (ao->a[2]);
1759 ut32 width = getnum (ao->a[3]);
1760 ut32 msb = lsb + width - 1;
1761 if ((lsb > 31) || (msb > 31)) {
1762 return -1;
1763 }
1764 ao->o = 0x60f30000;
1765 ao->o |= ((lsb & 0x1c) << 2);
1766 ao->o |= ((lsb & 0x3) << 14);
1767 ao->o |= (msb << 8);
1768 return std_32bit_2reg (ao, m, false);
1769 }
1770 break;
1771 default:
1772 return -1;
1773 }
1774 } else
1775 if (( m = opmask (ao->op, "bic", S_BIT) )) {
1776 ut64 argt = thumb_selector (ao->a);
1777 switch (argt) {
1778 case THUMB_REG_REG: {
1779 ao->o = 0x8043;
1780 if (std_16bit_2reg (ao, m)) {
1781 return 2;
1782 }
1783 std_opt_2 (ao);
1784 }
1785 // intentional fallthrough
1786 case THUMB_REG_REG_REG: {
1787 ao->o = 0x20ea0000;
1788 return std_32bit_3reg (ao, m, false);
1789 }
1790 break;
1791 case THUMB_REG_CONST: {
1792 std_opt_2 (ao);
1793 }
1794 // intentional fallthrough
1795 case THUMB_REG_REG_CONST: {
1796 ao->o = 0x20f00000;
1797 ao->o |= getthimmed12 (ao->a[2]);
1798 return std_32bit_2reg (ao, m, false);
1799 }
1800 break;
1801 case THUMB_REG_REG_SHIFT: {
1802 std_opt_3 (ao);
1803 }
1804 // intentional fallthrough
1805 case THUMB_REG_REG_REG_SHIFT: {
1806 ao->o = 0x20ea0000;
1807 return std_32bit_3reg (ao, m, true);
1808 }
1809 break;
1810 default:
1811 return -1;
1812 }
1813 } else
1814 if (( m = opmask (ao->op, "bkpt", 0) )) {
1815 ut64 argt = thumb_selector (ao->a);
1816 switch (argt) {
1817 case THUMB_CONST: {
1818 ut32 num = getnum (ao->a[0]);
1819 if (num > 255) {
1820 return -1;
1821 }
1822 ao->o = 0x00be;
1823 ao->o |= num << 8;
1824 return 2;
1825 }
1826 break;
1827 default:
1828 return -1;
1829 }
1830 } else
1831 if (( m = opmask (ao->op, "cbnz", 0) )) {
1832 ut64 argt = thumb_selector (ao->a);
1833 switch (argt) {
1834 case THUMB_REG_CONST: {
1835 ut8 reg1 = getreg (ao->a[0]);
1836 st32 offset = thumb_getoffset (ao->a[1], off);
1837 if ((reg1 > 7) || (offset > 127) || (offset % 2 != 0)) {
1838 return -1;
1839 }
1840 ao->o = 0x00b9;
1841 ao->o |= reg1 << 8;
1842 ao->o |= (offset & 0x3e) << 10;
1843 ao->o |= (offset & 0x40) >> 5;
1844 return 2;
1845 }
1846 break;
1847 default:
1848 return -1;
1849 }
1850 } else
1851 if (( m = opmask (ao->op, "cbz", 0) )) {
1852 ut64 argt = thumb_selector (ao->a);
1853 switch (argt) {
1854 case THUMB_REG_CONST: {
1855 ut8 reg1 = getreg (ao->a[0]);
1856 st32 offset = thumb_getoffset (ao->a[1], off);
1857 if ((reg1 > 7) || (offset > 127) || (offset % 2 != 0)) {
1858 return -1;
1859 }
1860 ao->o = 0x00b1;
1861 ao->o |= reg1 << 8;
1862 ao->o |= (offset & 0x3e) << 10;
1863 ao->o |= (offset & 0x40) >> 5;
1864 return 2;
1865 }
1866 break;
1867 default:
1868 return -1;
1869 }
1870 } else
1871 if (( m = opmask (ao->op, "cdp", TWO_BIT) )) {
1872 ut64 argt = thumb_selector (ao->a);
1873 switch (argt) {
1874 case THUMB_COPROC_CONST_COREG_COREG_COREG: {
1875 ao->a[5] = "0";
1876 }
1877 //intentional fallthrough
1878 case THUMB_COPROC_CONST_COREG_COREG_COREG_CONST: {
1879 ut32 coproc = getcoproc (ao->a[0]);
1880 ut32 opc1 = getnum (ao->a[1]);
1881 ut8 reg1 = getcoprocreg (ao->a[2]);
1882 ut8 reg2 = getcoprocreg (ao->a[3]);
1883 ut8 reg3 = getcoprocreg (ao->a[4]);
1884 ut32 opc2 = getnum (ao->a[5]);
1885 if ((coproc > 15) || (opc1 > 15) || (opc2 > 7)) {
1886 return -1;
1887 }
1888 ao->o = 0x00ee0000;
1889 if (m & TWO_BIT) {
1890 ao->o |= 1 << 20;
1891 }
1892 ao->o |= coproc;
1893 ao->o |= opc1 << 28;
1894 ao->o |= reg1 << 4;
1895 ao->o |= reg2 << 24;
1896 ao->o |= reg3 << 8;
1897 ao->o |= opc2 << 13;
1898 return 4;
1899 }
1900 break;
1901 default:
1902 return -1;
1903 }
1904 } else
1905 if (( m = opmask (ao->op, "clrex", 0) )) {
1906 ut64 argt = thumb_selector (ao->a);
1907 switch (argt) {
1908 case THUMB_NONE: {
1909 ao->o = 0xbff32f8f;
1910 return 4;
1911 }
1912 break;
1913 default:
1914 return -1;
1915 }
1916 } else
1917 if (( m = opmask (ao->op, "clz", 0) )) {
1918 ut64 argt = thumb_selector (ao->a);
1919 switch (argt) {
1920 case THUMB_REG_REG: {
1921 ao->o = 0xb0fa80f0;
1922 ao->a[2] = ao->a[1];
1923 return std_32bit_3reg (ao, m, false);
1924 }
1925 break;
1926 default:
1927 return -1;
1928 }
1929 } else
1930 if (( m = opmask (ao->op, "cmn", 0) )) {
1931 ut64 argt = thumb_selector (ao->a);
1932 switch (argt) {
1933 case THUMB_REG_CONST: {
1934 ut8 reg1 = getreg (ao->a[0]);
1935 ut32 num = getthimmed12 (ao->a[1]);
1936 ao->o = 0x10f1000f;
1937 ao->o |= reg1 << 24;
1938 ao->o |= num;
1939 return 4;
1940 }
1941 break;
1942 case THUMB_REG_REG: {
1943 ao->o = 0xc042;
1944 if (std_16bit_2reg (ao, m)) {
1945 return 2;
1946 }
1947 ao->a[2] = "lsl 0";
1948 }
1949 // intentional fallthrough
1950 case THUMB_REG_REG_SHIFT: {
1951 ao->o = 0x10eb000f;
1952 return std_32bit_2reg (ao, m, true);
1953 }
1954 break;
1955 default:
1956 return -1;
1957 }
1958 } else
1959 if (( m = opmask (ao->op, "cmp", 0) )) {
1960 ut64 argt = thumb_selector (ao->a);
1961 switch (argt) {
1962 case THUMB_REG_CONST: {
1963 ut8 reg1 = getreg (ao->a[0]);
1964 ut32 num = getnum (ao->a[1]);
1965 if ((num < 256) && (!(m & DOTW_BIT))) {
1966 ao->o = 0x0028;
1967 ao->o |= reg1;
1968 ao->o |= num << 8;
1969 return 2;
1970 }
1971 num = getthimmed12 (ao->a[1]);
1972 ao->o = 0xb0f1000f;
1973 ao->o |= reg1 << 24;
1974 ao->o |= num;
1975 return 4;
1976 }
1977 break;
1978 case THUMB_REG_REG: {
1979 ut8 reg1 = getreg (ao->a[0]);
1980 ut8 reg2 = getreg (ao->a[1]);
1981 ao->o = 0x8042;
1982 if (std_16bit_2reg (ao, m)) {
1983 return 2;
1984 }
1985 if (!(m & DOTW_BIT)) {
1986 ao->o = 0x0045;
1987 ao->o |= ((reg1 & 0x7) << 8);
1988 ao->o |= ((reg1 & 0x8) << 12);
1989 ao->o |= reg2 << 11;
1990 return 2;
1991 }
1992 ao->a[2] = "lsl 0";
1993 }
1994 // intentional fallthrough
1995 case THUMB_REG_REG_SHIFT: {
1996 ut8 reg1 = getreg (ao->a[0]);
1997 ut8 reg2 = getreg (ao->a[1]);
1998 ut32 shift = thumb_getshift (ao->a[2]);
1999 ao->o = 0xb0eb000f;
2000 ao->o |= reg1 << 24;
2001 ao->o |= reg2 << 8;
2002 ao->o |= shift;
2003 return 4;
2004 }
2005 break;
2006 default:
2007 return -1;
2008 }
2009 } else
2010 if (( m = opmask (ao->op, "cps", ID_BIT | IE_BIT) )) {
2011 ut64 argt = thumb_selector (ao->a);
2012 switch (argt) {
2013 case THUMB_OTHER: {
2014 st8 aif = iflag(ao->a[0]);
2015 if (aif == -1) {
2016 return -1;
2017 }
2018 if (!(m & DOTW_BIT)) {
2019 ao->o = 0x60b6;
2020 ao->o |= aif << 8;
2021 if (m & ID_BIT) {
2022 ao->o |= 1 << 12;
2023 }
2024 return 2;
2025 }
2026 ao->a[1] = "0";
2027 }
2028 // intentional fallthrough
2029 case THUMB_OTHER_CONST: {
2030 st8 aif = iflag(ao->a[0]);
2031 ut8 mode = getnum (ao->a[1]);
2032 if ((mode > 31) || (aif == -1)) {
2033 return -1;
2034 }
2035 ao->o = 0xaff30085;
2036 ao->o |= mode << 8;
2037 ao->o |= aif << 13;
2038 if (m & ID_BIT) {
2039 ao->o |= 1 << 1;
2040 }
2041 return 4;
2042 }
2043 break;
2044 case THUMB_CONST: {
2045 ut8 mode = getnum (ao->a[0]);
2046 if ((m & ID_BIT) || (m & IE_BIT) || (mode > 31)) {
2047 return -1;
2048 }
2049 ao->o = 0xaff30081;
2050 ao->o |= mode << 8;
2051 return 4;
2052 }
2053 break;
2054 default:
2055 return -1;
2056 }
2057 } else
2058 if ((m = opmask (ao->op, "dbg", 0))) {
2059 ut64 argt = thumb_selector (ao->a);
2060 switch (argt) {
2061 case THUMB_CONST: {
2062 ut32 option = getnum (ao->a[0]);
2063 if (option > 15) {
2064 return -1;
2065 }
2066 ao->o = 0xaff3f080;
2067 ao->o |= option << 8;
2068 return 4;
2069 }
2070 default:
2071 return -1;
2072 }
2073 } else
2074 if ((m = opmask (ao->op, "dmb", 0))) {
2075 ut64 argt = thumb_selector (ao->a);
2076 switch (argt) {
2077 case THUMB_NONE: {
2078 ao->o = 0xbff35f8f;
2079 return 4;
2080 }
2081 break;
2082 case THUMB_OTHER: {
2083 r_str_case (ao->a[0], false);
2084 if (strcmpnull (ao->a[0], "sy")) {
2085 return -1;
2086 }
2087 ao->a[0] = "15";
2088 }
2089 // intentional fallthrough
2090 case THUMB_CONST: {
2091 ut32 option = getnum (ao->a[0]);
2092 if (option != 15) {
2093 return -1;
2094 }
2095 ao->o = 0xbff3508f;
2096 ao->o |= option << 8;
2097 return 4;
2098 }
2099 break;
2100 default:
2101 return -1;
2102 }
2103 } else
2104 if ((m = opmask (ao->op, "dsb", 0))) {
2105 ut64 argt = thumb_selector (ao->a);
2106 switch (argt) {
2107 case THUMB_NONE: {
2108 ao->o = 0xbff34f8f;
2109 return 4;
2110 }
2111 // intentional fallthrough
2112 case THUMB_OTHER: {
2113 r_str_case (ao->a[0], false);
2114 if (!strcmpnull ((ao->a[0] = parse_hints(ao->a[0])), "-1")) {
2115 return -1;
2116 }
2117 }
2118 // intentional fallthrough
2119 case THUMB_CONST: {
2120 ut32 option = getnum (ao->a[0]);
2121 if ((option != 6) && (option != 7) && (option != 14) && (option != 15)) {
2122 return -1;
2123 }
2124 ao->o = 0xbff3408f;
2125 ao->o |= option << 8;
2126 return 4;
2127 }
2128 break;
2129 default:
2130 return -1;
2131 }
2132 } else
2133 if ((m = opmask (ao->op, "eor", S_BIT))) {
2134 ut64 argt = thumb_selector (ao->a);
2135 switch (argt) {
2136 case THUMB_REG_CONST:
2137 std_opt_2 (ao);
2138 // intentional fallthrough
2139 case THUMB_REG_REG_CONST: {
2140 err = false;
2141 ut32 imm = getthimmed12 (ao->a[2]);
2142 if (err) {
2143 return -1;
2144 }
2145 ao->o = 0x80f00000;
2146 ao->o |= imm;
2147 return std_32bit_2reg (ao, m, false);
2148 }
2149 break;
2150 case THUMB_REG_REG: {
2151 ao->o = 0x4040;
2152 if (std_16bit_2reg (ao, m)) {
2153 return 2;
2154 }
2155 std_opt_2 (ao);
2156 }
2157 // intentional fallthrough
2158 case THUMB_REG_REG_REG:
2159 ao->a[3] = "lsl 0";
2160 // intentional fallthrough
2161 case THUMB_REG_REG_REG_SHIFT: {
2162 ao->o = 0x80ea0000;
2163 return std_32bit_3reg (ao, m, true);
2164 }
2165 break;
2166 default:
2167 return -1;
2168 }
2169 } else
2170 if ((m = opmask (ao->op, "isb", 0))) {
2171 ut64 argt = thumb_selector (ao->a);
2172 switch (argt) {
2173 case THUMB_NONE: {
2174 ao->o = 0xbff36f8f;
2175 return 4;
2176 }
2177 // intentional fallthrough
2178 case THUMB_OTHER: {
2179 r_str_case (ao->a[0], false);
2180 if (strcmpnull (ao->a[0], "sy")) {
2181 return -1;
2182 }
2183 ao->a[0] = "15";
2184 }
2185 // intentional fallthrough
2186 case THUMB_CONST: {
2187 ut32 option = getnum (ao->a[0]);
2188 if (option != 15) {
2189 return -1;
2190 }
2191 ao->o = 0xbff3608f;
2192 ao->o |= option << 8;
2193 return 4;
2194 }
2195 break;
2196 default:
2197 return -1;
2198 }
2199 } else
2200 if ((m = itmask (ao->op))) {
2201 ut64 argt = thumb_selector (ao->a);
2202 switch (argt) {
2203 case THUMB_OTHER: {
2204 ut16 cond = 0;
2205 ut16 i;
2206
2207 const char *conds[] = {
2208 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
2209 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv", 0
2210 };
2211 r_str_case (ao->a[0], false);
2212 for (i = 0; conds[i]; i++) {
2213 if (!(strcmpnull(ao->a[0], conds[i]))) {
2214 cond = i;
2215 break;
2216 }
2217 }
2218
2219 if (i == 16) {
2220 return -1;
2221 }
2222 ao->o = 0x00bf;
2223 ao->o |= cond << 12;
2224
2225 ut8 nrcs = (m & 0x30) >> 4;
2226 ut8 thiset = 0;
2227
2228 for (i = 0; i < nrcs; i++) {
2229 thiset = ((m & (1 << (3 - i))) >> (3 - i));
2230 ao->o |= ((cond & 0x1) ^ thiset) << (11 - i);
2231 }
2232 ao->o |= 1 << (11 - i);
2233 return 2;
2234 }
2235 break;
2236 default:
2237 return -1;
2238 }
2239 } else
2240 if ((m = opmask (ao->op, "ldc", TWO_BIT | L_BIT))) {
2241 ut64 argt = thumb_selector (ao->a);
2242 switch (argt) {
2243 case THUMB_COPROC_COREG_BRACKREG_CONSTBRACK: {
2244 ut8 proc = getcoproc (ao->a[0]);
2245 ut8 reg1 = getcoprocreg (ao->a[1]);
2246 ut8 reg2 = getregmemstart (ao->a[2]);
2247 st32 imm = getnummemend (ao->a[3]);
2248 ao->o = 0x10ed0000;
2249 if (m & L_BIT) {
2250 ao->o |= 1 << 30;
2251 }
2252 if (m & TWO_BIT) {
2253 ao->o |= 1 << 20;
2254 }
2255 if (imm < 0) {
2256 imm = -imm;
2257 } else {
2258 ao->o |= 1 << 31;
2259 }
2260 if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2261 return -1;
2262 }
2263 ao->o |= proc;
2264 ao->o |= reg1 << 4;
2265 ao->o |= (imm >> 2) << 8;
2266 ao->o |= reg2 << 24;
2267 return 4;
2268 }
2269 break;
2270 case THUMB_COPROC_COREG_BRACKREGBRACK:
2271 ao->a[3] = "0";
2272 // intentional fallthrough
2273 case THUMB_COPROC_COREG_BRACKREGBRACK_CONST: {
2274 ut8 proc = getcoproc (ao->a[0]);
2275 ut8 reg1 = getcoprocreg (ao->a[1]);
2276 ut8 reg2 = getregmemstartend (ao->a[2]);
2277 st32 imm = getnum (ao->a[3]);
2278 ao->o = 0x30ec0000;
2279 if (m & L_BIT) {
2280 ao->o |= 1 << 30;
2281 }
2282 if (m & TWO_BIT) {
2283 ao->o |= 1 << 20;
2284 }
2285 if (imm < 0) {
2286 imm = -imm;
2287 } else {
2288 ao->o |= 1 << 31;
2289 }
2290 if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2291 return -1;
2292 }
2293 ao->o |= proc;
2294 ao->o |= reg1 << 4;
2295 ao->o |= (imm >> 2) << 8;
2296 ao->o |= reg2 << 24;
2297 return 4;
2298 }
2299 break;
2300 case THUMB_COPROC_COREG_BRACKREG_CONSTBRACKBANG: {
2301 ut8 proc = getcoproc (ao->a[0]);
2302 ut8 reg1 = getcoprocreg (ao->a[1]);
2303 ut8 reg2 = getregmemstart (ao->a[2]);
2304 st32 imm = getnummemendbang (ao->a[3]);
2305 ao->o = 0x30ed0000;
2306 if (m & L_BIT) {
2307 ao->o |= 1 << 30;
2308 }
2309 if (m & TWO_BIT) {
2310 ao->o |= 1 << 20;
2311 }
2312 if (imm < 0) {
2313 imm = -imm;
2314 } else {
2315 ao->o |= 1 << 31;
2316 }
2317 if ((proc > 15) || (reg1 > 15) || (reg2 > 15) || (imm > 1024) || (imm % 4 != 0)) {
2318 return -1;
2319 }
2320 ao->o |= proc;
2321 ao->o |= reg1 << 4;
2322 ao->o |= (imm >> 2) << 8;
2323 ao->o |= reg2 << 24;
2324 return 4;
2325 }
2326 break;
2327 default:
2328 return -1;
2329 }
2330 } else
2331 if ((m = opmask (ao->op, "ldm", DB_BIT | EA_BIT | IA_BIT | FD_BIT))) {
2332 ut64 argt = thumb_selector (ao->a);
2333 switch (argt) {
2334 case THUMB_REGBANG_LIST: {
2335 ut8 reg1 = getregmembang (ao->a[0]);
2336 ut32 list = getreglist (ao->a[1]);
2337 if (!((m & DB_BIT) || (m & EA_BIT)) && !(list & 0xff00) && (reg1 < 8) && !(m & DOTW_BIT)) {
2338 ao->o = 0x00c8;
2339 ao->o |= reg1;
2340 if (list & (1 << reg1)) {
2341 list ^= 1 << (reg1);
2342 }
2343 ao->o |= (list & 0xff) << 8;
2344
2345 return 2;
2346 }
2347 if (list & 0x2000) {
2348 return -1;
2349 }
2350 if ((m & DB_BIT) || (m & EA_BIT)) {
2351 ao->o = 0x30e90000;
2352 } else {
2353 // ldmia is the default!
2354 ao->o = 0xb0e80000;
2355 }
2356
2357 ao->o |= reg1 << 24;
2358 ao->o |= (list & 0xff) << 8;
2359 ao->o |= (list & 0xff00) >> 8;
2360 return 4;
2361 }
2362 break;
2363 case THUMB_REG_LIST: {
2364 ut8 reg1 = getreg (ao->a[0]);
2365 ut32 list = getreglist (ao->a[1]);
2366 if (!((m & DB_BIT) || (m & EA_BIT)) && !(list & 0xff00) && (reg1 < 8) && !(m & DOTW_BIT)) {
2367 ao->o = 0x00c8;
2368 ao->o |= reg1;
2369 ao->o |= 1 << (reg1 + 8);
2370 ao->o |= (list & 0xff) << 8;
2371 return 2;
2372 }
2373 if (list & 0x2000) {
2374 return -1;
2375 }
2376
2377 if ((m & DB_BIT) || (m & EA_BIT)) {
2378 ao->o = 0x10e90000;
2379 } else {
2380 ao->o = 0x90e80000;
2381 }
2382
2383 ao->o |= reg1 << 24;
2384 ao->o |= (list & 0xff) << 8;
2385 ao->o |= (list & 0xff00) >> 8;
2386 return 4;
2387 }
2388 break;
2389 default:
2390 return -1;
2391 }
2392 } else
2393 if ((m = opmask (ao->op, "ldr", B_BIT | H_BIT | D_BIT | T_BIT | S_BIT))) {
2394 ut64 argt = thumb_selector (ao->a);
2395 ut32 ldrsel = m & (B_BIT | H_BIT | D_BIT);
2396 if ((m & S_BIT) && !(m & (B_BIT | H_BIT))) {
2397 return -1;
2398 }
2399 switch (argt) {
2400 case THUMB_REG_CONST:
2401 ao->a[2] = ao->a[1];
2402 strcat (ao->a[2],"]");
2403 ao->a[1] = "[r15";
2404 // intentional fallthrough
2405 case THUMB_REG_BRACKREGBRACK:
2406 if (ao->a[2] == NULL) { // double fallthrough
2407 ao->a[1][strlen (ao->a[1]) -1] = '\0';
2408 ao->a[2] = "0]";
2409 }
2410 // intentional fallthrough
2411 case THUMB_REG_BRACKREG_CONSTBRACK: {
2412 ut8 reg1 = getreg (ao->a[0]);
2413 ut8 reg2 = getregmemstart (ao->a[1]);
2414 st32 num = getnummemend (ao->a[2]);
2415 if (ldrsel == 0) {
2416 if (m & T_BIT) {
2417 if ((num < 0) || (num > 255)) {
2418 return -1;
2419 }
2420 ao->o = 0x50f8000e;
2421 ao->o |= num << 8;
2422 return mem_32bit_2reg (ao, m);
2423 }
2424 if (reg2 == 15) {
2425 if ((num > 4095) || (num < -4095)) {
2426 return -1;
2427 }
2428 if ((reg1 < 8) && (num < 1024) && (num % 4 == 0)) {
2429 ao->o = 0x0048;
2430 ao->o |= reg1;
2431 ao->o |= (num >> 2) << 8;
2432 return 2;
2433 }
2434 ao->o = 0x5ff80000;
2435 if (num < 0) {
2436 num = -num;
2437 } else {
2438 ao->o |= 1 << 31;
2439 }
2440 ao->o |= reg1 << 4;
2441 ao->o |= (num & 0xff) << 8;
2442 ao->o |= (num & 0x0f00) >> 8;
2443 return 4;
2444 }
2445 if ((reg2 == 13) && (reg1 < 8) && (num >= 0) && (num < 1024) && (num % 4 == 0) && (!(m & DOTW_BIT))) {
2446 ao->o = 0x0098;
2447 ao->o |= reg1;
2448 ao->o |= (num >> 2) << 8;
2449 return 2;
2450 }
2451 if ((num >= 0) && (num < 128) && (num % 4 == 0)) {
2452 ao->o = 0x0068;
2453 ao->o |= (num >> 4);
2454 ao->o |= ((num >> 2) & 0x3) << 14;
2455 if (mem_16bit_2reg (ao, m)) {
2456 return 2;
2457 }
2458 }
2459 if ((num > 4095) || (num < -1023)) {
2460 return -1;
2461 }
2462 if (num >= 0) {
2463 ao->o = 0xd0f80000;
2464 ao->o |= (num & 0xff) << 8;
2465 ao->o |= (num & 0xf00) >> 8;
2466 return mem_32bit_2reg (ao, m);
2467 }
2468 ao->o = 0x50f8000c;
2469 ao->o |= (-num & 0xff) << 8;
2470 return mem_32bit_2reg (ao, m);
2471 } else
2472 if (ldrsel == B_BIT) {
2473 if (m & T_BIT) {
2474 if ((num < 0) || (num > 255)) {
2475 return -1;
2476 }
2477 ao->o = 0x10f8000e;
2478 if (m & S_BIT) {
2479 ao->o |= 1 << 16;
2480 }
2481 ao->o |= num << 8;
2482 return mem_32bit_2reg (ao, m);
2483 }
2484 if (reg2 == 15) {
2485 if ((num > 4095) || (num < -4095)) {
2486 return -1;
2487 }
2488 ao->o = 0x1ff80000;
2489 if (m & S_BIT) {
2490 ao->o |= 1 << 16;
2491 }
2492 if (num < 0) {
2493 num = -num;
2494 } else {
2495 ao->o |= 1 << 31;
2496 }
2497 ao->o |= reg1 << 4;
2498 ao->o |= (num & 0xff) << 8;
2499 ao->o |= (num & 0x0f00) >> 8;
2500 return 4;
2501 }
2502 if ((num >= 0) && (num < 32) && (!(m & S_BIT))) {
2503 ao->o = 0x0078;
2504 ao->o |= (num >> 2);
2505 ao->o |= (num & 0x3) << 14;
2506 if (mem_16bit_2reg (ao, m)) {
2507 return 2;
2508 }
2509 }
2510 if ((num > 4095) || (num < -255)) {
2511 return -1;
2512 }
2513 if (num >= 0) {
2514 ao->o = 0x90f80000;
2515 if (m & S_BIT) {
2516 ao->o |= 1 << 16;
2517 }
2518 ao->o |= (num & 0xff) << 8;
2519 ao->o |= (num & 0xf00) >> 8;
2520 return mem_32bit_2reg (ao, m);
2521 }
2522 ao->o = 0x10f8000c;
2523 if (m & S_BIT) {
2524 ao->o |= 1 << 16;
2525 }
2526 ao->o |= -num << 8;
2527 return mem_32bit_2reg (ao, m);
2528 } else
2529 if (ldrsel == H_BIT) {
2530 if (m & T_BIT) {
2531 if ((num < 0) || (num > 255)) {
2532 return -1;
2533 }
2534 ao->o = 0x30f8000e;
2535 if (m & S_BIT) {
2536 ao->o |= 1 << 16;
2537 }
2538 ao->o |= num << 8;
2539 return mem_32bit_2reg (ao, m);
2540 }
2541 if (reg2 == 15) {
2542 if ((num > 4095) || (num < -4095)) {
2543 return -1;
2544 }
2545 ao->o = 0x3ff80000;
2546 if (m & S_BIT) {
2547 ao->o |= 1 << 16;
2548 }
2549 if (num < 0) {
2550 num = -num;
2551 } else {
2552 ao->o |= 1 << 31;
2553 }
2554 ao->o |= reg1 << 4;
2555 ao->o |= (num & 0xff) << 8;
2556 ao->o |= (num & 0x0f00) >> 8;
2557 return 4;
2558 }
2559 if ((num >= 0) && (num < 64) && (num % 2 == 0) && (!(m & S_BIT))) {
2560 ao->o = 0x0088;
2561 ao->o |= (num >> 3);
2562 ao->o |= ((num >> 1) & 0x3) << 14;
2563 if (mem_16bit_2reg (ao, m)) {
2564 return 2;
2565 }
2566 }
2567 if ((num > 4095) || (num < -255)) {
2568 return -1;
2569 }
2570 if (num >= 0) {
2571 ao->o = 0xb0f80000;
2572 if (m & S_BIT) {
2573 ao->o |= 1 << 16;
2574 }
2575 ao->o |= (num & 0xff) << 8;
2576 ao->o |= (num & 0xf00) >> 8;
2577 return mem_32bit_2reg (ao, m);
2578 }
2579 ao->o = 0x30f8000c;
2580 if (m & S_BIT) {
2581 ao->o |= 1 << 16;
2582 }
2583 ao->o |= -num << 8;
2584 return mem_32bit_2reg (ao, m);
2585 } else {
2586 return -1;
2587 }
2588 }
2589 break;
2590 case THUMB_REG_BRACKREGBRACK_CONST: {
2591 ut8 reg1 = getreg (ao->a[0]);
2592 ut8 reg2 = getregmemstartend (ao->a[1]);
2593 st32 num = getnum (ao->a[2]);
2594 if ((num < -255) || (num > 255)) {
2595 return -1;
2596 }
2597 if (ldrsel == 0) {
2598 ao->o = 0x50f80009;
2599 } else
2600 if (ldrsel == B_BIT) {
2601 ao->o = 0x10f80009;
2602 } else
2603 if (ldrsel == H_BIT) {
2604 ao->o = 0x30f80009;
2605 } else {
2606 return -1;
2607 }
2608 if (m & S_BIT) {
2609 ao->o |= 1 << 16;
2610 }
2611 if (num < 0) {
2612 num = -num;
2613 } else {
2614 ao->o |= 1 << 1;
2615 }
2616 ao->o |= num << 8;
2617 ao->o |= reg1 << 4;
2618 ao->o |= reg2 << 24;
2619 return 4;
2620 }
2621 break;
2622 case THUMB_REG_BRACKREG_CONSTBRACKBANG: {
2623 st32 num = getnummemendbang (ao->a[2]);
2624 if ((num < -255) || (num > 255)) {
2625 return -1;
2626 }
2627 if (ldrsel == 0) {
2628 ao->o = 0x50f8000d;
2629 } else
2630 if (ldrsel == B_BIT) {
2631 ao->o = 0x10f8000d;
2632 } else
2633 if (ldrsel == H_BIT) {
2634 ao->o = 0x30f8000d;
2635 } else {
2636 return -1;
2637 }
2638 if (m & S_BIT) {
2639 ao->o |= 1 << 16;
2640 }
2641 if (num < 0) {
2642 num = -num;
2643 } else {
2644 ao->o |= 1 << 1;
2645 }
2646 ao->o |= num << 8;
2647 return mem_32bit_2reg (ao, m);
2648 }
2649 break;
2650 case THUMB_REG_BRACKREG_REGBRACK: {
2651 ut8 reg3 = getregmemend (ao->a[2]);
2652 if (reg3 < 8) {
2653 if (ldrsel == 0) {
2654 ao->o = 0x0058;
2655 } else
2656 if (ldrsel == B_BIT) {
2657 if (m & S_BIT) {
2658 ao->o = 0x0056;
2659 } else {
2660 ao->o = 0x005c;
2661 }
2662 } else
2663 if (ldrsel == H_BIT) {
2664 if (m & S_BIT) {
2665 ao->o = 0x005e;
2666 } else {
2667 ao->o = 0x005a;
2668 }
2669 } else
2670 {
2671 return -1;
2672 }
2673 ao->o |= (reg3 & 0x3) << 14;
2674 ao->o |= (reg3 & 0x4) >> 2;
2675 if (mem_16bit_2reg (ao, m)) {
2676 return 2;
2677 }
2678 }
2679 ao->a[2][strlen (ao->a[2]) -1] = '\0';
2680 ao->a[3] = "lsl 0]";
2681 }
2682 // intentional fallthrough
2683 case THUMB_REG_BRACKREG_REG_SHIFTBRACK: {
2684 ut8 reg3 = getreg (ao->a[2]);
2685 ut32 shift = getshiftmemend (ao->a[3]);
2686
2687 shift >>= 2;
2688 if (shift & 0xffffcfff) {
2689 return -1;
2690 }
2691
2692 if (ldrsel == 0) {
2693 ao->o = 0x50f80000;
2694 } else
2695 if (ldrsel == B_BIT) {
2696 ao->o = 0x10f80000;
2697 } else
2698 if (ldrsel == H_BIT) {
2699 ao->o = 0x30f80000;
2700 } else
2701 {
2702 return -1;
2703 }
2704 if (m & S_BIT) {
2705 ao->o |= 1 << 16;
2706 }
2707 ao->o |= reg3 << 8;
2708 ao->o |= shift;
2709 return mem_32bit_2reg (ao, m);
2710 }
2711 break;
2712 case THUMB_REG_REG_BRACKREGBRACK: {
2713 ao->a[2][strlen (ao->a[2]) -1] = '\0';
2714 ao->a[3] = "0]";
2715 }
2716 // intentional fallthrough
2717 case THUMB_REG_REG_BRACKREG_CONSTBRACK: {
2718 ut8 reg1 = getreg (ao->a[0]);
2719 ut8 reg2 = getreg (ao->a[1]);
2720 ut8 reg3 = getregmemstart (ao->a[2]);
2721 st32 num = getnummemend (ao->a[3]);
2722
2723 if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2724 return -1;
2725 }
2726 ao->o = 0x50e90000;
2727 if (num < 0) {
2728 num = -num;
2729 } else {
2730 ao->o |= 1 << 31;
2731 }
2732 ao->o |= reg1 << 4;
2733 ao->o |= reg2;
2734 ao->o |= reg3 << 24;
2735 ao->o |= (num >> 2) << 8;
2736 return 4;
2737 }
2738 break;
2739 case THUMB_REG_REG_BRACKREGBRACK_CONST: {
2740 ut8 reg1 = getreg (ao->a[0]);
2741 ut8 reg2 = getreg (ao->a[1]);
2742 ut8 reg3 = getregmemstartend (ao->a[2]);
2743 st32 num = getnum (ao->a[3]);
2744 if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2745 return -1;
2746 }
2747 ao->o = 0x70e80000;
2748 if (num < 0) {
2749 num = -num;
2750 } else {
2751 ao->o |= 1 << 31;
2752 }
2753 ao->o |= reg1 << 4;
2754 ao->o |= reg2;
2755 ao->o |= reg3 << 24;
2756 ao->o |= (num >> 2) << 8;
2757 return 4;
2758 }
2759 break;
2760 case THUMB_REG_REG_BRACKREG_CONSTBRACKBANG: {
2761 ut8 reg1 = getreg (ao->a[0]);
2762 ut8 reg2 = getreg (ao->a[1]);
2763 ut8 reg3 = getregmemstart (ao->a[2]);
2764 st32 num = getnummemendbang (ao->a[3]);
2765 if ((num > 1020) || (num < -1020) || (num % 4 != 0) || (ldrsel != D_BIT)) {
2766 return -1;
2767 }
2768 ao->o = 0x70e90000;
2769 if (num < 0) {
2770 num = -num;
2771 } else {
2772 ao->o |= 1 << 31;
2773 }
2774 ao->o |= reg1 << 4;
2775 ao->o |= reg2;
2776 ao->o |= reg3 << 24;
2777 ao->o |= (num >> 2) << 8;
2778 return 4;
2779 }
2780 break;
2781 default:
2782 return -1;
2783 }
2784 } else
2785 if ((m = opmask (ao->op, "ldrex", B_BIT | H_BIT | D_BIT))) {
2786 ut64 argt = thumb_selector (ao->a);
2787 ut32 ldrsel = m & (B_BIT | H_BIT | D_BIT);
2788 switch (argt) {
2789 case THUMB_REG_BRACKREGBRACK: {
2790 ut8 reg1 = getreg (ao->a[0]);
2791 ut8 reg2 = getregmemstartend (ao->a[1]);
2792
2793 if (ldrsel == B_BIT) {
2794 ao->o = 0xd0e84f0f;
2795 ao->o |= reg1 << 4;
2796 ao->o |= reg2 << 24;
2797 return 4;
2798 } else
2799 if (ldrsel == H_BIT) {
2800 ao->o = 0xd0e85f0f;
2801 ao->o |= reg1 << 4;
2802 ao->o |= reg2 << 24;
2803 return 4;
2804 } else
2805 if (ldrsel == 0) {
2806 ao->a[1][strlen (ao->a[1]) - 1] = '\0';
2807 ao->a[2] = "0]";
2808 } else {
2809 return -1;
2810 }
2811 }
2812 // intentional fallthrough
2813 case THUMB_REG_BRACKREG_CONSTBRACK: {
2814 st32 num = getnummemend (ao->a[2]);
2815 if ((ldrsel != 0) || (num < 0) || (num > 1020) || (num % 4 != 0)) {
2816 return -1;
2817 }
2818 ao->o = 0x50e8000f;
2819 ao->o |= (num >> 2) << 8;
2820 return mem_32bit_2reg (ao, m);
2821 }
2822 break;
2823 case THUMB_REG_REG_BRACKREGBRACK: {
2824 ut8 reg1 = getreg (ao->a[0]);
2825 ut8 reg2 = getreg (ao->a[1]);
2826 ut8 reg3 = getregmemstartend (ao->a[2]);
2827 if (!(ldrsel & D_BIT)) {
2828 return -1;
2829 }
2830 ao->o = 0xd0e87f00;
2831 ao->o |= reg1 << 4;
2832 ao->o |= reg2;
2833 ao->o |= reg3 << 24;
2834 return 4;
2835 }
2836 break;
2837 default:
2838 return -1;
2839 }
2840 } else
2841 if ((m = opmask (ao->op, "lsl", S_BIT))) {
2842 ut64 argt = thumb_selector (ao->a);
2843 switch (argt) {
2844 case THUMB_REG_REG_CONST: {
2845 ut8 reg1 = getreg (ao->a[0]);
2846 ut8 reg2 = getreg (ao->a[1]);
2847 ut32 num = getnum (ao->a[2]);
2848 if (num > 32) {
2849 return -1;
2850 }
2851 ao->o = 0x0000;
2852 if (std_16bit_2reg (ao, m)) {
2853 ao->o |= (num & 0x03) << 14;
2854 ao->o |= num >> 2;
2855 return 2;
2856 }
2857 ao->o = 0x4fea0000;
2858 ao->o |= reg1;
2859 ao->o |= reg2 << 8;
2860 ao->o |= (num >> 2) << 4;
2861 ao->o |= (num & 0x3) << 14;
2862 if (m & S_BIT) {
2863 ao->o |= 1 << 28;
2864 }
2865 return 4;
2866 }
2867 break;
2868 case THUMB_REG_REG: {
2869 ao->o = 0x8040;
2870 if (std_16bit_2reg (ao, m)) {
2871 return 2;
2872 }
2873 std_opt_2 (ao);
2874 }
2875 // intentional fallthrough
2876 case THUMB_REG_REG_REG: {
2877 ao->o = 0x00fa00f0;
2878 return std_32bit_3reg (ao, m, false);
2879 }
2880 break;
2881 default:
2882 return -1;
2883 }
2884 } else
2885 if ((m = opmask (ao->op, "lsr", S_BIT))) {
2886 ut64 argt = thumb_selector (ao->a);
2887 switch (argt) {
2888 case THUMB_REG_REG_CONST: {
2889 ut8 reg1 = getreg (ao->a[0]);
2890 ut8 reg2 = getreg (ao->a[1]);
2891 ut32 num = getnum (ao->a[2]);
2892 if (num > 32) {
2893 return -1;
2894 }
2895 ao->o = 0x0008;
2896 if (std_16bit_2reg (ao, m)) {
2897 ao->o |= (num & 0x03) << 14;
2898 ao->o |= num >> 2;
2899 return 2;
2900 }
2901 ao->o = 0x4fea1000;
2902 ao->o |= reg1;
2903 ao->o |= reg2 << 8;
2904 ao->o |= (num >> 2) << 4;
2905 ao->o |= (num & 0x3) << 14;
2906 if (m & S_BIT) {
2907 ao->o |= 1 << 28;
2908 }
2909 return 4;
2910 }
2911 break;
2912 case THUMB_REG_REG: {
2913 ao->o = 0xc040;
2914 if (std_16bit_2reg (ao, m)) {
2915 return 2;
2916 }
2917 std_opt_2 (ao);
2918 }
2919 // intentional fallthrough
2920 case THUMB_REG_REG_REG: {
2921 ao->o = 0x20fa00f0;
2922 return std_32bit_3reg (ao, m, false);
2923 }
2924 break;
2925 default:
2926 return -1;
2927 }
2928 } else
2929 if ((m = opmask (ao->op, "mcr", R_BIT | TWO_BIT))) {
2930 ut64 argt = thumb_selector (ao->a);
2931 switch (argt) {
2932 case THUMB_COPROC_CONST_REG_COREG_COREG: {
2933 ao->a[5] = "0";
2934 }
2935 // intentional fallthrough
2936 case THUMB_COPROC_CONST_REG_COREG_COREG_CONST: {
2937 ut32 coproc = getcoproc (ao->a[0]);
2938 ut32 opc1 = getnum (ao->a[1]);
2939 ut32 reg1 = getreg (ao->a[2]);
2940 ut32 coreg1 = getcoprocreg (ao->a[3]);
2941 ut32 coreg2 = getcoprocreg (ao->a[4]);
2942 ut32 opc2 = getnum (ao->a[5]);
2943
2944 if ((coproc > 15) || (opc1 > 7) || (reg1 > 15) || (coreg1 > 15) || (coreg2 > 15) || (opc2 > 7) || (m & R_BIT)) {
2945 return -1;
2946 }
2947
2948 ao->o = 0x00ee1000;
2949 if (m & TWO_BIT) {
2950 ao->o |= 1 << 20;
2951 }
2952 ao->o |= coproc;
2953 ao->o |= opc1 << 29;
2954 ao->o |= reg1 << 4;
2955 ao->o |= coreg1 << 24;
2956 ao->o |= coreg2 << 8;
2957 ao->o |= opc2 << 13;
2958 return 4;
2959 }
2960 break;
2961 case THUMB_COPROC_CONST_REG_REG_COREG: {
2962 ut32 coproc = getcoproc (ao->a[0]);
2963 ut32 opc = getnum (ao->a[1]);
2964 ut32 reg1 = getreg (ao->a[2]);
2965 ut32 reg2 = getreg (ao->a[3]);
2966 ut32 coreg = getcoprocreg (ao->a[4]);
2967
2968 if ((coproc > 15) || (opc > 15) || (reg1 > 15) || (reg2 > 15) || (coreg > 15) || (!(m & R_BIT))) {
2969 return -1;
2970 }
2971
2972 ao->o = 0x40ec0000;
2973 if (m & TWO_BIT) {
2974 ao->o |= 1 << 20;
2975 }
2976 ao->o |= coproc;
2977 ao->o |= opc << 12;
2978 ao->o |= reg1 << 4;
2979 ao->o |= reg2 << 24;
2980 ao->o |= coreg << 8;
2981 return 4;
2982 }
2983 break;
2984 default:
2985 return -1;
2986 }
2987 } else
2988 if ((m = opmask (ao->op, "mla", 0))) {
2989 ut64 argt = thumb_selector (ao->a);
2990 switch (argt) {
2991 case THUMB_REG_REG_REG_REG: {
2992 ut32 reg4 = getreg (ao->a[3]);
2993 if (reg4 > 15) {
2994 return -1;
2995 }
2996 ao->o = 0x00fb0000;
2997 ao->o |= reg4 << 4;
2998
2999 return std_32bit_3reg (ao, m, false);
3000 }
3001 break;
3002 default:
3003 return -1;
3004 }
3005 } else
3006 if ((m = opmask (ao->op, "mls", 0))) {
3007 ut64 argt = thumb_selector (ao->a);
3008 switch (argt) {
3009 case THUMB_REG_REG_REG_REG: {
3010 ut32 reg4 = getreg (ao->a[3]);
3011 if (reg4 > 15) {
3012 return -1;
3013 }
3014 ao->o = 0x00fb1000;
3015 ao->o |= reg4 << 4;
3016
3017 return std_32bit_3reg (ao, m, false);
3018 }
3019 break;
3020 default:
3021 return -1;
3022 }
3023 } else
3024 if ((m = opmask (ao->op, "mov", S_BIT | W_BIT | T_BIT))) {
3025 ut64 argt = thumb_selector (ao->a);
3026 switch (argt) {
3027 case THUMB_REG_CONST: {
3028 ut32 reg1 = getreg (ao->a[0]);
3029 err = false;
3030 ut32 num = getnum (ao->a[1]);
3031
3032 if (reg1 > 15) {
3033 return -1;
3034 }
3035
3036 if ((m & W_BIT) || (m & T_BIT)) {
3037 ut32 wnum = getnum (ao->a[1]);
3038 if (wnum > 65535) {
3039 return -1;
3040 }
3041 ao->o = 0x40f20000;
3042 if (m & T_BIT) {
3043 ao->o |= 1 << 31;
3044 }
3045 ao->o |= reg1;
3046 ao->o |= getthzeroimmed16 (wnum);
3047 return 4;
3048 }
3049
3050 if (err) {
3051 return -1;
3052 }
3053
3054 if ((num < 256) && (reg1 < 8) && (!(m & DOTW_BIT))) {
3055 ao->o = 0x0020;
3056 ao->o |= reg1;
3057 ao->o |= num << 8;
3058 return 2;
3059 }
3060
3061 ao->o = 0x4ff00000;
3062 ao->o |= reg1;
3063 ao->o |= getthimmed12 (ao->a[1]);
3064 if (m & S_BIT) {
3065 ao->o |= 1 << 28;
3066 }
3067 return 4;
3068 }
3069 break;
3070 case THUMB_REG_REG: {
3071 ut32 reg1 = getreg (ao->a[0]);
3072 ut32 reg2 = getreg (ao->a[1]);
3073
3074 if ((reg1 > 15) || (reg2 > 15)) {
3075 return -1;
3076 }
3077
3078 if ((!(m & S_BIT)) && (!(m & DOTW_BIT))) {
3079 ao->o = 0x0046;
3080 ao->o |= (reg1 & 0x7) << 8;
3081 ao->o |= (reg1 & 0x8) << 12;
3082 ao->o |= reg2 << 11;
3083 return 2;
3084 }
3085
3086 if ((reg1 < 8) && (reg2 < 8) && (!(m & DOTW_BIT))) {
3087 ao->o = 0;
3088 ao->o |= reg1 << 8;
3089 ao->o |= reg2 << 11;
3090 return 2;
3091 }
3092
3093 ao->o = 0x4fea0000;
3094 ao->o |= reg1;
3095 ao->o |= reg2 << 8;
3096 if (m & S_BIT) {
3097 ao->o |= 1 << 28;
3098 }
3099 return 4;
3100 }
3101 break;
3102 default:
3103 return -1;
3104 }
3105 } else
3106 if ((m = opmask (ao->op, "mrc", TWO_BIT))) {
3107 ut64 argt = thumb_selector (ao->a);
3108 switch (argt) {
3109 case THUMB_COPROC_CONST_REG_COREG_COREG: {
3110 ao->a[5] = "0";
3111 }
3112 // intentional fallthrough
3113 case THUMB_COPROC_CONST_REG_COREG_COREG_CONST: {
3114 ut32 coproc = getcoproc (ao->a[0]);
3115 ut32 opc1 = getnum (ao->a[1]);
3116 ut32 reg1 = getreg (ao->a[2]);
3117 ut32 coreg1 = getcoprocreg (ao->a[3]);
3118 ut32 coreg2 = getcoprocreg (ao->a[4]);
3119 ut32 opc2 = getnum (ao->a[5]);
3120
3121 if ((coproc > 15) || (opc1 > 7) || (reg1 > 15) || (coreg1 > 15) || (coreg2 > 15) || (opc2 > 7)) {
3122 return -1;
3123 }
3124
3125 ao->o = 0x10ee1000;
3126 if (m & TWO_BIT) {
3127 ao->o |= 1 << 20;
3128 }
3129 ao->o |= coproc;
3130 ao->o |= opc1 << 29;
3131 ao->o |= reg1 << 4;
3132 ao->o |= coreg1 << 24;
3133 ao->o |= coreg2 << 8;
3134 ao->o |= opc2 << 13;
3135 return 4;
3136 }
3137 break;
3138 default:
3139 return -1;
3140 }
3141 } else
3142 if ((m = opmask (ao->op, "mrrc", TWO_BIT))) {
3143 ut64 argt = thumb_selector (ao->a);
3144 switch (argt) {
3145 case THUMB_COPROC_CONST_REG_REG_COREG: {
3146 ut32 coproc = getcoproc (ao->a[0]);
3147 ut32 opc = getnum (ao->a[1]);
3148 ut32 reg1 = getreg (ao->a[2]);
3149 ut32 reg2 = getreg (ao->a[3]);
3150 ut32 coreg = getcoprocreg (ao->a[4]);
3151
3152 if ((coproc > 15) || (opc > 15) || (reg1 > 15) || (reg2 > 15) || (coreg > 15)) {
3153 return -1;
3154 }
3155
3156 ao->o = 0x50ec0000;
3157 if (m & TWO_BIT) {
3158 ao->o |= 1 << 20;
3159 }
3160 ao->o |= coproc;
3161 ao->o |= opc << 12;
3162 ao->o |= reg1 << 4;
3163 ao->o |= reg2 << 24;
3164 ao->o |= coreg << 8;
3165 return 4;
3166 }
3167 break;
3168 default:
3169 return -1;
3170 }
3171 } else
3172 if ((m = opmask (ao->op, "mrs", 0))) {
3173 ut64 argt = thumb_selector (ao->a);
3174 switch (argt) {
3175 case THUMB_REG_OTHER: {
3176 ut32 reg1 = getreg (ao->a[0]);
3177 r_str_case (ao->a[1], false);
3178
3179 if (reg1 > 15) {
3180 return -1;
3181 }
3182
3183 if ((!strcmp(ao->a[1], "cpsr")) || (!strcmp(ao->a[1], "apsr"))) {
3184 ao->o = 0xeff30080;
3185 ao->o |= reg1;
3186 return 4;
3187 }
3188
3189 if (!strcmp(ao->a[1], "spsr")) {
3190 ao->o = 0xfff30080;
3191 ao->o |= reg1;
3192 return 4;
3193 }
3194
3195 return -1;
3196 }
3197 break;
3198 default:
3199 return -1;
3200 }
3201 } else
3202 if ((m = opmask (ao->op, "msr", 0))) {
3203 ut64 argt = thumb_selector (ao->a);
3204 switch (argt) {
3205 case THUMB_OTHER_REG: {
3206 r_str_case (ao->a[0], false);
3207 ut8 spsr = 0;
3208 ut8 bank = interpret_msrbank (ao->a[0], &spsr);
3209 ut32 reg1 = getreg (ao->a[1]);
3210
3211 if ((bank == 0) || (reg1 > 15)) {
3212 return -1;
3213 }
3214
3215 ao->o = 0x80f30080;
3216 ao->o |= reg1 << 24;
3217 ao->o |= bank;
3218 if (spsr != 0) {
3219 ao->o |= 1 << 28;
3220 }
3221 return 4;
3222 }
3223 break;
3224 default:
3225 return -1;
3226 }
3227 } else
3228 if ((m = opmask (ao->op, "mul", 0))) {
3229 ut64 argt = thumb_selector (ao->a);
3230 switch (argt) {
3231 case THUMB_REG_REG: {
3232 std_opt_2 (ao);
3233 }
3234 // intentional fallthrough
3235 case THUMB_REG_REG_REG: {
3236 ut8 reg1 = getreg (ao->a[0]);
3237 ut8 reg3 = getreg (ao->a[2]);
3238
3239 ao->o = 0x4043;
3240 if ((reg1 == reg3) && (std_16bit_2reg (ao, m))) {
3241 return 2;
3242 }
3243
3244 ao->o = 0x00fb00f0;
3245 return std_32bit_3reg (ao, m, false);
3246 }
3247 break;
3248 default:
3249 return -1;
3250 }
3251 } else
3252 if ((m = opmask (ao->op, "mvn", S_BIT))) {
3253 ut64 argt = thumb_selector (ao->a);
3254 switch (argt) {
3255 case THUMB_REG_CONST: {
3256 ut8 reg1 = getreg (ao->a[0]);
3257 err = false;
3258 ut32 num = getthimmed12 (ao->a[1]);
3259
3260 if ((reg1 > 15) || err) {
3261 return -1;
3262 }
3263
3264 ao->o = 0x6ff00000;
3265 ao->o |= reg1;
3266 ao->o |= num;
3267 if (m & S_BIT) {
3268 ao->o |= 1 << 28;
3269 }
3270 return 4;
3271 }
3272 break;
3273 case THUMB_REG_REG: {
3274 ao->a[2] = "lsl 0";
3275 }
3276 // intentional fallthrough
3277 case THUMB_REG_REG_SHIFT: {
3278 ut8 reg1 = getreg (ao->a[0]);
3279 ut8 reg2 = getreg (ao->a[1]);
3280 ut32 shift = thumb_getshift (ao->a[2]);
3281
3282 if ((reg1 > 15) || (reg2 > 15)) {
3283 return -1;
3284 }
3285
3286 ao->o = 0xc043;
3287 if ((shift == 0) && (std_16bit_2reg (ao, m))) {
3288 return 2;
3289 }
3290
3291 ao->o = 0x6fea0000;
3292 ao->o |= reg1;
3293 ao->o |= reg2 << 8;
3294 ao->o |= shift;
3295 if (m & S_BIT) {
3296 ao->o |= 1 << 28;
3297 }
3298 return 4;
3299 }
3300 break;
3301 default:
3302 return -1;
3303 }
3304 } else
3305 if ((m = opmask (ao->op, "nop", 0))) {
3306 ut64 argt = thumb_selector (ao->a);
3307 switch (argt) {
3308 case THUMB_NONE: {
3309 if (m & DOTW_BIT) {
3310 ao->o = 0xaff30080;
3311 return 4;
3312 }
3313 ao->o = 0x00bf;
3314 return 2;
3315 }
3316 break;
3317 default:
3318 return -1;
3319 }
3320 } else
3321 if ((m = opmask (ao->op, "orn", S_BIT))) {
3322 ut64 argt = thumb_selector (ao->a);
3323 switch (argt) {
3324 case THUMB_REG_CONST: {
3325 std_opt_2 (ao);
3326 }
3327 // intentional fallthrough
3328 case THUMB_REG_REG_CONST: {
3329 err = false;
3330 ut32 num = getthimmed12 (ao->a[2]);
3331
3332 if (err) {
3333 return -1;
3334 }
3335
3336 ao->o = 0x60f00000;
3337 ao->o |= num;
3338 return (std_32bit_2reg (ao, m, false));
3339 }
3340 break;
3341 case THUMB_REG_REG: {
3342 std_opt_2 (ao);
3343 }
3344 // intentional fallthrough
3345 case THUMB_REG_REG_REG: {
3346 ao->a[3] = "lsl 0";
3347 }
3348 // intentional fallthrough
3349 case THUMB_REG_REG_SHIFT: {
3350 if (ao->a[3] == NULL) { // double fallthrough
3351 std_opt_3 (ao);
3352 }
3353 }
3354 // intentional fallthrough
3355 case THUMB_REG_REG_REG_SHIFT: {
3356 ao->o = 0x60ea0000;
3357 return std_32bit_3reg (ao, m, true);
3358 }
3359 break;
3360 default:
3361 return -1;
3362 }
3363 } else
3364 if ((m = opmask (ao->op, "orr", S_BIT))) {
3365 ut64 argt = thumb_selector (ao->a);
3366 switch (argt) {
3367 case THUMB_REG_CONST: {
3368 std_opt_2 (ao);
3369 }
3370 // intentional fallthrough
3371 case THUMB_REG_REG_CONST: {
3372 err = false;
3373 ut32 num = getthimmed12 (ao->a[2]);
3374
3375 if (err) {
3376 return -1;
3377 }
3378
3379 ao->o = 0x40f00000;
3380 ao->o |= num;
3381 return std_32bit_2reg (ao, m, false);
3382 }
3383 break;
3384 case THUMB_REG_REG: {
3385 ao->o = 0x0043;
3386 if (std_16bit_2reg (ao, m)) {
3387 return 2;
3388 }
3389 std_opt_2 (ao);
3390 }
3391 // intentional fallthrough
3392 case THUMB_REG_REG_REG: {
3393 ao->a[3] = "lsl 0";
3394 }
3395 // intentional fallthrough
3396 case THUMB_REG_REG_SHIFT: {
3397 if (ao->a[3] == NULL) { // double fallthrough
3398 std_opt_3 (ao);
3399 }
3400 }
3401 // intentional fallthrough
3402 case THUMB_REG_REG_REG_SHIFT: {
3403 ao->o = 0x40ea0000;
3404 return (std_32bit_3reg (ao, m, true));
3405 }
3406 break;
3407 default:
3408 return -1;
3409 }
3410 } else
3411 if ((m = opmask (ao->op, "pkh", BT_BIT | TB_BIT))) {
3412 ut64 argt = thumb_selector (ao->a);
3413 switch (argt) {
3414 case THUMB_REG_REG: {
3415 std_opt_2 (ao);
3416 }
3417 // intentional fallthrough
3418 case THUMB_REG_REG_REG: {
3419 if (m & TB_BIT) {
3420 ao->a[3] = "asr 0";
3421 } else
3422 if (m & BT_BIT) {
3423 ao->a[3] = "lsl 0";
3424 } else {
3425 return -1;
3426 }
3427 }
3428 // intentional fallthrough
3429 case THUMB_REG_REG_SHIFT: {
3430 if (ao->a[3] == NULL) { // double fallthrough
3431 std_opt_3 (ao);
3432 }
3433 }
3434 // intentional fallthrough
3435 case THUMB_REG_REG_REG_SHIFT: {
3436 ut32 shift = thumb_getshift (ao->a[3]);
3437
3438 if (((m & TB_BIT) && ((shift & 0x00003000) != 0x00002000)) || ((m & BT_BIT) && ((shift & 0x00003000) != 0)) || ((m & (TB_BIT | BT_BIT)) == 0)) {
3439 return -1;
3440 }
3441
3442 ao->o = 0xc0ea0000;
3443 return (std_32bit_3reg (ao, m, true));
3444 }
3445 break;
3446 default:
3447 return -1;
3448 }
3449 } else
3450 if ((m = opmask (ao->op, "pld", 0))) {
3451 ut64 argt = thumb_selector (ao->a);
3452 switch (argt) {
3453 case THUMB_BRACKREG_CONSTBRACK: {
3454 ut8 reg1 = getregmemstart (ao->a[0]);
3455 st32 num = getnummemend (ao->a[1]);
3456
3457 if (reg1 == 15) {
3458 if ((num < -4095) || (num > 4095)) {
3459 return -1;
3460 }
3461 ao->o = 0x1ff800f0;
3462 if (num > 0) {
3463 ao->o |= 1 << 31;
3464 } else {
3465 num = -num;
3466 }
3467 ao->o |= (num & 0x0ff) << 8;
3468 ao->o |= (num & 0xf00) >> 8;
3469 return 4;
3470 }
3471
3472 if ((reg1 > 15) || (num < -255) || (num > 4095)) {
3473 return -1;
3474 }
3475
3476 if (num > 0) {
3477 ao->o = 0x90f800f0;
3478 ao->o |= (num & 0x0ff) << 8;
3479 ao->o |= (num & 0xf00) >> 8;
3480 ao->o |= reg1 << 24;
3481 return 4;
3482 }
3483 num = -num;
3484 ao->o = 0x10f800fc;
3485 ao->o |= num << 8;
3486 ao->o |= reg1 << 24;
3487 return 4;
3488 }
3489 break;
3490 case THUMB_BRACKREG_REGBRACK: {
3491 ao->a[1][strlen (ao->a[1]) - 1] = '\0';
3492 ao->a[2] = "lsl 0]";
3493 }
3494 // intentional fallthrough
3495 case THUMB_BRACKREG_REG_SHIFTBRACK: {
3496 ut8 reg1 = getregmemstart (ao->a[0]);
3497 ut8 reg2 = getreg (ao->a[1]);
3498 ut32 shift = getshiftmemend (ao->a[2]) >> 2;
3499
3500 if ((reg1 > 15) || (reg2 > 15) || ((shift & 0xffffcfff) != 0)) {
3501 return -1;
3502 }
3503
3504 ao->o = 0x10f800f0;
3505 ao->o |= reg1 << 24;
3506 ao->o |= reg2 << 8;
3507 ao->o |= shift;
3508 return 4;
3509 }
3510 break;
3511 default:
3512 return -1;
3513 }
3514 } else
3515 if ((m = opmask (ao->op, "pli", 0))) {
3516 ut64 argt = thumb_selector (ao->a);
3517 switch (argt) {
3518 case THUMB_BRACKREG_CONSTBRACK: {
3519 ut8 reg1 = getregmemstart (ao->a[0]);
3520 st32 num = getnummemend (ao->a[1]);
3521
3522 if (reg1 == 15) {
3523 if ((num < -4095) || (num > 4095)) {
3524 return -1;
3525 }
3526 ao->o = 0x1ff900f0;
3527 if (num > 0) {
3528 ao->o |= 1 << 31;
3529 } else {
3530 num = -num;
3531 }
3532 ao->o |= (num & 0x0ff) << 8;
3533 ao->o |= (num & 0xf00) >> 8;
3534 return 4;
3535 }
3536
3537 if ((reg1 > 15) || (num < -255) || (num > 4095)) {
3538 return -1;
3539 }
3540
3541 if (num > 0) {
3542 ao->o = 0x90f900f0;
3543 ao->o |= (num & 0x0ff) << 8;
3544 ao->o |= (num & 0xf00) >> 8;
3545 ao->o |= reg1 << 24;
3546 return 4;
3547 }
3548 num = -num;
3549 ao->o = 0x10f900fc;
3550 ao->o |= num << 8;
3551 ao->o |= reg1 << 24;
3552 return 4;
3553 }
3554 break;
3555 case THUMB_BRACKREG_REGBRACK: {
3556 ao->a[1][strlen (ao->a[1]) -1] = '\0';
3557 ao->a[2] = "lsl 0]";
3558 }
3559 // intentional fallthrough
3560 case THUMB_BRACKREG_REG_SHIFTBRACK: {
3561 ut8 reg1 = getregmemstart (ao->a[0]);
3562 ut8 reg2 = getreg (ao->a[1]);
3563 ut32 shift = getshiftmemend (ao->a[2]) >> 2;
3564
3565 if ((reg1 > 15) || (reg2 > 15) || ((shift & 0xffffcfff) != 0)) {
3566 return -1;
3567 }
3568
3569 ao->o = 0x10f900f0;
3570 ao->o |= reg1 << 24;
3571 ao->o |= reg2 << 8;
3572 ao->o |= shift;
3573 return 4;
3574 }
3575 break;
3576 default:
3577 return -1;
3578 }
3579 } else
3580 if ((m = opmask (ao->op, "pop", 0))) {
3581 ut64 argt = thumb_selector (ao->a);
3582 switch (argt) {
3583 case THUMB_LIST: {
3584 st32 list = getreglist (ao->a[0]);
3585 if ((list <= 0) || ((list & (1 << 13)) != 0)) {
3586 return -1;
3587 }
3588 if ((!(m & DOTW_BIT)) && ((list & 0x00007f00) == 0)) {
3589 ao->o = 0x00bc;
3590 ao->o |= (list & 0x8000) >> 15;
3591 ao->o |= (list & 0xff) << 8;
3592 return 2;
3593 }
3594 ao->o = 0xbde80000;
3595 ao->o |= (list & 0xff00) >> 8;
3596 ao->o |= (list & 0xff) << 8;
3597 return 4;
3598 }
3599 break;
3600 default:
3601 return -1;
3602 }
3603 } else
3604 if ((m = opmask (ao->op, "push", 0))) {
3605 ut64 argt = thumb_selector (ao->a);
3606 switch (argt) {
3607 case THUMB_LIST: {
3608 st32 list = getreglist (ao->a[0]);
3609 if ((list <= 0) || ((list & 0x0000a000) != 0)) {
3610 return -1;
3611 }
3612 if ((!(m & DOTW_BIT)) && ((list & 0x00001f00) == 0)) {
3613 ao->o = 0x00b4;
3614 ao->o |= (list & 0x4000) >> 14;
3615 ao->o |= (list & 0xff) << 8;
3616 return 2;
3617 }
3618 ao->o = 0x2de90000;
3619 ao->o |= (list & 0xff00) >> 8;
3620 ao->o |= (list & 0xff) << 8;
3621 return 4;
3622 }
3623 break;
3624 default:
3625 return -1;
3626 }
3627 } else
3628 if ((m = opmask (ao->op, "qadd", EIGHT_BIT | SIXTEEN_BIT))) {
3629 ut64 argt = thumb_selector (ao->a);
3630 switch (argt) {
3631 case THUMB_REG_REG: {
3632 std_opt_2 (ao);
3633 }
3634 // intentional fallthrough
3635 case THUMB_REG_REG_REG: {
3636 if (m & SIXTEEN_BIT) {
3637 ao->o = 0x90fa10f0;
3638 } else
3639 if (m & EIGHT_BIT) {
3640 ao->o = 0x80fa10f0;
3641 } else {
3642 ao->o = 0x80fa80f0;
3643 }
3644
3645 return std_32bit_3reg (ao, m, false);
3646 }
3647 break;
3648 default:
3649 return -1;
3650 }
3651 } else
3652 if ((m = opmask (ao->op, "qasx", 0))) {
3653 ut64 argt = thumb_selector (ao->a);
3654 switch (argt) {
3655 case THUMB_REG_REG: {
3656 std_opt_2 (ao);
3657 }
3658 // intentional fallthrough
3659 case THUMB_REG_REG_REG: {
3660 ao->o = 0xa0fa10f0;
3661 return std_32bit_3reg (ao, m, false);
3662 }
3663 break;
3664 default:
3665 return -1;
3666 }
3667 } else
3668 if ((m = opmask (ao->op, "qdadd", 0))) {
3669 ut64 argt = thumb_selector (ao->a);
3670 switch (argt) {
3671 case THUMB_REG_REG: {
3672 std_opt_2 (ao);
3673 }
3674 // intentional fallthrough
3675 case THUMB_REG_REG_REG: {
3676 ao->o = 0x80fa90f0;
3677 return std_32bit_3reg (ao, m, false);
3678 }
3679 break;
3680 default:
3681 return -1;
3682 }
3683 } else
3684 if ((m = opmask (ao->op, "qdsub", 0))) {
3685 ut64 argt = thumb_selector (ao->a);
3686 switch (argt) {
3687 case THUMB_REG_REG: {
3688 std_opt_2 (ao);
3689 }
3690 // intentional fallthrough
3691 case THUMB_REG_REG_REG: {
3692 ao->o = 0x80fab0f0;
3693 return std_32bit_3reg (ao, m, false);
3694 }
3695 break;
3696 default:
3697 return -1;
3698 }
3699 } else
3700 if ((m = opmask (ao->op, "qsax", 0))) {
3701 ut64 argt = thumb_selector (ao->a);
3702 switch (argt) {
3703 case THUMB_REG_REG: {
3704 std_opt_2 (ao);
3705 }
3706 // intentional fallthrough
3707 case THUMB_REG_REG_REG: {
3708 ao->o = 0xe0fa10f0;
3709 return std_32bit_3reg (ao, m, false);
3710 }
3711 break;
3712 default:
3713 return -1;
3714 }
3715 } else
3716 if ((m = opmask (ao->op, "qsub", EIGHT_BIT | SIXTEEN_BIT))) {
3717 ut64 argt = thumb_selector (ao->a);
3718 switch (argt) {
3719 case THUMB_REG_REG: {
3720 std_opt_2 (ao);
3721 }
3722 // intentional fallthrough
3723 case THUMB_REG_REG_REG: {
3724 if (m & SIXTEEN_BIT) {
3725 ao->o = 0xd0fa10f0;
3726 } else
3727 if (m & EIGHT_BIT) {
3728 ao->o = 0xc0fa10f0;
3729 } else {
3730 ao->o = 0x80faa0f0;
3731 }
3732 return std_32bit_3reg (ao, m, false);
3733 }
3734 break;
3735 default:
3736 return -1;
3737 }
3738 } else
3739 if ((m = opmask (ao->op, "rbit", 0))) {
3740 ut64 argt = thumb_selector (ao->a);
3741 switch (argt) {
3742 case THUMB_REG_REG: {
3743 ao->a[2] = ao->a[1];
3744 ao->o = 0x90faa0f0;
3745 return std_32bit_3reg (ao, m, false);
3746 }
3747 break;
3748 default:
3749 return -1;
3750 }
3751 } else
3752 if ((m = opmask (ao->op, "rev", SIXTEEN_BIT | SH_BIT))) {
3753 ut64 argt = thumb_selector (ao->a);
3754 switch (argt) {
3755 case THUMB_REG_REG: {
3756 if (m & SIXTEEN_BIT) {
3757 ao->o = 0x40ba;
3758 } else
3759 if (m & SH_BIT) {
3760 ao->o = 0xc0ba;
3761 } else {
3762 ao->o = 0x00ba;
3763 }
3764
3765 if (std_16bit_2reg (ao, m)) {
3766 return 2;
3767 }
3768
3769 if (m & SIXTEEN_BIT) {
3770 ao->o = 0x90fa90f0;
3771 } else
3772 if (m & SH_BIT) {
3773 ao->o = 0x90fab0f0;
3774 } else {
3775 ao->o = 0x90fa80f0;
3776 }
3777 ao->a[2] = ao->a[1];
3778 return std_32bit_3reg (ao, m, false);
3779 }
3780 break;
3781 default:
3782 return -1;
3783 }
3784 } else
3785 if ((m = opmask (ao->op, "rfe", IA_BIT | FD_BIT | DB_BIT | EA_BIT))) {
3786 ut64 argt = thumb_selector (ao->a);
3787 ut32 wb = 0;
3788 switch (argt) {
3789 case THUMB_REGBANG: {
3790 ao->a[0][strlen (ao->a[0]) - 1] = '\0';
3791 wb = 0x20000000;
3792 }
3793 // intentional fallthrough
3794 case THUMB_REG: {
3795 ut8 reg1 = getreg (ao->a[0]);
3796
3797 if (reg1 > 15) {
3798 return -1;
3799 }
3800
3801 if ((m & DB_BIT) || (m & EA_BIT)) {
3802 ao->o = 0x10e800c0;
3803 } else {
3804 ao->o = 0x90e900c0;
3805 }
3806
3807 ao->o |= reg1 << 24;
3808 ao->o |= wb;
3809 return 4;
3810 }
3811 break;
3812 default:
3813 return -1;
3814 }
3815 } else
3816 if ((m = opmask (ao->op, "ror", S_BIT))) {
3817 ut64 argt = thumb_selector (ao->a);
3818 switch (argt) {
3819 case THUMB_REG_REG_CONST: {
3820 ut8 reg1 = getreg (ao->a[0]);
3821 ut8 reg2 = getreg (ao->a[1]);
3822 ut32 num = getnum (ao->a[2]);
3823
3824 if ((reg1 > 15) || (reg2 > 15) || (num > 31) || (num < 1)) {
3825 return -1;
3826 }
3827
3828 ao->o = 0x4fea3000;
3829 ao->o |= reg1;
3830 ao->o |= reg2 << 8;
3831 ao->o |= (num & 0x3) << 14;
3832 ao->o |= (num & 0x1c) << 2;
3833 if (m & S_BIT) {
3834 ao->o |= 1 << 28;
3835 }
3836 return 4;
3837 }
3838 break;
3839 case THUMB_REG_REG: {
3840 ao->o = 0xc041;
3841 if (std_16bit_2reg (ao, m)) {
3842 return 2;
3843 }
3844 std_opt_2 (ao);
3845 }
3846 // intentional fallthrough
3847 case THUMB_REG_REG_REG: {
3848 ao->o = 0x60fa00f0;
3849 return (std_32bit_3reg (ao, m, false));
3850 }
3851 break;
3852 default:
3853 return -1;
3854 }
3855 } else
3856 if ((m = opmask (ao->op, "rrx", S_BIT))) {
3857 ut64 argt = thumb_selector (ao->a);
3858 switch (argt) {
3859 case THUMB_REG_REG: {
3860 ut8 reg1 = getreg (ao->a[0]);
3861 ut8 reg2 = getreg (ao->a[1]);
3862
3863 if ((reg1 > 15) || (reg2 > 15)) {
3864 return -1;
3865 }
3866
3867 ao->o = 0x4fea3000;
3868 ao->o |= reg1;
3869 ao->o |= reg2 << 8;
3870 if (m & S_BIT) {
3871 ao->o |= 1 << 28;
3872 }
3873 return 4;
3874 }
3875 break;
3876 default:
3877 return -1;
3878 }
3879 } else
3880 if ((m = opmask (ao->op, "rsb", S_BIT))) {
3881 ut64 argt = thumb_selector (ao->a);
3882 switch (argt) {
3883 case THUMB_REG_CONST: {
3884 std_opt_2 (ao);
3885 }
3886 // intentional fallthrough
3887 case THUMB_REG_REG_CONST: {
3888 err = false;
3889 ut32 num = getthimmed12 (ao->a[2]);
3890
3891 if (err) {
3892 return -1;
3893 }
3894
3895 ao->o = 0x4042;
3896 if ((num == 0) && std_16bit_2reg (ao, m)) {
3897 return 2;
3898 }
3899
3900 ao->o = 0xc0f10000;
3901 ao->o |= num;
3902 return (std_32bit_2reg (ao, m, false));
3903 }
3904 break;
3905 case THUMB_REG_REG: {
3906 std_opt_2 (ao);
3907 }
3908 // intentional fallthrough
3909 case THUMB_REG_REG_REG: {
3910 ao->a[3] = "lsl 0";
3911 }
3912 // intentional fallthrough
3913 case THUMB_REG_REG_SHIFT: {
3914 if (ao->a[3] == NULL) { // double fallthrough
3915 std_opt_3 (ao);
3916 }
3917 }
3918 // intentional fallthrough
3919 case THUMB_REG_REG_REG_SHIFT: {
3920 ao->o = 0xc0eb0000;
3921 return (std_32bit_3reg (ao, m, true));
3922 }
3923 break;
3924 default:
3925 return -1;
3926 }
3927 } else
3928 if ((m = opmask (ao->op, "sadd", EIGHT_BIT | SIXTEEN_BIT))) {
3929 ut64 argt = thumb_selector (ao->a);
3930 switch (argt) {
3931 case THUMB_REG_REG: {
3932 std_opt_2 (ao);
3933 }
3934 // intentional fallthrough
3935 case THUMB_REG_REG_REG: {
3936 if (m & SIXTEEN_BIT) {
3937 ao->o = 0x90fa00f0;
3938 } else
3939 if (m & EIGHT_BIT) {
3940 ao->o = 0x80fa00f0;
3941 } else {
3942 return -1;
3943 }
3944 return std_32bit_3reg (ao, m, false);
3945 }
3946 break;
3947 default:
3948 return -1;
3949 }
3950 } else
3951 if ((m = opmask (ao->op, "sasx", 0))) {
3952 ut64 argt = thumb_selector (ao->a);
3953 switch (argt) {
3954 case THUMB_REG_REG: {
3955 std_opt_2 (ao);
3956 }
3957 // intentional fallthrough
3958 case THUMB_REG_REG_REG: {
3959 ao->o = 0xa0fa00f0;
3960 return std_32bit_3reg (ao, m, false);
3961 }
3962 break;
3963 default:
3964 return -1;
3965 }
3966 } else
3967 if ((m = opmask (ao->op, "sbc", S_BIT))) {
3968 ut64 argt = thumb_selector (ao->a);
3969 switch (argt) {
3970 case THUMB_REG_REG: {
3971 ao->o = 0x8041;
3972 if (std_16bit_2reg (ao, m)) {
3973 return 2;
3974 }
3975 std_opt_2 (ao);
3976 }
3977 // intentional fallthrough
3978 case THUMB_REG_REG_REG: {
3979 ao->a[3] = "lsl 0";
3980 }
3981 // intentional fallthrough
3982 case THUMB_REG_REG_SHIFT: {
3983 if (ao->a[3] == NULL) { // double fallthrough
3984 std_opt_3 (ao);
3985 }
3986 }
3987 // intentional fallthrough
3988 case THUMB_REG_REG_REG_SHIFT: {
3989 ao->o = 0x60eb0000;
3990 return std_32bit_3reg (ao, m, true);
3991 }
3992 break;
3993 case THUMB_REG_CONST: {
3994 std_opt_2 (ao);
3995 }
3996 // intentional fallthrough
3997 case THUMB_REG_REG_CONST: {
3998 ao->o = 0x60f10000;
3999 err = false;
4000 ut32 num = getthimmed12 (ao->a[2]);
4001
4002 if (err) {
4003 return -1;
4004 }
4005 ao->o |= num;
4006
4007 return std_32bit_2reg (ao, m, false);
4008 }
4009 break;
4010 default:
4011 return -1;
4012 }
4013 } else
4014 if (( m = opmask (ao->op, "sbfx", 0) )) {
4015 ut64 argt = thumb_selector (ao->a);
4016 switch (argt) {
4017 case THUMB_REG_REG_CONST_CONST: {
4018 ut32 lsb = getnum (ao->a[2]);
4019 ut32 width = getnum (ao->a[3]);
4020 ut32 msb = lsb + width - 1;
4021 if ((lsb > 31) || (msb > 31)) {
4022 return -1;
4023 }
4024 ao->o = 0x40f30000;
4025 ao->o |= ((lsb & 0x1c) << 2);
4026 ao->o |= ((lsb & 0x3) << 14);
4027 ao->o |= ((width - 1) << 8);
4028 return std_32bit_2reg (ao, m, false);
4029 }
4030 break;
4031 default:
4032 return -1;
4033 }
4034 } else
4035 if ((m = opmask (ao->op, "sdiv", 0))) {
4036 ut64 argt = thumb_selector (ao->a);
4037 switch (argt) {
4038 case THUMB_REG_REG: {
4039 std_opt_2 (ao);
4040 }
4041 // intentional fallthrough
4042 case THUMB_REG_REG_REG: {
4043 ao->o = 0x90fbf0f0;
4044 return std_32bit_3reg (ao, m, false);
4045 }
4046 break;
4047 default:
4048 return -1;
4049 }
4050 } else
4051 if ((m = opmask (ao->op, "sel", 0))) {
4052 ut64 argt = thumb_selector (ao->a);
4053 switch (argt) {
4054 case THUMB_REG_REG: {
4055 std_opt_2 (ao);
4056 }
4057 // intentional fallthrough
4058 case THUMB_REG_REG_REG: {
4059 ao->o = 0xa0fa80f0;
4060 return std_32bit_3reg (ao, m, false);
4061 }
4062 break;
4063 default:
4064 return -1;
4065 }
4066 } else
4067 if ((m = opmask (ao->op, "setend", 0))) {
4068 ut64 argt = thumb_selector (ao->a);
4069 switch (argt) {
4070 case THUMB_OTHER: {
4071 r_str_case (ao->a[0], false);
4072 ao->o = 0x50b6;
4073 if (!(strcmpnull (ao->a[0], "be"))) {
4074 ao->o |= 1 << 11;
4075 return 2;
4076 } else
4077 if (!(strcmpnull (ao->a[0], "le"))) {
4078 return 2;
4079 } else {
4080 return -1;
4081 }
4082 break;
4083 }
4084 default:
4085 return -1;
4086 }
4087 } else
4088 if ((m = opmask (ao->op, "sev", 0))) {
4089 ut64 argt = thumb_selector (ao->a);
4090 switch (argt) {
4091 case THUMB_NONE:
4092 if (m & DOTW_BIT) {
4093 ao->o = 0xaff30480;
4094 return 4;
4095 } else {
4096 ao->o = 0x40bf;
4097 return 2;
4098 }
4099 break;
4100 default:
4101 return -1;
4102 }
4103 } else
4104 if ((m = opmask (ao->op, "shadd", EIGHT_BIT | SIXTEEN_BIT ))) {
4105 ut64 argt = thumb_selector (ao->a);
4106 switch (argt) {
4107 case THUMB_REG_REG: {
4108 std_opt_2 (ao);
4109 }
4110 // intentional fallthrough
4111 case THUMB_REG_REG_REG: {
4112 if (m & SIXTEEN_BIT) {
4113 ao->o = 0x90fa20f0;
4114 } else
4115 if (m & EIGHT_BIT) {
4116 ao->o = 0x80fa20f0;
4117 } else {
4118 return -1;
4119 }
4120 return std_32bit_3reg (ao, m, false);
4121 }
4122 break;
4123 default:
4124 return -1;
4125 }
4126 } else
4127 if ((m = opmask (ao->op, "shasx", 0))) {
4128 ut64 argt = thumb_selector (ao->a);
4129 switch (argt) {
4130 case THUMB_REG_REG: {
4131 std_opt_2 (ao);
4132 }
4133 // intentional fallthrough
4134 case THUMB_REG_REG_REG: {
4135 ao->o = 0xa0fa20f0;
4136 return std_32bit_3reg (ao, m, false);
4137 }
4138 break;
4139 default:
4140 return -1;
4141 }
4142 } else
4143 if ((m = opmask (ao->op, "shsax", 0))) {
4144 ut64 argt = thumb_selector (ao->a);
4145 switch (argt) {
4146 case THUMB_REG_REG: {
4147 std_opt_2 (ao);
4148 }
4149 // intentional fallthrough
4150 case THUMB_REG_REG_REG: {
4151 ao->o = 0xe0fa20f0;
4152 return std_32bit_3reg (ao, m, false);
4153 }
4154 break;
4155 default:
4156 return -1;
4157 }
4158 } else
4159 if ((m = opmask (ao->op, "shsub", EIGHT_BIT | SIXTEEN_BIT))) {
4160 ut64 argt = thumb_selector (ao->a);
4161 switch (argt) {
4162 case THUMB_REG_REG: {
4163 std_opt_2 (ao);
4164 }
4165 // intentional fallthrough
4166 case THUMB_REG_REG_REG: {
4167 if (m & SIXTEEN_BIT) {
4168 ao->o = 0xd0fa20f0;
4169 } else
4170 if (m & EIGHT_BIT) {
4171 ao->o = 0xc0fa20f0;
4172 } else {
4173 return -1;
4174 }
4175 return std_32bit_3reg (ao, m, false);
4176 }
4177 break;
4178 default:
4179 return -1;
4180 }
4181 } else
4182 if ((m = opmask (ao->op, "smc", 0))) {
4183 ut64 argt = thumb_selector (ao->a);
4184 switch (argt) {
4185 case THUMB_CONST: {
4186 err = false;
4187 ut32 num = getnum (ao->a[0]);
4188
4189 if (err || (num > 15)) {
4190 return -1;
4191 }
4192
4193 ao->o = 0xf0f70080;
4194 ao->o |= num << 24;
4195 return 4;
4196 }
4197 break;
4198 default:
4199 return -1;
4200 }
4201 } else
4202 if ((m = opmask (ao->op, "smla", BB_BIT | BT_BIT | TB_BIT | TT_BIT | WB_BIT | WT_BIT | L_BIT | D_BIT | X_BIT))) {
4203 ut64 argt = thumb_selector (ao->a);
4204 switch (argt) {
4205 case THUMB_REG_REG_REG_REG: {
4206 ut8 reg1 = getreg (ao->a[0]);
4207 ut8 reg2 = getreg (ao->a[1]);
4208 ut8 reg3 = getreg (ao->a[2]);
4209 ut8 reg4 = getreg (ao->a[3]);
4210
4211 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT)) {
4212 return -1;
4213 }
4214 if (m & L_BIT) {
4215 if (m & BB_BIT) {
4216 ao->o = 0xc0fb8000;
4217 } else
4218 if (m & BT_BIT) {
4219 ao->o = 0xc0fb9000;
4220 } else
4221 if (m & TB_BIT) {
4222 ao->o = 0xc0fba000;
4223 } else
4224 if (m & TT_BIT) {
4225 ao->o = 0xc0fbb000;
4226 } else
4227 if (m & D_BIT) {
4228 ao->o = 0xc0fbc000;
4229 if (m & X_BIT) {
4230 ao->o |= 1 << 12;
4231 }
4232 } else {
4233 ao->o = 0xc0fb0000;
4234 }
4235 ao->o |= reg1 << 4;
4236 ao->o |= reg2;
4237 ao->o |= reg3 << 24;
4238 ao->o |= reg4 << 8;
4239 return 4;
4240 }
4241 if (m & BB_BIT) {
4242 ao->o = 0x10fb0000;
4243 ao->o |= reg4 << 4;
4244 return std_32bit_3reg (ao, m, false);
4245 }
4246 if (m & BT_BIT) {
4247 ao->o = 0x10fb1000;
4248 ao->o |= reg4 << 4;
4249 return std_32bit_3reg (ao, m, false);
4250 }
4251 if (m & TB_BIT) {
4252 ao->o = 0x10fb2000;
4253 ao->o |= reg4 << 4;
4254 return std_32bit_3reg (ao, m, false);
4255 }
4256 if (m & TT_BIT) {
4257 ao->o = 0x10fb3000;
4258 ao->o |= reg4 << 4;
4259 return std_32bit_3reg (ao, m, false);
4260 }
4261 if (m & D_BIT) {
4262 ao->o = 0x20fb0000;
4263 if (m & X_BIT) {
4264 ao->o |= 1 << 12;
4265 }
4266 ao->o |= reg4 << 4;
4267 return std_32bit_3reg (ao, m, false);
4268 }
4269 if (m & WB_BIT) {
4270 ao->o = 0x30fb0000;
4271 ao->o |= reg4 << 4;
4272 return std_32bit_3reg (ao, m, false);
4273 }
4274 if (m & WT_BIT) {
4275 ao->o = 0x30fb1000;
4276 ao->o |= reg4 << 4;
4277 return std_32bit_3reg (ao, m, false);
4278 }
4279 return -1;
4280 }
4281 break;
4282 default:
4283 return -1;
4284 }
4285 } else
4286 if ((m = opmask (ao->op, "smlsd", X_BIT))) {
4287 ut64 argt = thumb_selector (ao->a);
4288 switch (argt) {
4289 case THUMB_REG_REG_REG_REG: {
4290 ut8 reg4 = getreg (ao->a[3]);
4291
4292 if (reg4 > 15) {
4293 return -1;
4294 }
4295 ao->o = 0x40fb0000;
4296 if (m & X_BIT) {
4297 ao->o |= 1 << 12;
4298 }
4299 ao->o |= reg4 << 4;
4300 return std_32bit_3reg (ao, m, false);
4301 }
4302 break;
4303 default:
4304 return -1;
4305 }
4306 } else
4307 if ((m = opmask (ao->op, "smlsld", X_BIT))) {
4308 ut64 argt = thumb_selector (ao->a);
4309 switch (argt) {
4310 case THUMB_REG_REG_REG_REG: {
4311 ut8 reg1 = getreg (ao->a[0]);
4312 ut8 reg2 = getreg (ao->a[1]);
4313 ut8 reg3 = getreg (ao->a[2]);
4314 ut8 reg4 = getreg (ao->a[3]);
4315
4316 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT)) {
4317 return -1;
4318 }
4319 ao->o = 0xd0fbc000;
4320
4321 if (m & X_BIT) {
4322 ao->o |= 1 << 12;
4323 }
4324
4325 ao->o |= reg1 << 4;
4326 ao->o |= reg2;
4327 ao->o |= reg3 << 24;
4328 ao->o |= reg4 << 8;
4329 return 4;
4330 }
4331 break;
4332 default:
4333 return -1;
4334 }
4335 } else
4336 if ((m = opmask (ao->op, "smmla", R_BIT))) {
4337 ut64 argt = thumb_selector (ao->a);
4338 switch (argt) {
4339 case THUMB_REG_REG_REG_REG: {
4340 ut8 reg4 = getreg (ao->a[3]);
4341
4342 if (reg4 > 15) {
4343 return -1;
4344 }
4345 ao->o = 0x50fb0000;
4346 if (m & R_BIT) {
4347 ao->o |= 1 << 12;
4348 }
4349 ao->o |= reg4 << 4;
4350 return std_32bit_3reg (ao, m, false);
4351 }
4352 break;
4353 default:
4354 return -1;
4355 }
4356 } else
4357 if ((m = opmask (ao->op, "smmls", R_BIT))) {
4358 ut64 argt = thumb_selector (ao->a);
4359 switch (argt) {
4360 case THUMB_REG_REG_REG_REG: {
4361 ut8 reg4 = getreg (ao->a[3]);
4362
4363 if (reg4 > 15) {
4364 return -1;
4365 }
4366 ao->o = 0x60fb0000;
4367 if (m & R_BIT) {
4368 ao->o |= 1 << 12;
4369 }
4370 ao->o |= reg4 << 4;
4371 return std_32bit_3reg (ao, m, false);
4372 }
4373 break;
4374 default:
4375 return -1;
4376 }
4377 } else
4378 if ((m = opmask (ao->op, "smmul", R_BIT))) {
4379 ut64 argt = thumb_selector (ao->a);
4380 switch (argt) {
4381 case THUMB_REG_REG: {
4382 std_opt_2 (ao);
4383 }
4384 // intentional fallthrough
4385 case THUMB_REG_REG_REG: {
4386 ao->o = 0x50fb00f0;
4387 if (m & R_BIT) {
4388 ao->o |= 1 << 12;
4389 }
4390 return std_32bit_3reg (ao, m, false);
4391 }
4392 break;
4393 default:
4394 return -1;
4395 }
4396 } else
4397 if ((m = opmask (ao->op, "smuad", X_BIT))) {
4398 ut64 argt = thumb_selector (ao->a);
4399 switch (argt) {
4400 case THUMB_REG_REG: {
4401 std_opt_2 (ao);
4402 }
4403 // intentional fallthrough
4404 case THUMB_REG_REG_REG: {
4405 ao->o = 0x20fb00f0;
4406 if (m & X_BIT) {
4407 ao->o |= 1 << 12;
4408 }
4409 return std_32bit_3reg (ao, m, false);
4410 }
4411 break;
4412 default:
4413 return -1;
4414 }
4415 } else
4416 if ((m = opmask (ao->op, "smul", BB_BIT | BT_BIT | TB_BIT | TT_BIT | WB_BIT | WT_BIT | L_BIT))) {
4417 ut64 argt = thumb_selector (ao->a);
4418 switch (argt) {
4419 case THUMB_REG_REG: {
4420 std_opt_2 (ao);
4421 }
4422 // intentional fallthrough
4423 case THUMB_REG_REG_REG: {
4424 if (m & BB_BIT) {
4425 ao->o = 0x10fb00f0;
4426 } else
4427 if (m & BT_BIT) {
4428 ao->o = 0x10fb10f0;
4429 } else
4430 if (m & TB_BIT) {
4431 ao->o = 0x10fb20f0;
4432 } else
4433 if (m & TT_BIT) {
4434 ao->o = 0x10fb30f0;
4435 } else
4436 if (m & WB_BIT) {
4437 ao->o = 0x30fb00f0;
4438 } else
4439 if (m & WT_BIT) {
4440 ao->o = 0x30fb10f0;
4441 } else {
4442 return -1;
4443 }
4444 return std_32bit_3reg (ao, m, false);
4445 }
4446 break;
4447 case THUMB_REG_REG_REG_REG: {
4448 ut8 reg1 = getreg (ao->a[0]);
4449 ut8 reg2 = getreg (ao->a[1]);
4450 ut8 reg3 = getreg (ao->a[2]);
4451 ut8 reg4 = getreg (ao->a[3]);
4452
4453 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15) || (m & DOTN_BIT) || (!(m & L_BIT))) {
4454 return -1;
4455 }
4456
4457 ao->o = 0x80fb0000;
4458 ao->o |= reg1 << 4;
4459 ao->o |= reg2;
4460 ao->o |= reg3 << 24;
4461 ao->o |= reg4 << 8;
4462 return 4;
4463 }
4464 break;
4465 default:
4466 return -1;
4467 }
4468 } else
4469 if ((m = opmask (ao->op, "smusd", X_BIT))) {
4470 ut64 argt = thumb_selector (ao->a);
4471 switch (argt) {
4472 case THUMB_REG_REG: {
4473 std_opt_2 (ao);
4474 }
4475 // intentional fallthrough
4476 case THUMB_REG_REG_REG: {
4477 ao->o = 0x40fb00f0;
4478 if (m & X_BIT) {
4479 ao->o |= 1 << 12;
4480 }
4481 return std_32bit_3reg (ao, m, false);
4482 }
4483 break;
4484 default:
4485 return -1;
4486 }
4487 } else
4488 if ((m = opmask (ao->op, "srs", DB_BIT | FD_BIT | IA_BIT | EA_BIT))) {
4489 ut32 w = 0;
4490 ut64 argt = thumb_selector (ao->a);
4491 switch (argt) {
4492 case THUMB_CONSTBANG: {
4493 ao->a[0][strlen (ao->a[0]) - 1] = '\0';
4494 w = 1;
4495 }
4496 // intentional fallthrough
4497 case THUMB_CONST: {
4498 ut32 num = getnum (ao->a[0]);
4499 if (num > 31) {
4500 return -1;
4501 }
4502 if ((m & DB_BIT) || (m & FD_BIT)) {
4503 ao->o = 0x0de800c0;
4504 } else {
4505 ao->o = 0x8de900c0;
4506 }
4507 ao->o |= num << 8;
4508 ao->o |= w << 29;
4509 return 4;
4510 }
4511 break;
4512 default:
4513 return -1;
4514 }
4515 } else
4516 if ((m = opmask (ao->op, "ssat", SIXTEEN_BIT))) {
4517 ut64 argt = thumb_selector (ao->a);
4518 switch (argt) {
4519 case THUMB_REG_CONST_REG: {
4520 ao->a[3] = "lsl 0";
4521 }
4522 // intentional fallthrough
4523 case THUMB_REG_CONST_REG_SHIFT: {
4524 ut8 reg1 = getreg (ao->a[0]);
4525 ut32 num = getnum (ao->a[1]) - 1;
4526 ut8 reg2 = getreg (ao->a[2]);
4527 ut32 shift = thumb_getshift (ao->a[3]);
4528
4529 if (err || (reg1 > 15) || (reg2 > 15) || (num > 31) || (shift & 0x00001000) || ((m & SIXTEEN_BIT) && shift)) {
4530 return -1;
4531 }
4532
4533 if (shift & 0x00002000) {
4534 shift |= 0x20000000;
4535 shift &= 0xffffdfff;
4536 }
4537
4538 if (m & SIXTEEN_BIT) {
4539 ao->o = 0x20f30000;
4540 } else {
4541 ao->o = 0x00f30000;
4542 }
4543
4544 ao->o |= reg1;
4545 ao->o |= reg2 << 24;
4546 ao->o |= num << 8;
4547 ao->o |= shift;
4548 return 4;
4549 }
4550 break;
4551 default:
4552 return -1;
4553 }
4554 } else
4555 if ((m = opmask (ao->op, "ssax", 0))) {
4556 ut64 argt = thumb_selector (ao->a);
4557 switch (argt) {
4558 case THUMB_REG_REG: {
4559 std_opt_2 (ao);
4560 }
4561 // intentional fallthrough
4562 case THUMB_REG_REG_REG: {
4563 ao->o = 0xe0fa00f0;
4564 return std_32bit_3reg (ao, m, false);
4565 }
4566 break;
4567 default:
4568 return -1;
4569 }
4570 } else
4571 if ((m = opmask (ao->op, "ssub", EIGHT_BIT | SIXTEEN_BIT))) {
4572 ut64 argt = thumb_selector (ao->a);
4573 switch (argt) {
4574 case THUMB_REG_REG: {
4575 std_opt_2 (ao);
4576 }
4577 // intentional fallthrough
4578 case THUMB_REG_REG_REG: {
4579 if (m & EIGHT_BIT) {
4580 ao->o = 0xc0fa00f0;
4581 } else
4582 if (m & SIXTEEN_BIT) {
4583 ao->o = 0xd0fa00f0;
4584 } else {
4585 return -1;
4586 }
4587 return std_32bit_3reg (ao, m, false);
4588 }
4589 break;
4590 default:
4591 return -1;
4592 }
4593 } else if ((m = opmask (ao->op, "stc", L_BIT | TWO_BIT))) {
4594 ut64 argt = thumb_selector (ao->a);
4595 switch (argt) {
4596 case THUMB_COPROC_COREG_BRACKREGBRACK: {
4597 ao->a[2][strlen (ao->a[2]) - 1] = '\0';
4598 ao->a[3] = "0]";
4599 }
4600 // intentional fallthrough
4601 case THUMB_COPROC_COREG_BRACKREG_CONSTBRACK: {
4602 ut8 coproc = getcoproc (ao->a[0]);
4603 ut8 coreg = getcoprocreg (ao->a[1]);
4604 ut8 reg = getregmemstart (ao->a[2]);
4605 st32 num = getnummemend (ao->a[3]);
4606
4607 if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4608 return -1;
4609 }
4610
4611 ao->o = 0x00ed0000;
4612 if (m & L_BIT) {
4613 ao->o |= 1 << 30;
4614 }
4615 if (m & TWO_BIT) {
4616 ao->o |= 1 << 20;
4617 }
4618 if (num < 0) {
4619 num = -num;
4620 } else {
4621 ao->o |= 1 << 31;
4622 }
4623 ao->o |= coproc;
4624 ao->o |= coreg << 4;
4625 ao->o |= reg << 24;
4626 ao->o |= (num >> 2) << 8;
4627 return 4;
4628 }
4629 break;
4630 case THUMB_COPROC_COREG_BRACKREGBRACK_CONST: {
4631 ut8 coproc = getcoproc (ao->a[0]);
4632 ut8 coreg = getcoprocreg (ao->a[1]);
4633 ut8 reg = getregmemstartend (ao->a[2]);
4634 st32 num = getnum (ao->a[3]);
4635
4636 if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4637 return -1;
4638 }
4639
4640 ao->o = 0x20ec0000;
4641 if (m & L_BIT) {
4642 ao->o |= 1 << 30;
4643 }
4644 if (m & TWO_BIT) {
4645 ao->o |= 1 << 20;
4646 }
4647 if (num < 0) {
4648 num = -num;
4649 } else {
4650 ao->o |= 1 << 31;
4651 }
4652 ao->o |= coproc;
4653 ao->o |= coreg << 4;
4654 ao->o |= reg << 24;
4655 ao->o |= (num >> 2) << 8;
4656 return 4;
4657 }
4658 break;
4659 case THUMB_COPROC_COREG_BRACKREG_CONSTBRACKBANG: {
4660 ut8 coproc = getcoproc (ao->a[0]);
4661 ut8 coreg = getcoprocreg (ao->a[1]);
4662 ut8 reg = getregmemstart (ao->a[2]);
4663 st32 num = getnummemendbang (ao->a[3]);
4664
4665 if ((coproc > 15) || (coreg > 15) || (reg > 15) || (num > 4092) || (num < -4092) || (num % 4 != 0)) {
4666 return -1;
4667 }
4668
4669 ao->o = 0x20ed0000;
4670 if (m & L_BIT) {
4671 ao->o |= 1 << 30;
4672 }
4673 if (m & TWO_BIT) {
4674 ao->o |= 1 << 20;
4675 }
4676 if (num < 0) {
4677 num = -num;
4678 } else {
4679 ao->o |= 1 << 31;
4680 }
4681 ao->o |= coproc;
4682 ao->o |= coreg << 4;
4683 ao->o |= reg << 24;
4684 ao->o |= (num >> 2) << 8;
4685 return 4;
4686 }
4687 break;
4688 default:
4689 return -1;
4690 }
4691 } else if ((m = opmask (ao->op, "stm", FD_BIT | DB_BIT | IA_BIT | EA_BIT))) {
4692 ut64 argt = thumb_selector (ao->a);
4693 bool wb = false;
4694 switch (argt) {
4695 case THUMB_REGBANG_LIST: {
4696 wb = true;
4697 ao->a[0][strlen (ao->a[0]) - 1] = '\0';
4698 }
4699 // intentional fallthrough
4700 case THUMB_REG_LIST: {
4701 ut8 reg = getreg (ao->a[0]);
4702 st32 list = getreglist (ao->a[1]);
4703 if ((list <= 0) || ((list & 0x0000a000) != 0)) {
4704 return -1;
4705 }
4706
4707 if ((!(m & DOTW_BIT)) && ((list & 0x0000ff00) == 0) && (!(m & (FD_BIT | DB_BIT))) && wb) {
4708 ao->o = 0x00c0;
4709 ao->o |= (list & 0x000000ff) << 8;
4710 ao->o |= reg;
4711 return 2;
4712 }
4713
4714 if ((m & (FD_BIT | DB_BIT | IA_BIT | EA_BIT)) == 0) {
4715 return -1;
4716 }
4717
4718 if (m & (FD_BIT | DB_BIT)) {
4719 ao->o = 0x00e90000;
4720 } else {
4721 ao->o = 0x80e80000;
4722 }
4723
4724 if (wb) {
4725 ao->o |= 1 << 29;
4726 }
4727
4728 ao->o |= reg << 24;
4729 ao->o |= (list & 0x000000ff) << 8;
4730 ao->o |= (list & 0x0000ff00) >> 8;
4731 return 4;
4732 }
4733 break;
4734 default:
4735 return -1;
4736 }
4737 } else if ((m = opmask (ao->op, "str", B_BIT | T_BIT | D_BIT | H_BIT))) {
4738 ut64 argt = thumb_selector (ao->a);
4739 ut32 strsel = m & (B_BIT | H_BIT | D_BIT);
4740 switch (argt) {
4741 case THUMB_REG_BRACKREGBRACK:
4742 if (ao->a[2] == NULL) { // double fallthrough
4743 ao->a[1][strlen (ao->a[1]) -1] = '\0';
4744 ao->a[2] = "0]";
4745 }
4746 // intentional fallthrough
4747 case THUMB_REG_BRACKREG_CONSTBRACK: {
4748 ut8 reg1 = getreg (ao->a[0]);
4749 ut8 reg2 = getregmemstart (ao->a[1]);
4750 st32 num = getnummemend (ao->a[2]);
4751 if (m & T_BIT) {
4752 if ((num < 0) || (num > 255)) {
4753 return -1;
4754 }
4755 if (strsel == 0) {
4756 ao->o = 0x40f8000e;
4757 } else
4758 if (strsel == H_BIT) {
4759 ao->o = 0x20f8000e;
4760 } else
4761 if (strsel == B_BIT) {
4762 ao->o = 0x00f8000e;
4763 } else {
4764 return -1;
4765 }
4766 ao->o |= num << 8;
4767 return mem_32bit_2reg (ao, m);
4768 }
4769
4770 if ((strsel == 0) && (reg2 == 13) && (num >= 0) && (num < 1024) && ((num % 4) == 0) && (reg1 < 8) & (!(m & DOTW_BIT))) {
4771 ao->o = 0x0090;
4772 ao->o |= reg1;
4773 ao->o |= (num >> 2) << 8;
4774 return 2;
4775 }
4776
4777 bool t1form = false;
4778 if ((strsel == 0) && (num < 128) && (num >= 0) && (num % 4 == 0)) {
4779 ao->o = 0x0060;
4780 ao->o |= (num >> 4);
4781 ao->o |= ((num >> 2) & 0x3) << 14;
4782 t1form = true;
4783 }
4784 if ((strsel == B_BIT) && (num < 32) && (num >= 0)) {
4785 ao->o = 0x0070;
4786 ao->o |= (num >> 2);
4787 ao->o |= (num & 0x3) << 14;
4788 t1form = true;
4789 }
4790 if ((strsel == H_BIT) && (num < 64) && (num >= 0) && (num % 2 == 0)) {
4791 ao->o = 0x0080;
4792 ao->o |= (num >> 3);
4793 ao->o |= ((num >> 1) & 0x3) << 14;
4794 t1form = true;
4795 }
4796 if (t1form) {
4797 if (mem_16bit_2reg (ao, m)) {
4798 return 2;
4799 }
4800 }
4801
4802 if ((num > 4095) || (num < -255)) {
4803 return -1;
4804 }
4805 if (num >= 0) {
4806 if (strsel == 0) {
4807 ao->o = 0xc0f80000;
4808 } else
4809 if (strsel == B_BIT) {
4810 ao->o = 0x80f80000;
4811 } else
4812 if (strsel == H_BIT) {
4813 ao->o = 0xa0f80000;
4814 } else {
4815 return -1;
4816 }
4817 ao->o |= (num >> 8);
4818 ao->o |= (num & 0x000000ff) << 8;
4819 return mem_32bit_2reg (ao, m);
4820 }
4821 if (strsel == 0) {
4822 ao->o = 0x40f8000c;
4823 } else
4824 if (strsel == B_BIT) {
4825 ao->o = 0x00f8000c;
4826 } else
4827 if (strsel == H_BIT) {
4828 ao->o = 0x20f8000c;
4829 } else {
4830 return -1;
4831 }
4832 ao->o |= -num << 8;
4833 return mem_32bit_2reg (ao, m);
4834 }
4835 break;
4836 case THUMB_REG_BRACKREGBRACK_CONST: {
4837 ut8 reg1 = getreg (ao->a[0]);
4838 ut8 reg2 = getregmemstartend (ao->a[1]);
4839 st32 num = getnum (ao->a[2]);
4840
4841 if ((num > 255) || (num < -255)) {
4842 return -1;
4843 }
4844
4845 if (strsel == 0) {
4846 ao->o = 0x40f80009;
4847 } else
4848 if (strsel == B_BIT) {
4849 ao->o = 0x00f80009;
4850 } else
4851 if (strsel == H_BIT) {
4852 ao->o = 0x20f80009;
4853 } else {
4854 return -1;
4855 }
4856
4857 if (num < 0) {
4858 num = -num;
4859 } else {
4860 ao->o |= 1 << 1;
4861 }
4862 ao->o |= num << 8;
4863 ao->o |= reg1 << 4;
4864 ao->o |= reg2 << 24;
4865 return 4;
4866 }
4867 break;
4868 case THUMB_REG_BRACKREG_CONSTBRACKBANG: {
4869 st32 num = getnummemendbang (ao->a[2]);
4870
4871 if ((num > 255) || (num < -255)) {
4872 return -1;
4873 }
4874
4875 if (strsel == 0) {
4876 ao->o = 0x40f8000d;
4877 } else
4878 if (strsel == B_BIT) {
4879 ao->o = 0x00f8000d;
4880 } else
4881 if (strsel == H_BIT) {
4882 ao->o = 0x20f8000d;
4883 } else {
4884 return -1;
4885 }
4886
4887 if (num < 0) {
4888 num = -num;
4889 } else {
4890 ao->o |= 1 << 1;
4891 }
4892 ao->o |= num << 8;
4893 return mem_32bit_2reg (ao, m);
4894 }
4895 break;
4896 case THUMB_REG_BRACKREG_REGBRACK: {
4897 ut8 reg1 = getreg (ao->a[0]);
4898 ut8 reg2 = getregmemstart (ao->a[1]);
4899 ut8 reg3 = getregmemend (ao->a[2]);
4900 if ((reg1 < 8) && (reg2 < 8) && (reg3 < 8) && (!(m & DOTW_BIT))) {
4901 if (strsel == 0) {
4902 ao->o = 0x0050;
4903 } else
4904 if (strsel == B_BIT) {
4905 ao->o = 0x0054;
4906 } else
4907 if (strsel == H_BIT) {
4908 ao->o = 0x0052;
4909 } else {
4910 return -1;
4911 }
4912 ao->o |= reg1 << 8;
4913 ao->o |= reg2 << 11;
4914 ao->o |= (reg3 & 0x3) << 14;
4915 ao->o |= (reg3 >> 2);
4916 return 2;
4917 }
4918 ao->a[2][strlen (ao->a[2]) - 1] = '\0';
4919 ao->a[3] = "lsl 0]";
4920 }
4921 // intentional fallthrough
4922 case THUMB_REG_BRACKREG_REG_SHIFTBRACK: {
4923 ut8 reg1 = getreg (ao->a[0]);
4924 ut8 reg2 = getregmemstart (ao->a[1]);
4925 ut8 reg3 = getreg (ao->a[2]);
4926 ut32 shift = getshiftmemend (ao->a[3]) >> 2;
4927
4928 if (((shift & 0xffffcfff) != 0) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
4929 return -1;
4930 }
4931
4932 if (strsel == 0) {
4933 ao->o = 0x40f80000;
4934 } else
4935 if (strsel == B_BIT) {
4936 ao->o = 0x00f80000;
4937 } else
4938 if (strsel == H_BIT) {
4939 ao->o = 0x20f80000;
4940 } else {
4941 return -1;
4942 }
4943
4944 ao->o |= reg1 << 4;
4945 ao->o |= reg2 << 24;
4946 ao->o |= reg3 << 8;
4947 ao->o |= shift;
4948 return 4;
4949 }
4950 break;
4951 case THUMB_REG_REG_BRACKREGBRACK: {
4952 ao->a[2][strlen (ao->a[2]) - 1] = '\0';
4953 ao->a[3] = "0]";
4954 }
4955 // intentional fallthrough
4956 case THUMB_REG_REG_BRACKREG_CONSTBRACK: {
4957 ut8 reg1 = getreg (ao->a[0]);
4958 ut8 reg2 = getreg (ao->a[1]);
4959 ut8 reg3 = getregmemstart (ao->a[2]);
4960 st32 num = getnummemend (ao->a[3]);
4961
4962 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
4963 return -1;
4964 }
4965
4966 ao->o = 0x40e90000;
4967
4968 if (num < 0) {
4969 num = -num;
4970 } else {
4971 ao->o |= 1 << 31;
4972 }
4973 ao->o |= reg1 << 4;
4974 ao->o |= reg2;
4975 ao->o |= reg3 << 24;
4976 ao->o |= (num >> 2) << 8;
4977 return 4;
4978 }
4979 break;
4980 case THUMB_REG_REG_BRACKREG_CONSTBRACKBANG: {
4981 ut8 reg1 = getreg (ao->a[0]);
4982 ut8 reg2 = getreg (ao->a[1]);
4983 ut8 reg3 = getregmemstart (ao->a[2]);
4984 st32 num = getnummemendbang (ao->a[3]);
4985
4986 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
4987 return -1;
4988 }
4989
4990 ao->o = 0x60e90000;
4991
4992 if (num < 0) {
4993 num = -num;
4994 } else {
4995 ao->o |= 1 << 31;
4996 }
4997 ao->o |= reg1 << 4;
4998 ao->o |= reg2;
4999 ao->o |= reg3 << 24;
5000 ao->o |= (num >> 2) << 8;
5001 return 4;
5002 }
5003 break;
5004 case THUMB_REG_REG_BRACKREGBRACK_CONST: {
5005 ut8 reg1 = getreg (ao->a[0]);
5006 ut8 reg2 = getreg (ao->a[1]);
5007 ut8 reg3 = getregmemstartend (ao->a[2]);
5008 st32 num = getnum (ao->a[3]);
5009
5010 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (strsel != D_BIT) || (num > 1023) || (num < -1023) || ((num % 4) != 0)) {
5011 return -1;
5012 }
5013
5014 ao->o = 0x60e80000;
5015
5016 if (num < 0) {
5017 num = -num;
5018 } else {
5019 ao->o |= 1 << 31;
5020 }
5021 ao->o |= reg1 << 4;
5022 ao->o |= reg2;
5023 ao->o |= reg3 << 24;
5024 ao->o |= (num >> 2) << 8;
5025 return 4;
5026 }
5027 break;
5028 default:
5029 return -1;
5030 }
5031 } else
5032 if ((m = opmask (ao->op, "strex", B_BIT | D_BIT | H_BIT))) {
5033 ut64 argt = thumb_selector (ao->a);
5034 ut32 strsel = m & (B_BIT | H_BIT | D_BIT);
5035 switch (argt) {
5036 case THUMB_REG_REG_BRACKREGBRACK: {
5037 ut8 reg1 = getreg (ao->a[0]);
5038 ut8 reg2 = getreg (ao->a[1]);
5039 ut8 reg3 = getregmemstartend (ao->a[2]);
5040
5041 if ((strsel == D_BIT) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15)) {
5042 return -1;
5043 }
5044 if (strsel == B_BIT) {
5045 ao->o = 0xc0e8400f;
5046 ao->o |= reg1 << 8;
5047 ao->o |= reg2 << 4;
5048 ao->o |= reg3 << 24;
5049 return 4;
5050 } else
5051 if (strsel == H_BIT) {
5052 ao->o = 0xc0e8500f;
5053 ao->o |= reg1 << 8;
5054 ao->o |= reg2 << 4;
5055 ao->o |= reg3 << 24;
5056 return 4;
5057 }
5058
5059 ao->a[2][strlen (ao->a[2]) - 1] = '\0';
5060 ao->a[3] = "0]";
5061 }
5062 // intentional fallthrough
5063 case THUMB_REG_REG_BRACKREG_CONSTBRACK: {
5064 ut8 reg1 = getreg (ao->a[0]);
5065 ut8 reg2 = getreg (ao->a[1]);
5066 ut8 reg3 = getregmemstart (ao->a[2]);
5067 st32 num = getnummemend (ao->a[3]);
5068
5069 if ((strsel != 0) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (num < 0) || (num > 1023) || ((num % 4) !=0)) {
5070 return -1;
5071 }
5072
5073 ao->o = 0x40e80000;
5074 ao->o |= reg1;
5075 ao->o |= reg2 << 4;
5076 ao->o |= reg3 << 24;
5077 ao->o |= (num >> 2) << 8;
5078 return 4;
5079 }
5080 break;
5081 case THUMB_REG_REG_REG_BRACKREGBRACK: {
5082 ut8 reg1 = getreg (ao->a[0]);
5083 ut8 reg2 = getreg (ao->a[1]);
5084 ut8 reg3 = getreg (ao->a[2]);
5085 ut8 reg4 = getregmemstartend (ao->a[3]);
5086
5087 if ((strsel != D_BIT) || (reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5088 return -1;
5089 }
5090
5091 ao->o = 0xc0e87000;
5092 ao->o |= reg1 << 8;
5093 ao->o |= reg2 << 4;
5094 ao->o |= reg3;
5095 ao->o |= reg4 << 24;
5096 return 4;
5097 }
5098 break;
5099 }
5100 } else
5101 if ((m = opmask (ao->op, "sub", S_BIT | W_BIT))) {
5102 ut64 argt = thumb_selector (ao->a);
5103 switch (argt) {
5104 case THUMB_REG_CONST: {
5105 std_opt_2 (ao);
5106 }
5107 // intentional fallthrough
5108 case THUMB_REG_REG_CONST: {
5109 ut8 reg1 = getreg (ao->a[0]);
5110 ut8 reg2 = getreg (ao->a[1]);
5111 ut32 num = getnum (ao->a[2]);
5112
5113 if ((reg1 > 15) || (reg2 > 15)) {
5114 return -1;
5115 }
5116
5117 if ((reg1 == 15) && (reg2 == 14) && (num < 256)) {
5118 ao->o = 0xdef3008f;
5119 ao->o |= num << 8;
5120 return 4;
5121 }
5122 if (reg2 == 13) {
5123 if ((reg1 == 13) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num <= 4096) && (num % 4 == 0)) {
5124 ao->o = 0x80b0;
5125 ao->o |= (num >> 2) << 8;
5126 return 2;
5127 }
5128 err = false;
5129 ut32 thnum = getthimmed12 (ao->a[2]);
5130
5131 if (!err && (!(m & W_BIT))) {
5132 ao->o = 0xadf10000;
5133 ao->o |= thnum;
5134 ao->o |= reg1;
5135 if (m & S_BIT) {
5136 ao->o |= 1 << 28;
5137 }
5138 return 4;
5139 }
5140
5141 if (num > 4096) {
5142 return -1;
5143 }
5144
5145 ao->o = 0xadf20000;
5146 ao->o |= getthzeroimmed12 (num);
5147 ao->o |= reg1;
5148 return 4;
5149 }
5150
5151 if ((reg1 < 8) && (reg2 < 8) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num < 8)) {
5152 ao->o = 0x001e;
5153 ao->o |= reg1 << 8;
5154 ao->o |= reg2 << 11;
5155 ao->o |= (num & 0x3) << 14;
5156 ao->o |= (num >> 2);
5157 return 2;
5158 }
5159
5160 if ((reg1 < 8) && (reg1 == reg2) && (!(m & DOTW_BIT)) && (!(m & W_BIT)) && (num < 256)) {
5161 ao->o = 0x0038;
5162 ao->o |= reg1;
5163 ao->o |= num << 8;
5164 return 2;
5165 }
5166
5167 err = false;
5168 ut32 thnum = getthimmed12 (ao->a[2]);
5169
5170 if (!err && (!(m & W_BIT))) {
5171 ao->o = 0xa0f10000;
5172 ao->o |= thnum;
5173 return std_32bit_2reg (ao, m, false);
5174 }
5175
5176 if (num > 4096) {
5177 return -1;
5178 }
5179
5180 ao->o = 0xa0f20000;
5181 ao->o |= reg1;
5182 ao->o |= reg2 << 24;
5183 ao->o |= getthzeroimmed12 (num);
5184 return 4;
5185 }
5186 break;
5187 case THUMB_REG_REG: {
5188 std_opt_2 (ao);
5189 }
5190 // intentional fallthrough
5191 case THUMB_REG_REG_REG: {
5192 ao->a[3] = "lsl 0";
5193 }
5194 // intentional fallthrough
5195 case THUMB_REG_REG_SHIFT:
5196 if (ao->a[3] == NULL) { // double fallthrough
5197 std_opt_3 (ao);
5198 }
5199 // intentional fallthrough
5200 case THUMB_REG_REG_REG_SHIFT: {
5201 ut8 reg1 = getreg (ao->a[0]);
5202 ut8 reg2 = getreg (ao->a[1]);
5203 ut8 reg3 = getreg (ao->a[2]);
5204 ut32 shift = thumb_getshift (ao->a[3]);
5205
5206 if (reg2 == 13) {
5207 ao->o = 0xadeb0000;
5208 ao->o |= reg1;
5209 ao->o |= reg3 << 8;
5210 ao->o |= shift;
5211 if (m & S_BIT) {
5212 ao->o |= 1 << 28;
5213 }
5214 return 4;
5215 }
5216
5217 if ((shift == 0) && (reg1 < 8) && (reg2 < 8) && (reg3 < 8) && (!(m & DOTW_BIT))) {
5218 ao->o = 0x001a;
5219 ao->o |= reg1 << 8;
5220 ao->o |= reg2 << 11;
5221 ao->o |= (reg3 & 0x3) << 14;
5222 ao->o |= (reg3 >> 2);
5223 return 2;
5224 }
5225
5226 ao->o = 0xa0eb0000;
5227 return std_32bit_3reg (ao, m, true);
5228 }
5229 break;
5230 default:
5231 return -1;
5232 }
5233 } else
5234 if ((m = opmask (ao->op, "svc", 0))) {
5235 ut64 argt = thumb_selector (ao->a);
5236 switch (argt) {
5237 case THUMB_CONST: {
5238 ut32 num = getnum (ao->a[0]);
5239 if (num > 255) {
5240 return -1;
5241 }
5242 ao->o = 0x00df;
5243 ao->o |= num << 8;
5244 return 2;
5245 }
5246 break;
5247 default:
5248 return -1;
5249 }
5250 } else
5251 if ((m = opmask (ao->op, "sxta", B_BIT | H_BIT | SIXTEEN_BIT))) {
5252 ut64 argt = thumb_selector (ao->a);
5253 switch (argt) {
5254 case THUMB_REG_REG: {
5255 std_opt_2 (ao);
5256 }
5257 // intentional fallthrough
5258 case THUMB_REG_REG_REG: {
5259 ao->a[3] = "lsl 0";
5260 }
5261 // intentional fallthrough
5262 case THUMB_REG_REG_SHIFT: {
5263 if (ao->a[3] == NULL) { // double fallthrough
5264 std_opt_3 (ao);
5265 }
5266 }
5267 // intentional fallthrough
5268 case THUMB_REG_REG_REG_SHIFT: {
5269 ut32 shift = thumb_getshift (ao->a[3]);
5270
5271 if ((shift != 0) && ((shift & 0x0000f010) != 0x00003000)) {
5272 return -1;
5273 }
5274
5275 ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5276
5277 if (sufsel == B_BIT) {
5278 ao->o = 0x40fa80f0;
5279 } else
5280 if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5281 ao->o = 0x20fa80f0;
5282 } else
5283 if (sufsel == H_BIT) {
5284 ao->o = 0x00fa80f0;
5285 } else {
5286 return -1;
5287 }
5288
5289 ao->o |= (shift & 0x00000060) << 7;
5290 return std_32bit_3reg (ao, m, false);
5291 }
5292 break;
5293 }
5294 } else
5295 if ((m = opmask (ao->op, "sxt", B_BIT | H_BIT | SIXTEEN_BIT))) {
5296 ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5297 ut64 argt = thumb_selector (ao->a);
5298 switch (argt) {
5299 case THUMB_REG_REG: {
5300 ao->a[2] = "lsl 0";
5301 }
5302 // intentional fallthrough
5303 case THUMB_REG_REG_SHIFT: {
5304 ut8 reg1 = getreg (ao->a[0]);
5305 ut8 reg2 = getreg (ao->a[1]);
5306 ut32 shift = thumb_getshift (ao->a[2]);
5307
5308 if ((reg1 > 15) && (reg2 > 15) && (shift != 0) && ((shift & 0x0000f010) != 0x00003000)) {
5309 return -1;
5310 }
5311
5312 if (sufsel == B_BIT) {
5313 ao->o = 0x40b2;
5314 if ((shift == 0) && std_16bit_2reg (ao, m)) {
5315 return 2;
5316 }
5317 ao->o = 0x4ffa80f0;
5318 } else
5319 if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5320 ao->o = 0x2ffa80f0;
5321 } else
5322 if (sufsel == H_BIT) {
5323 ao->o = 0x00b2;
5324 if ((shift == 0) && std_16bit_2reg (ao, m)) {
5325 return 2;
5326 }
5327 ao->o = 0x0ffa80f0;
5328 } else {
5329 return -1;
5330 }
5331
5332 ao->o |= (shift & 0x00000060) << 7;
5333 ao->o |= reg1;
5334 ao->o |= reg2 << 8;
5335 return 4;
5336 }
5337 break;
5338 }
5339 } else
5340 if ((m = opmask (ao->op, "tb", B_BIT | H_BIT))) {
5341 ut64 argt = thumb_selector (ao->a);
5342 ut64 sufsel = m & (B_BIT | H_BIT);
5343 switch (argt) {
5344 case THUMB_BRACKREG_REGBRACK: {
5345 ut8 reg1 = getregmemstart (ao->a[0]);
5346 ut8 reg2 = getregmemend (ao->a[1]);
5347
5348 if ((reg1 > 15) || (reg2 > 15)) {
5349 return -1;
5350 }
5351
5352 if (sufsel == B_BIT) {
5353 ao->o = 0xd0e800f0;
5354 ao->o |= reg1 << 24;
5355 ao->o |= reg2 << 8;
5356 return 4;
5357 }
5358 ao->a[1][strlen (ao->a[1]) - 1] = '\0';
5359 ao->a[2] = "lsl 1]";
5360 }
5361 // intentional fallthrough
5362 case THUMB_BRACKREG_REG_SHIFTBRACK: {
5363 ut8 reg1 = getregmemstart (ao->a[0]);
5364 ut8 reg2 = getreg (ao->a[1]);
5365 ut32 shift = getshiftmemend (ao->a[2]);
5366
5367 if ((reg1 > 15) || (reg2 > 15) || (shift != 0x00004000) || (sufsel != H_BIT)) {
5368 return -1;
5369 }
5370
5371 ao->o = 0xd0e810f0;
5372 ao->o |= reg1 << 24;
5373 ao->o |= reg2 << 8;
5374 return 4;
5375 }
5376 break;
5377 default:
5378 return -1;
5379 }
5380 } else
5381 if ((m = opmask (ao->op, "teq", 0))) {
5382 ut64 argt = thumb_selector (ao->a);
5383 switch (argt) {
5384 case THUMB_REG_CONST: {
5385 ut8 reg = getreg (ao->a[0]);
5386 err = false;
5387 ut32 num = getthimmed12 (ao->a[1]);
5388
5389 if (err || (reg > 15)) {
5390 return -1;
5391 }
5392
5393 ao->o = 0x90f0000f;
5394 ao->o |= reg << 24;
5395 ao->o |= num;
5396 return 4;
5397 }
5398 break;
5399 case THUMB_REG_REG: {
5400 ao->a[2] = "lsl 0";
5401 }
5402 // intentional fallthrough
5403 case THUMB_REG_REG_SHIFT: {
5404 ao->o = 0x90ea000f;
5405 return std_32bit_2reg (ao, m, true);
5406 }
5407 break;
5408 default:
5409 return -1;
5410 }
5411 } else
5412 if ((m = opmask (ao->op, "tst", 0))) {
5413 ut64 argt = thumb_selector (ao->a);
5414 switch (argt) {
5415 case THUMB_REG_CONST: {
5416 ut8 reg1 = getreg (ao->a[0]);
5417 err = false;
5418 ut32 num = getthimmed12 (ao->a[1]);
5419
5420 if (err || (reg1 > 15)) {
5421 return -1;
5422 }
5423
5424 ao->o = 0x10f0000f;
5425 ao->o |= reg1 << 24;
5426 ao->o |= num;
5427 return 4;
5428 }
5429 break;
5430 case THUMB_REG_REG: {
5431 ao->o = 0x0042;
5432
5433 if (std_16bit_2reg (ao, m)) {
5434 return 2;
5435 }
5436
5437 ao->a[2] = "lsl 0";
5438 }
5439 // intentional fallthrough
5440 case THUMB_REG_REG_SHIFT: {
5441 ao->o = 0x10ea000f;
5442 return std_32bit_2reg (ao, m, true);
5443 }
5444 break;
5445 default:
5446 return -1;
5447 }
5448 } else
5449 if ((m = opmask (ao->op, "uadd", EIGHT_BIT | SIXTEEN_BIT))) {
5450 ut64 argt = thumb_selector (ao->a);
5451 switch (argt) {
5452 case THUMB_REG_REG: {
5453 std_opt_2 (ao);
5454 }
5455 // intentional fallthrough
5456 case THUMB_REG_REG_REG: {
5457 if (m & EIGHT_BIT) {
5458 ao->o = 0x80fa40f0;
5459 } else
5460 if (m & SIXTEEN_BIT) {
5461 ao->o = 0x90fa40f0;
5462 } else {
5463 return -1;
5464 }
5465
5466 return std_32bit_3reg (ao, m, false);
5467 }
5468 break;
5469 default:
5470 return -1;
5471 }
5472 } else
5473 if ((m = opmask (ao->op, "uasx", 0))) {
5474 ut64 argt = thumb_selector (ao->a);
5475 switch (argt) {
5476 case THUMB_REG_REG: {
5477 std_opt_2 (ao);
5478 }
5479 // intentional fallthrough
5480 case THUMB_REG_REG_REG: {
5481 ao->o = 0xa0fa40f0;
5482 return std_32bit_3reg (ao, m, false);
5483 }
5484 break;
5485 default:
5486 return -1;
5487 }
5488 } else
5489 if ((m = opmask (ao->op, "ubfx", 0))) {
5490 ut64 argt = thumb_selector (ao->a);
5491 switch (argt) {
5492 case THUMB_REG_REG_CONST_CONST: {
5493 ut8 reg1 = getreg (ao->a[0]);
5494 ut8 reg2 = getreg (ao->a[1]);
5495 ut32 lsb = getnum (ao->a[2]);
5496 ut32 widthm1 = getnum (ao->a[3]) - 1;
5497
5498 if ((reg1 > 15) || (reg2 > 15) || (lsb > 31) || ((31 - lsb) <= widthm1)) {
5499 return -1;
5500 }
5501
5502 ao->o = 0xc0f30000;
5503 ao->o |= reg1;
5504 ao->o |= reg2 << 24;
5505 ao->o |= (lsb & 0x1c) << 2;
5506 ao->o |= (lsb & 0x3) << 14;
5507 ao->o |= widthm1 << 8;
5508 return 4;
5509 }
5510 break;
5511 default:
5512 return -1;
5513 }
5514 } else
5515 if ((m = opmask (ao->op, "udiv", 0))) {
5516 ut64 argt = thumb_selector (ao->a);
5517 switch (argt) {
5518 case THUMB_REG_REG: {
5519 std_opt_2 (ao);
5520 }
5521 // intentional fallthrough
5522 case THUMB_REG_REG_REG: {
5523 ao->o = 0xb0fbf0f0;
5524 return std_32bit_3reg (ao, m, false);
5525 }
5526 break;
5527 default:
5528 return -1;
5529 }
5530 } else
5531 if ((m = opmask (ao->op, "uhadd", EIGHT_BIT | SIXTEEN_BIT))) {
5532 ut64 argt = thumb_selector (ao->a);
5533 ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5534 switch (argt) {
5535 case THUMB_REG_REG: {
5536 std_opt_2 (ao);
5537 }
5538 // intentional fallthrough
5539 case THUMB_REG_REG_REG: {
5540 if (sufsel == EIGHT_BIT) {
5541 ao->o = 0x80fa60f0;
5542 } else
5543 if (sufsel == SIXTEEN_BIT) {
5544 ao->o = 0x90fa60f0;
5545 } else {
5546 return -1;
5547 }
5548
5549 return std_32bit_3reg (ao, m, false);
5550 }
5551 break;
5552 default:
5553 return -1;
5554 }
5555 } else
5556 if ((m = opmask (ao->op, "uhasx", 0))) {
5557 ut64 argt = thumb_selector (ao->a);
5558 switch (argt) {
5559 case THUMB_REG_REG: {
5560 std_opt_2 (ao);
5561 }
5562 // intentional fallthrough
5563 case THUMB_REG_REG_REG: {
5564 ao->o = 0xa0fa60f0;
5565
5566 return std_32bit_3reg (ao, m, false);
5567
5568 }
5569 break;
5570 default:
5571 return -1;
5572 }
5573 } else
5574 if ((m = opmask (ao->op, "uhsax", 0))) {
5575 ut64 argt = thumb_selector (ao->a);
5576 switch (argt) {
5577 case THUMB_REG_REG: {
5578 std_opt_2 (ao);
5579 }
5580 // intentional fallthrough
5581 case THUMB_REG_REG_REG: {
5582 ao->o = 0xe0fa60f0;
5583
5584 return std_32bit_3reg (ao, m, false);
5585 }
5586 break;
5587 default:
5588 return -1;
5589 }
5590 } else
5591 if ((m = opmask (ao->op, "uhsub", EIGHT_BIT | SIXTEEN_BIT))) {
5592 ut64 argt = thumb_selector (ao->a);
5593 ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5594 switch (argt) {
5595 case THUMB_REG_REG: {
5596 std_opt_2 (ao);
5597 }
5598 // intentional fallthrough
5599 case THUMB_REG_REG_REG: {
5600 if (sufsel == EIGHT_BIT) {
5601 ao->o = 0xc0fa60f0;
5602 } else
5603 if (sufsel == SIXTEEN_BIT) {
5604 ao->o = 0xd0fa60f0;
5605 } else {
5606 return -1;
5607 }
5608
5609 return std_32bit_3reg (ao, m, false);
5610 }
5611 break;
5612 default:
5613 return -1;
5614 }
5615 } else
5616 if ((m = opmask (ao->op, "umaal", 0))) {
5617 ut64 argt = thumb_selector (ao->a);
5618 switch (argt) {
5619 case THUMB_REG_REG_REG_REG: {
5620 ut8 reg1 = getreg (ao->a[0]);
5621 ut8 reg2 = getreg (ao->a[1]);
5622 ut8 reg3 = getreg (ao->a[2]);
5623 ut8 reg4 = getreg (ao->a[3]);
5624
5625 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5626 return -1;
5627 }
5628
5629 ao->o = 0xe0fb6000;
5630 ao->o |= reg1 << 4;
5631 ao->o |= reg2;
5632 ao->o |= reg3 << 24;
5633 ao->o |= reg4 << 8;
5634 return 4;
5635 }
5636 break;
5637 default:
5638 return -1;
5639 }
5640 } else
5641 if ((m = opmask (ao->op, "umlal", 0))) {
5642 ut64 argt = thumb_selector (ao->a);
5643 switch (argt) {
5644 case THUMB_REG_REG_REG_REG: {
5645 ut8 reg1 = getreg (ao->a[0]);
5646 ut8 reg2 = getreg (ao->a[1]);
5647 ut8 reg3 = getreg (ao->a[2]);
5648 ut8 reg4 = getreg (ao->a[3]);
5649
5650 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5651 return -1;
5652 }
5653
5654 ao->o = 0xe0fb0000;
5655 ao->o |= reg1 << 4;
5656 ao->o |= reg2;
5657 ao->o |= reg3 << 24;
5658 ao->o |= reg4 << 8;
5659 return 4;
5660 }
5661 break;
5662 default:
5663 return -1;
5664 }
5665 } else
5666 if ((m = opmask (ao->op, "umull", 0))) {
5667 ut64 argt = thumb_selector (ao->a);
5668 switch (argt) {
5669 case THUMB_REG_REG_REG_REG: {
5670 ut8 reg1 = getreg (ao->a[0]);
5671 ut8 reg2 = getreg (ao->a[1]);
5672 ut8 reg3 = getreg (ao->a[2]);
5673 ut8 reg4 = getreg (ao->a[3]);
5674
5675 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5676 return -1;
5677 }
5678
5679 ao->o = 0xa0fb0000;
5680 ao->o |= reg1 << 4;
5681 ao->o |= reg2;
5682 ao->o |= reg3 << 24;
5683 ao->o |= reg4 << 8;
5684 return 4;
5685 }
5686 break;
5687 default:
5688 return -1;
5689 }
5690 } else
5691 if ((m = opmask (ao->op, "uqadd", EIGHT_BIT | SIXTEEN_BIT))) {
5692 ut64 argt = thumb_selector (ao->a);
5693 ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5694 switch (argt) {
5695 case THUMB_REG_REG: {
5696 std_opt_2 (ao);
5697 }
5698 // intentional fallthrough
5699 case THUMB_REG_REG_REG: {
5700 if (sufsel == EIGHT_BIT) {
5701 ao->o = 0x80fa50f0;
5702 } else
5703 if (sufsel == SIXTEEN_BIT) {
5704 ao->o = 0x90fa50f0;
5705 } else {
5706 return -1;
5707 }
5708
5709 return std_32bit_3reg (ao, m, false);
5710 }
5711 break;
5712 default:
5713 return -1;
5714 }
5715 } else
5716 if ((m = opmask (ao->op, "uqasx", 0))) {
5717 ut64 argt = thumb_selector (ao->a);
5718 switch (argt) {
5719 case THUMB_REG_REG: {
5720 std_opt_2 (ao);
5721 }
5722 // intentional fallthrough
5723 case THUMB_REG_REG_REG: {
5724 ao->o = 0xa0fa50f0;
5725
5726 return std_32bit_3reg (ao, m, false);
5727 }
5728 break;
5729 default:
5730 return -1;
5731 }
5732 } else
5733 if ((m = opmask (ao->op, "uqsax", 0))) {
5734 ut64 argt = thumb_selector (ao->a);
5735 switch (argt) {
5736 case THUMB_REG_REG: {
5737 std_opt_2 (ao);
5738 }
5739 // intentional fallthrough
5740 case THUMB_REG_REG_REG: {
5741 ao->o = 0xe0fa50f0;
5742
5743 return std_32bit_3reg (ao, m, false);
5744 }
5745 break;
5746 default:
5747 return -1;
5748 }
5749 } else
5750 if ((m = opmask (ao->op, "uqsub", EIGHT_BIT | SIXTEEN_BIT))) {
5751 ut64 argt = thumb_selector (ao->a);
5752 ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5753 switch (argt) {
5754 case THUMB_REG_REG: {
5755 std_opt_2 (ao);
5756 }
5757 // intentional fallthrough
5758 case THUMB_REG_REG_REG: {
5759 if (sufsel == EIGHT_BIT) {
5760 ao->o = 0xc0fa50f0;
5761 } else
5762 if (sufsel == SIXTEEN_BIT) {
5763 ao->o = 0xd0fa50f0;
5764 } else {
5765 return -1;
5766 }
5767
5768 return std_32bit_3reg (ao, m, false);
5769 }
5770 break;
5771 default:
5772 return -1;
5773 }
5774 } else
5775 if ((m = opmask (ao->op, "usad8", 0))) {
5776 ut64 argt = thumb_selector (ao->a);
5777 switch (argt) {
5778 case THUMB_REG_REG: {
5779 std_opt_2 (ao);
5780 }
5781 // intentional fallthrough
5782 case THUMB_REG_REG_REG: {
5783 ao->o = 0x70fb00f0;
5784
5785 return std_32bit_3reg (ao, m, false);
5786 }
5787 break;
5788 default:
5789 return -1;
5790 }
5791 } else
5792 if ((m = opmask (ao->op, "usada8", 0))) {
5793 ut64 argt = thumb_selector (ao->a);
5794 switch (argt) {
5795 case THUMB_REG_REG_REG_REG: {
5796 ut8 reg1 = getreg (ao->a[0]);
5797 ut8 reg2 = getreg (ao->a[1]);
5798 ut8 reg3 = getreg (ao->a[2]);
5799 ut8 reg4 = getreg (ao->a[3]);
5800
5801 if ((reg1 > 15) || (reg2 > 15) || (reg3 > 15) || (reg4 > 15)) {
5802 return -1;
5803 }
5804
5805 ao->o = 0x70fb0000;
5806 ao->o |= reg1;
5807 ao->o |= reg2 << 24;
5808 ao->o |= reg3 << 8;
5809 ao->o |= reg4 << 4;
5810 return 4;
5811 }
5812 break;
5813 default:
5814 return -1;
5815 }
5816 } else
5817 if ((m = opmask (ao->op, "usat", SIXTEEN_BIT))) {
5818 ut64 argt = thumb_selector (ao->a);
5819 switch (argt) {
5820 case THUMB_REG_CONST_REG: {
5821 if (m & SIXTEEN_BIT) {
5822 ut8 reg1 = getreg (ao->a[0]);
5823 ut32 num = getnum (ao->a[1]);
5824 ut8 reg2 = getreg (ao->a[2]);
5825
5826 if ((reg1 > 15) || (num > 15) || (reg2 > 15)) {
5827 return -1;
5828 }
5829
5830 ao->o = 0xa0f30000;
5831 ao->o |= reg1;
5832 ao->o |= reg2 << 24;
5833 ao->o |= num << 8;
5834 return 4;
5835 }
5836
5837 ao->a[3] = "lsl 0";
5838 }
5839 // intentional fallthrough
5840 case THUMB_REG_CONST_REG_SHIFT: {
5841 ut8 reg1 = getreg (ao->a[0]);
5842 ut32 num = getnum (ao->a[1]);
5843 ut8 reg2 = getreg (ao->a[2]);
5844 ut32 shift = thumb_getshift (ao->a[3]);
5845
5846 if ((reg1 > 15) || (num > 31) || (reg2 > 15) || (m & SIXTEEN_BIT) || ((shift & 0x00001000) != 0)) {
5847 return -1;
5848 }
5849
5850 ao->o = 0x80f30000;
5851 ao->o |= reg1;
5852 ao->o |= (num & 0xf) << 8;
5853 ao->o |= (num >> 4 ) << 12;
5854 ao->o |= reg2 << 24;
5855 ao->o |= (shift & 0x00002000) << 16;
5856 ao->o |= (shift & 0x0000c070);
5857 return 4;
5858 }
5859 break;
5860 default:
5861 return -1;
5862 }
5863 } else
5864 if ((m = opmask (ao->op, "usax", 0))) {
5865 ut64 argt = thumb_selector (ao->a);
5866 switch (argt) {
5867 case THUMB_REG_REG: {
5868 std_opt_2 (ao);
5869 }
5870 // intentional fallthrough
5871 case THUMB_REG_REG_REG: {
5872 ao->o = 0xe0fa40f0;
5873
5874 return std_32bit_3reg (ao, m, false);
5875 }
5876 break;
5877 default:
5878 return -1;
5879 }
5880 } else
5881 if ((m = opmask (ao->op, "usub", EIGHT_BIT | SIXTEEN_BIT))) {
5882 ut64 argt = thumb_selector (ao->a);
5883 ut64 sufsel = m & (EIGHT_BIT | SIXTEEN_BIT);
5884 switch (argt) {
5885 case THUMB_REG_REG: {
5886 std_opt_2 (ao);
5887 }
5888 // intentional fallthrough
5889 case THUMB_REG_REG_REG: {
5890 if (sufsel == EIGHT_BIT) {
5891 ao->o = 0xc0fa40f0;
5892 } else
5893 if (sufsel == SIXTEEN_BIT) {
5894 ao->o = 0xd0fa40f0;
5895 } else {
5896 return -1;
5897 }
5898
5899 return std_32bit_3reg (ao, m, false);
5900 }
5901 break;
5902 default:
5903 return -1;
5904 }
5905 } else
5906 if ((m = opmask (ao->op, "uxta", B_BIT | H_BIT | SIXTEEN_BIT))) {
5907 ut64 argt = thumb_selector (ao->a);
5908 ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5909 switch (argt) {
5910 case THUMB_REG_REG: {
5911 std_opt_2 (ao);
5912 }
5913 // intentional fallthrough
5914 case THUMB_REG_REG_REG: {
5915 ao->a[3] = "lsl 0";
5916 }
5917 // intentional fallthrough
5918 case THUMB_REG_REG_SHIFT: {
5919 if (ao->a[3] == NULL) { // double fallthrough
5920 std_opt_3 (ao);
5921 }
5922 }
5923 // intentional fallthrough
5924 case THUMB_REG_REG_REG_SHIFT: {
5925 ut32 shift = thumb_getshift (ao->a[3]);
5926
5927 if (shift && ((shift & 0x0000f010) != 0x00003000)) {
5928 return -1;
5929 }
5930
5931 if (sufsel == B_BIT) {
5932 ao->o = 0x50fa80f0;
5933 } else
5934 if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5935 ao->o = 0x30fa80f0;
5936 } else
5937 if (sufsel == H_BIT) {
5938 ao->o = 0x10fa80f0;
5939 } else {
5940 return -1;
5941 }
5942
5943 ao->o |= (shift & 0x00000060) << 7;
5944 return (std_32bit_3reg (ao, m, false));
5945 }
5946 break;
5947 default:
5948 return -1;
5949 }
5950 } else
5951 if ((m = opmask (ao->op, "uxt", B_BIT | H_BIT | SIXTEEN_BIT))) {
5952 ut64 argt = thumb_selector (ao->a);
5953 ut64 sufsel = m & (B_BIT | H_BIT | SIXTEEN_BIT);
5954 switch (argt) {
5955 case THUMB_REG_REG: {
5956 if ((sufsel == B_BIT) || (sufsel == H_BIT)) {
5957 if (sufsel == B_BIT) {
5958 ao->o = 0xc0b2;
5959 } else {
5960 ao->o = 0x80b2;
5961 }
5962 if (std_16bit_2reg (ao, m)) {
5963 return 2;
5964 }
5965 }
5966 ao->a[2] = "lsl 0";
5967 }
5968 // intentional fallthrough
5969 case THUMB_REG_REG_SHIFT: {
5970 ut8 reg1 = getreg (ao->a[0]);
5971 ut8 reg2 = getreg (ao->a[1]);
5972 ut32 shift = thumb_getshift (ao->a[2]);
5973
5974 if ((reg1 > 15) || (reg2 > 15) || (shift && ((shift & 0x0000f010) != 0x00003000))) {
5975 return -1;
5976 }
5977
5978 if (sufsel == B_BIT) {
5979 ao->o = 0x5ffa80f0;
5980 } else
5981 if (sufsel == (B_BIT | SIXTEEN_BIT)) {
5982 ao->o = 0x3ffa80f0;
5983 } else
5984 if (sufsel == H_BIT) {
5985 ao->o = 0x1ffa80f0;
5986 } else {
5987 return -1;
5988 }
5989
5990 ao->o |= (shift & 0x00000060) << 7;
5991 ao->o |= reg1;
5992 ao->o |= reg2 << 8;
5993 return 4;
5994 }
5995 break;
5996 default:
5997 return -1;
5998
5999 }
6000 } else
6001 if ((m = opmask (ao->op, "wfe", 0))) {
6002 ut64 argt = thumb_selector (ao->a);
6003 switch (argt) {
6004 case THUMB_NONE: {
6005 if (m & DOTW_BIT) {
6006 ao->o = 0xaff30280;
6007 return 4;
6008 } else {
6009 ao->o = 0x20bf;
6010 return 2;
6011 }
6012 }
6013 break;
6014 default:
6015 return -1;
6016 }
6017 } else
6018 if ((m = opmask (ao->op, "wfi", 0))) {
6019 ut64 argt = thumb_selector (ao->a);
6020 switch (argt) {
6021 case THUMB_NONE: {
6022 if (m & DOTW_BIT) {
6023 ao->o = 0xaff30380;
6024 return 4;
6025 } else {
6026 ao->o = 0x30bf;
6027 return 2;
6028 }
6029 }
6030 break;
6031 default:
6032 return -1;
6033 }
6034 } else
6035 if ((m = opmask (ao->op, "yield", 0))) {
6036 ut64 argt = thumb_selector (ao->a);
6037 switch (argt) {
6038 case THUMB_NONE: {
6039 if (m & DOTW_BIT) {
6040 ao->o = 0xaff30180;
6041 return 4;
6042 } else {
6043 ao->o = 0x10bf;
6044 return 2;
6045 }
6046 }
6047 break;
6048 default:
6049 return -1;
6050 }
6051 }
6052 return 0;
6053 }
6054
findyz(int x,int * y,int * z)6055 static int findyz(int x, int *y, int *z) {
6056 int i, j;
6057 for (i = 0;i < 0xff; i++) {
6058 for (j = 0;j < 0xf;j++) {
6059 int v = i << j;
6060 if (v > x) {
6061 continue;
6062 }
6063 if (v == x) {
6064 *y = i;
6065 *z = 16 - (j / 2);
6066 return 1;
6067 }
6068 }
6069 }
6070 return 0;
6071 }
6072
arm_assemble(ArmOpcode * ao,ut64 off,const char * str)6073 static int arm_assemble(ArmOpcode *ao, ut64 off, const char *str) {
6074 int i, j, ret, reg, a, b;
6075 int coproc, opc;
6076 bool rex = false;
6077 int shift, low, high;
6078 for (i = 0; ops[i].name; i++) {
6079 if (!strncmp (ao->op, ops[i].name, strlen (ops[i].name))) {
6080 ao->o = ops[i].code;
6081 arm_opcode_cond (ao, strlen(ops[i].name));
6082 if (ao->a[0] || ops[i].type == TYPE_BKP) {
6083 switch (ops[i].type) {
6084 case TYPE_MEM:
6085 if (!strncmp (ops[i].name, "strex", 5)) {
6086 rex = 1;
6087 }
6088 if (!strcmp (ops[i].name, "str") || !strcmp (ops[i].name, "ldr")) {
6089 if (!ao->a[2]) {
6090 ao->a[2] = "0";
6091 }
6092 }
6093 getrange (ao->a[0]);
6094 getrange (ao->a[1]);
6095 getrange (ao->a[2]);
6096 if (ao->a[0] && ao->a[1]) {
6097 char rn[8];
6098 strncpy (rn, ao->a[1], 7);
6099 int r0 = getreg (ao->a[0]);
6100 int r1 = getreg (ao->a[1]);
6101 if ((r0 < 0 || r0 > 15) || (r1 > 15 || r1 < 0)) {
6102 return 0;
6103 }
6104 ao->o |= r0 << 20;
6105 if (!strcmp (ops[i].name, "strd")) {
6106 r1 = getreg (ao->a[2]);
6107 if (r1 == -1) {
6108 break;
6109 }
6110 ao->o |= r1 << 8;
6111 if (ao->a[3]) {
6112 char *bracket = strchr (ao->a[3], ']');
6113 if (bracket) {
6114 *bracket = '\0';
6115 }
6116 int num = getnum (ao->a[3]);
6117 ao->o |= (num & 0x0f) << 24;
6118 ao->o |= ((num >> 4) & 0x0f) << 16;
6119 }
6120 break;
6121 }
6122 if (!strcmp (ops[i].name, "strh")) {
6123 ao->o |= r1 << 8;
6124 if (ao->a[2]) {
6125 reg = getreg (ao->a[2]);
6126 if (reg != -1) {
6127 ao->o |= reg << 24;
6128 } else {
6129 ao->o |= 1 << 14;
6130 ao->o |= getnum (ao->a[2]) << 24;
6131 }
6132 } else {
6133 ao->o |= 1 << 14;
6134 }
6135 break;
6136 }
6137 if (rex) {
6138 ao->o |= r1 << 24;
6139 } else {
6140 ao->o |= r1 << 8; // delta
6141 }
6142 } else {
6143 return 0;
6144 }
6145
6146 ret = getreg (ao->a[2]);
6147 if (ret != -1) {
6148 if (rex) {
6149 ao->o |= 1;
6150 ao->o |= (ret & 0x0f) << 8;
6151 } else {
6152 ao->o |= (strstr (str, "],")) ? 6 : 7;
6153 ao->o |= (ret & 0x0f) << 24;
6154 }
6155 if (ao->a[3]) {
6156 shift = getshift (ao->a[3]);
6157 low = shift & 0xFF;
6158 high = shift & 0xFF00;
6159 ao->o |= low << 24;
6160 ao->o |= high << 8;
6161 }
6162 } else {
6163 int num = getnum (ao->a[2]) & 0xfff;
6164 if (err) {
6165 break;
6166 }
6167 if (rex) {
6168 ao->o |= 1;
6169 } else {
6170 ao->o |= (strstr (str, "],")) ? 4 : 5;
6171 }
6172 ao->o |= 1;
6173 ao->o |= (num & 0xff) << 24;
6174 ao->o |= ((num >> 8) & 0xf) << 16;
6175 }
6176
6177 break;
6178 case TYPE_IMM:
6179 if (*ao->a[0]++ == '{') {
6180 for (j = 0; j < 16; j++) {
6181 if (ao->a[j] && *ao->a[j]) {
6182 getrange (ao->a[j]); // XXX filter regname string
6183 reg = getreg (ao->a[j]);
6184 if (reg != -1) {
6185 if (reg < 8) {
6186 ao->o |= 1 << (24 + reg);
6187 } else {
6188 ao->o |= 1 << (8 + reg);
6189 }
6190 }
6191 }
6192 }
6193 } else {
6194 ao->o |= getnum (ao->a[0]) << 24; // ???
6195 }
6196 break;
6197 case TYPE_BRA:
6198 if ((ret = getreg (ao->a[0])) == -1) {
6199 // TODO: control if branch out of range
6200 ret = (getnum (ao->a[0]) - (int)ao->off - 8) / 4;
6201 if (ret >= 0x00800000 || ret < (int)0xff800000) {
6202 eprintf ("Branch into out of range\n");
6203 return 0;
6204 }
6205 ao->o |= ((ret >> 16) & 0xff) << 8;
6206 ao->o |= ((ret >> 8) & 0xff) << 16;
6207 ao->o |= ((ret)&0xff) << 24;
6208 } else {
6209 eprintf ("This branch does not accept reg as arg\n");
6210 return 0;
6211 }
6212 break;
6213 case TYPE_BKP:
6214 ao->o |= 0x70 << 24;
6215 if (ao->a[0]) {
6216 int n = getnum (ao->a[0]);
6217 ao->o |= ((n & 0xf) << 24);
6218 ao->o |= (((n >> 4) & 0xff) << 16);
6219 }
6220 break;
6221 case TYPE_BRR:
6222 if ((ret = getreg (ao->a[0])) == -1) {
6223 ut32 dst = getnum (ao->a[0]);
6224 dst -= (ao->off + 8);
6225 if (dst & 0x2) {
6226 ao->o = 0xfb;
6227 } else {
6228 ao->o = 0xfa;
6229 }
6230 dst /= 4;
6231 ao->o |= ((dst >> 16) & 0xff) << 8;
6232 ao->o |= ((dst >> 8) & 0xff) << 16;
6233 ao->o |= ((dst)&0xff) << 24;
6234 return 4;
6235 } else {
6236 ao->o |= (getreg (ao->a[0]) << 24);
6237 }
6238 break;
6239 case TYPE_HLT: {
6240 ut32 o = 0, n = getnum (ao->a[0]);
6241 o |= ((n >> 12) & 0xf) << 8;
6242 o |= ((n >> 8) & 0xf) << 20;
6243 o |= ((n >> 4) & 0xf) << 16;
6244 o |= ((n) & 0xf) << 24;
6245 ao->o |=o;
6246 }
6247 break;
6248 case TYPE_SWI:
6249 ao->o |= (getnum (ao->a[0]) & 0xff) << 24;
6250 ao->o |= ((getnum (ao->a[0]) >> 8) & 0xff) << 16;
6251 ao->o |= ((getnum (ao->a[0]) >> 16) & 0xff) << 8;
6252 break;
6253 case TYPE_UDF:
6254 {
6255 // e7f000f0 = udf 0
6256 // e7ffffff = udf 0xffff
6257 ut32 n = getnum (ao->a[0]);
6258 ao->o |= 0xe7;
6259 ao->o |= (n & 0xf) << 24;
6260 ao->o |= ((n >> 4) & 0xff) << 16;
6261 ao->o |= ((n >> 12) & 0xf) << 8;
6262 }
6263 break;
6264 case TYPE_ARI:
6265 if (!ao->a[2]) {
6266 ao->a[2] = ao->a[1];
6267 ao->a[1] = ao->a[0];
6268 }
6269 reg = getreg (ao->a[0]);
6270 if (reg == -1) {
6271 return 0;
6272 }
6273 ao->o |= reg << 20;
6274
6275 reg = getreg (ao->a[1]);
6276 if (reg == -1) {
6277 return 0;
6278 }
6279 ao->o |= reg << 8;
6280 reg = getreg (ao->a[2]);
6281 if (reg == -1) {
6282 int imm = getnum(ao->a[2]);
6283 if (imm && !(imm & (imm - 1)) && imm > 255) {
6284 int r;
6285 for (r = 0; r != 32; r += 2) {
6286 if (!(imm & ~0xff)) {
6287 ao->o |= (r << 15) | (imm << 24) | 2;
6288 break;
6289 }
6290 imm = (imm << 2) | (imm >> 30);
6291 }
6292 } else {
6293 ao->o |= (imm << 24) | 2;
6294 }
6295 } else {
6296 ao->o |= reg << 24;
6297 }
6298 if (ao->a[3]) {
6299 ao->o |= getshift(ao->a[3]);
6300 }
6301 break;
6302 case TYPE_SWP:
6303 {
6304 int a1 = getreg (ao->a[1]);
6305 if (a1) {
6306 ao->o = 0xe1;
6307 ao->o |= (getreg (ao->a[0]) << 4) << 16;
6308 ao->o |= (0x90 + a1) << 24;
6309 if (ao->a[2]) {
6310 ao->o |= (getreg (ao->a[2] + 1)) << 8;
6311 } else {
6312 return 0;
6313 }
6314 }
6315 if (0xff == ((ao->o >> 16) & 0xff)) {
6316 return 0;
6317 }
6318 }
6319 break;
6320 case TYPE_MOV:
6321 if (!strcmpnull (ao->op, "movs")) {
6322 ao->o = 0xb0e1;
6323 }
6324 ao->o |= getreg (ao->a[0]) << 20;
6325 ret = getreg (ao->a[1]);
6326 if (ret != -1) {
6327 ao->o |= ret << 24;
6328 } else {
6329 int immed = getimmed8 (ao->a[1]);
6330 if (err) {
6331 return 0;
6332 }
6333 ao->o |= 0xa003 | (immed & 0xff) << 24 | (immed >> 8) << 16;
6334 }
6335 break;
6336 case TYPE_MOVW:
6337 reg = getreg (ao->a[0]);
6338 if (reg == -1) {
6339 return 0;
6340 }
6341 ao->o |= getreg (ao->a[0]) << 20;
6342 ret = getnum (ao->a[1]);
6343
6344 ao->o |= 0x3 | ret << 24;
6345 ao->o |= (ret & 0xf000) >> 4;
6346 ao->o |= (ret & 0xf00) << 8;
6347 break;
6348 case TYPE_MOVT:
6349 ao->o |= getreg (ao->a[0]) << 20;
6350 ret = getnum (ao->a[1]);
6351
6352 ao->o |= 0x4003 | ret << 24;
6353 ao->o |= (ret & 0xf000) >> 4;
6354 ao->o |= (ret & 0xf00) << 8;
6355 break;
6356 case TYPE_MUL:
6357 if (!strcmpnull (ao->op, "mul")) {
6358 ret = getreg (ao->a[0]);
6359 a = getreg (ao->a[1]);
6360 b = getreg (ao->a[2]);
6361 if (b == -1) {
6362 b = a;
6363 a = ret;
6364 }
6365 if (ret == -1 || a == -1) {
6366 return 0;
6367 }
6368 ao->o |= ret << 8;
6369 ao->o |= a << 24;
6370 ao->o |= b << 16;
6371 } else {
6372 low = getreg (ao->a[0]);
6373 high = getreg (ao->a[1]);
6374 a = getreg (ao->a[2]);
6375 b = getreg (ao->a[3]);
6376 if (low == -1 || high == -1 || a == -1 || b == -1) {
6377 return 0;
6378 }
6379 if (!strcmpnull (ao->op, "smlal")) {
6380 ao->o |= low << 20;
6381 ao->o |= high << 8;
6382 ao->o |= a << 24;
6383 ao->o |= b << 16;
6384 } else if (!strncmp (ao->op, "smla", 4)) {
6385 if (low > 14 || high > 14 || a > 14) {
6386 return 0;
6387 }
6388 ao->o |= low << 8;
6389 ao->o |= high << 24;
6390 ao->o |= a << 16;
6391 ao->o |= b << 20;
6392 break;
6393 } else {
6394 ao->o |= low << 20;
6395 ao->o |= high << 8;
6396 ao->o |= a << 24;
6397 ao->o |= b << 16;
6398 }
6399 }
6400 break;
6401 case TYPE_TST:
6402 a = getreg (ao->a[0]);
6403 b = getreg (ao->a[1]);
6404 if (b == -1) {
6405 int y, z;
6406 b = getnum (ao->a[1]);
6407 if (b >= 0 && b <= 0xff) {
6408 ao->o = 0x50e3;
6409 // TODO: if (b>255) -> automatic multiplier
6410 ao->o |= (a << 8);
6411 ao->o |= ((b & 0xff) << 24);
6412 } else
6413 if (findyz (b, &y, &z)) {
6414 ao->o = 0x50e3;
6415 ao->o |= (y << 24);
6416 ao->o |= (z << 16);
6417 } else {
6418 eprintf ("Parameter %d out0x3000a0e1 of range (0-255)\n", (int)b);
6419 return 0;
6420 }
6421 } else {
6422 ao->o |= (a << 8);
6423 ao->o |= (b << 24);
6424 if (ao->a[2]) {
6425 ao->o |= getshift (ao->a[2]);
6426 }
6427 }
6428 if (ao->a[2]) {
6429 int n = getnum (ao->a[2]);
6430 if (n & 1) {
6431 eprintf ("Invalid multiplier\n");
6432 return 0;
6433 }
6434 ao->o |= (n >> 1) << 16;
6435 }
6436 break;
6437 case TYPE_SHFT:
6438 reg = getreg (ao->a[2]);
6439 if (reg == -1 || reg > 14) {
6440 return 0;
6441 }
6442 ao->o |= reg << 16;
6443
6444 reg = getreg (ao->a[0]);
6445 if (reg == -1 || reg > 14) {
6446 return 0;
6447 }
6448 ao->o |= reg << 20;
6449
6450 reg = getreg (ao->a[1]);
6451 if (reg == -1 || reg > 14) {
6452 return 0;
6453 }
6454 ao->o |= reg << 24;
6455 break;
6456 case TYPE_REV:
6457 reg = getreg (ao->a[0]);
6458 if (reg == -1 || reg > 14) {
6459 return 0;
6460 }
6461 ao->o |= reg << 20;
6462
6463 reg = getreg (ao->a[1]);
6464 if (reg == -1 || reg > 14) {
6465 return 0;
6466 }
6467 ao->o |= reg << 24;
6468
6469 break;
6470 case TYPE_ENDIAN:
6471 if (!strcmp (ao->a[0], "le")) {
6472 ao->o |= 0;
6473 } else if (!strcmp (ao->a[0], "be")) {
6474 ao->o |= 0x20000;
6475 } else {
6476 return 0;
6477 }
6478 break;
6479 case TYPE_COPROC:
6480 //printf ("%s %s %s %s %s\n", ao->a[0], ao->a[1], ao->a[2], ao->a[3], ao->a[4] );
6481 if (ao->a[0]) {
6482 coproc = getnum (ao->a[0] + 1);
6483 if (coproc == -1 || coproc > 9) {
6484 return 0;
6485 }
6486 ao->o |= coproc << 16;
6487 }
6488
6489 opc = getnum (ao->a[1]);
6490 if (opc == -1 || opc > 7) {
6491 return 0;
6492 }
6493 ao->o |= opc << 13;
6494
6495 reg = getreg (ao->a[2]);
6496 if (reg == -1 || reg > 14) {
6497 return 0;
6498 }
6499 ao->o |= reg << 20;
6500
6501 // coproc register 1
6502 const char *a3 = ao->a[3];
6503 if (a3) {
6504 coproc = getnum (a3 + 1);
6505 if (coproc == -1 || coproc > 15) {
6506 return 0;
6507 }
6508 ao->o |= coproc << 8;
6509 }
6510
6511 const char *a4 = ao->a[4];
6512 if (a4) {
6513 coproc = getnum (ao->a[4] + 1);
6514 if (coproc == -1 || coproc > 15) {
6515 return 0;
6516 }
6517 ao->o |= coproc << 24;
6518 }
6519
6520 coproc = getnum (ao->a[5]);
6521 if (coproc > -1) {
6522 if (coproc > 7) {
6523 return 0;
6524 }
6525 // optional opcode
6526 ao->o |= coproc << 29;
6527 }
6528
6529 break;
6530 case TYPE_CLZ:
6531 ao->o |= 1 << 28;
6532
6533 reg = getreg (ao->a[0]);
6534 if (reg == -1 || reg > 14) {
6535 return 0;
6536 }
6537 ao->o |= reg << 20;
6538
6539 reg = getreg (ao->a[1]);
6540 if (reg == -1 || reg > 14) {
6541 return 0;
6542 }
6543 ao->o |= reg << 24;
6544
6545 break;
6546 case TYPE_NEG:
6547 if (!ao->a[0] || !ao->a[1]) {
6548 return 0;
6549 }
6550 ao->a[2] = "0";
6551 int len = strlen (ao->a[1]) + 1;
6552 memmove (ao->a[0] + 1, ao->a[0], ao->a[1] - ao->a[0] + len);
6553 ao->a[0]++;
6554 ao->a[1]++;
6555 strncpy (ao->op, "rsbs", 5);
6556 arm_assemble (ao, off, str); // rsbs reg0, reg1, #0
6557 break;
6558 }
6559 }
6560 return 1;
6561 }
6562 }
6563 return 0;
6564 }
6565
6566 typedef int (*AssembleFunction)(ArmOpcode *, ut64, const char *);
6567 static AssembleFunction assemble[2] = { &arm_assemble, &thumb_assemble };
6568
armass_assemble(const char * str,ut64 off,int thumb)6569 ut32 armass_assemble(const char *str, ut64 off, int thumb) {
6570 int i, j;
6571 char buf[128];
6572 ArmOpcode aop = {.off = off};
6573 for (i = j = 0; i < sizeof (buf) - 1 && str[j]; i++, j++) {
6574 if (str[j] == '#') {
6575 i--; continue;
6576 }
6577 buf[i] = tolower ((const ut8)str[j]);
6578 }
6579 buf[i] = 0;
6580 arm_opcode_parse (&aop, buf);
6581 aop.off = off;
6582 if (thumb < 0 || thumb > 1) {
6583 return -1;
6584 }
6585 if (assemble[thumb] (&aop, off, buf) <= 0) {
6586 //eprintf ("armass: Unknown opcode (%s)\n", buf);
6587 return -1;
6588 }
6589 return aop.o;
6590 }
6591
6592 #ifdef MAIN
thisplay(const char * str)6593 void thisplay(const char *str) {
6594 char cmd[32];
6595 int op = armass_assemble (str, 0x1000, 1);
6596 printf ("[%04x] %s\n", op, str);
6597 snprintf (cmd, sizeof(cmd), "rasm2 -d -b 16 -a arm %04x", op);
6598 system (cmd);
6599 }
6600
display(const char * str)6601 void display(const char *str) {
6602 char cmd[32];
6603 int op = armass_assemble (str, 0x1000, 0);
6604 printf ("[%08x] %s\n", op, str);
6605 snprintf (cmd, sizeof(cmd), "rasm2 -d -a arm %08x", op);
6606 system (cmd);
6607 }
6608
main()6609 int main() {
6610 thisplay ("ldmia r1!, {r3, r4, r5}");
6611 thisplay ("stmia r1!, {r3, r4, r5}");
6612 thisplay ("bkpt 12");
6613 return 0;
6614 thisplay("sub r1, r2, 0");
6615 thisplay("sub r1, r2, 4");
6616 thisplay("sub r1, r2, 5");
6617 thisplay("sub r1, r2, 7");
6618 thisplay("sub r3, 44");
6619 return 0;
6620 #if 0
6621 thisplay("mov r0, 11");
6622 thisplay("mov r0, r2");
6623 thisplay("mov r1, r4");
6624 thisplay("cmp r1, r2");
6625 thisplay("cmp r3, 44");
6626 thisplay("nop");
6627 thisplay("svc 15");
6628 thisplay("add r1, r2");
6629 thisplay("add r3, 44");
6630 thisplay("sub r1, r2, 3");
6631 thisplay("sub r3, 44");
6632 thisplay("tst r3,r4");
6633 thisplay("bx r3");
6634 thisplay("b 33");
6635 thisplay("b 0");
6636 thisplay("bne 44");
6637 thisplay("and r2,r3");
6638 #endif
6639 // INVALID thisplay("ldr r1, [pc, r2]");
6640 // INVALID thisplay("ldr r1, [sp, r2]");
6641 #if 0
6642 thisplay("ldr r1, [pc, 12]");
6643 thisplay("ldr r1, [sp, 24]");
6644 thisplay("ldr r1, [r2, r3]");
6645 #endif
6646 // INVALID thisplay("str r1, [pc, 22]");
6647 // INVALID thisplay("str r1, [pc, r2]");
6648 // INVALID thisplay("str r1, [sp, r2]");
6649 #if 0
6650 0: 8991 ldrh r1, [r2, #12]
6651 2: 7b11 ldrb r1, [r2, #12]
6652 4: 8191 strh r1, [r2, #12]
6653 6: 7311 strb r1, [r2, #12]
6654 #endif
6655 thisplay("ldrh r1, [r2, 8]"); // aligned to 4
6656 thisplay("ldrh r1, [r3, 8]"); // aligned to 4
6657 thisplay("ldrh r1, [r4, 16]"); // aligned to 4
6658 thisplay("ldrh r1, [r2, 32]"); // aligned to 4
6659 thisplay("ldrb r1, [r2, 20]"); // aligned to 4
6660 thisplay("strh r1, [r2, 20]"); // aligned to 4
6661 thisplay("strb r1, [r2, 20]"); // aligned to 4
6662 thisplay("str r1, [sp, 20]"); // aligned to 4
6663 thisplay("str r1, [r2, 12]"); // OK
6664 thisplay("str r1, [r2, r3]");
6665 return 0;
6666 #if 0
6667 display("mov r0, 33");
6668 display("mov r1, 33");
6669 display("movne r0, 33");
6670 display("tst r0, r1, lsl #2");
6671 display("svc 0x80");
6672 display("sub r3, r1, r2");
6673 display("add r0, r1, r2");
6674 display("mov fp, 0");
6675 display("pop {pc}");
6676 display("pop {r3}");
6677 display("bx r1");
6678 display("bx r3");
6679 display("bx pc");
6680 display("blx fp");
6681 display("pop {pc}");
6682 display("add lr, pc, lr");
6683 display("adds r3, #8");
6684 display("adds r3, r2, #8");
6685 display("subs r2, #1");
6686 display("cmp r0, r4");
6687 display("cmp r7, pc");
6688 display("cmp r1, r3");
6689 display("mov pc, 44");
6690 display("mov pc, r3");
6691 display("push {pc}");
6692 display("pop {pc}");
6693 display("nop");
6694 display("ldr r1, [r2, 33]");
6695 display("ldr r1, [r2, r3]");
6696 display("ldr r3, [r4, r6]");
6697 display("str r1, [pc, 33]");
6698 display("str r1, [pc], 2");
6699 display("str r1, [pc, 3]");
6700 display("str r1, [pc, r4]");
6701 display("bx r3");
6702 display("bcc 33");
6703 display("blx r3");
6704 display("bne 0x1200");
6705 display("str r0, [r1]");
6706 display("push {fp,lr}");
6707 display("pop {fp,lr}");
6708 display("pop {pc}");
6709 #endif
6710
6711 //10ab4: 00047e30 andeq r7, r4, r0, lsr lr
6712 //10ab8: 00036e70 andeq r6, r3, r0, ror lr
6713
6714 display("andeq r7, r4, r0, lsr lr");
6715 display("andeq r6, r3, r0, ror lr");
6716 // c4: e8bd80f0 pop {r4, r5, r6, r7, pc}
6717 display("pop {r4,r5,r6,r7,pc}");
6718
6719
6720 #if 0
6721 display("blx r1");
6722 display("blx 0x8048");
6723 #endif
6724
6725 #if 0
6726 display("b 0x123");
6727 display("bl 0x123");
6728 display("blt 0x123"); // XXX: not supported
6729 #endif
6730 return 0;
6731 }
6732 #endif
6733