fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/arm/disasm.c *
7 * Created: 2004-11-03 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2011 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "arm.h"
34#include "internal.h"
35
36
37static arm_dasm_f arm_dasm_op[256];
38
39
40enum {
41 ARG_NONE,
42
43 ARG_UIMM16,
44 ARG_UIMM24,
45 ARG_UIMM32,
46
47 ARG_RD,
48 ARG_RM,
49 ARG_RN,
50 ARG_RS,
51 ARG_RNI,
52
53 ARG_CD,
54 ARG_CN,
55 ARG_CM,
56
57 ARG_SH,
58
59 ARG_COPR,
60 ARG_COPR_OP1,
61 ARG_COPR_OP2,
62 ARG_COPR_OP3,
63
64 ARG_CPSR,
65 ARG_SPSR,
66 ARG_PSR_FLD,
67
68 ARG_AMODE2,
69 ARG_AMODE3,
70 ARG_AMODE4
71};
72
73
74enum {
75 FLG_NONE = 0,
76 FLG_COND = 1,
77 FLG_S = 2
78};
79
80
81static const char *arm_cond_names[16] = {
82 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
83 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"
84};
85
86static const char *arm_shifts[4] = {
87 "lsl", "lsr", "asr", "ror"
88};
89
90
91static
92unsigned dasm_arg (char *dst1, char *dst2, uint32_t ir, unsigned arg)
93{
94 switch (arg) {
95 case ARG_NONE:
96 dst1[0] = 0;
97 return (1);
98
99 case ARG_UIMM16:
100 sprintf (dst1, "0x%04lx", (unsigned long) (ir & 0xffffU));
101 return (1);
102
103 case ARG_UIMM24:
104 sprintf (dst1, "0x%06lx", (unsigned long) (ir & 0xffffffUL));
105 return (1);
106
107 case ARG_UIMM32:
108 sprintf (dst1, "0x%08lx", (unsigned long) ir);
109 return (1);
110
111 case ARG_RD:
112 if (arm_rd_is_pc (ir)) {
113 strcpy (dst1, "pc");
114 }
115 else {
116 sprintf (dst1, "r%u", (unsigned) arm_ir_rd (ir));
117 }
118 return (1);
119
120 case ARG_RM:
121 sprintf (dst1, "r%u", (unsigned) arm_ir_rm (ir));
122 return (1);
123
124 case ARG_RN:
125 sprintf (dst1, "r%u", (unsigned) arm_ir_rn (ir));
126 return (1);
127
128 case ARG_RS:
129 sprintf (dst1, "r%u", (unsigned) arm_ir_rs (ir));
130 return (1);
131
132 case ARG_RNI:
133 sprintf (dst1, "[r%u]", (unsigned) arm_ir_rn (ir));
134 return (1);
135
136 case ARG_CD:
137 sprintf (dst1, "c%u", (unsigned) arm_ir_rd (ir));
138 return (1);
139
140 case ARG_CN:
141 sprintf (dst1, "c%u", (unsigned) arm_ir_rn (ir));
142 return (1);
143
144 case ARG_CM:
145 sprintf (dst1, "c%u", (unsigned) arm_ir_rm (ir));
146 return (1);
147
148 case ARG_SH:
149 if (arm_ir_i (ir)) {
150 unsigned n;
151 uint32_t v;
152
153 n = arm_get_bits (ir, 8, 4) << 1;
154 v = arm_get_bits (ir, 0, 8);
155 v = arm_ror32 (v, n);
156
157 sprintf (dst1, "#0x%08lx", (unsigned long) v);
158
159 return (1);
160 }
161 else if ((ir & (1UL << 4)) == 0) {
162 unsigned n;
163 unsigned s;
164
165 n = arm_get_bits (ir, 7, 5);
166 s = arm_get_bits (ir, 5, 2);
167
168 if (n == 0) {
169 sprintf (dst1, "r%u", (unsigned) (ir & 0x0f));
170 if (s == 3) {
171 strcat (dst1, " rrx");
172 }
173 }
174 else {
175 sprintf (dst1, "r%u %s #%u", (unsigned) (ir & 0x0f), arm_shifts[s], n);
176 }
177
178 return (1);
179 }
180 else if ((ir & (1UL << 7)) == 0) {
181 unsigned rs = arm_get_bits (ir, 8, 4);
182 unsigned s = arm_get_bits (ir, 5, 2);
183
184 sprintf (dst1, "r%u %s r%u", (unsigned) (ir & 0x0f), arm_shifts[s], rs);
185
186 return (1);
187 }
188 return (0);
189
190 case ARG_COPR:
191 sprintf (dst1, "p%u", (unsigned) arm_get_bits (ir, 8, 4));
192 return (1);
193
194 case ARG_COPR_OP1:
195 sprintf (dst1, "0x%02X", (unsigned) arm_get_bits (ir, 21, 3));
196 return (1);
197
198 case ARG_COPR_OP2:
199 sprintf (dst1, "0x%02X", (unsigned) arm_get_bits (ir, 5, 3));
200 return (1);
201
202 case ARG_COPR_OP3:
203 sprintf (dst1, "0x%02X", (unsigned) arm_get_bits (ir, 4, 4));
204 return (1);
205
206 case ARG_CPSR:
207 strcpy (dst1, "cpsr");
208 return (1);
209
210 case ARG_SPSR:
211 strcpy (dst1, "spsr");
212 return (1);
213
214 case ARG_PSR_FLD:
215 if (arm_get_bit (ir, 22)) {
216 strcpy (dst1, "spsr_");
217 }
218 else {
219 strcpy (dst1, "cpsr_");
220 }
221
222 if (arm_get_bit (ir, 16)) {
223 strcat (dst1, "c");
224 }
225 if (arm_get_bit (ir, 17)) {
226 strcat (dst1, "x");
227 }
228 if (arm_get_bit (ir, 18)) {
229 strcat (dst1, "s");
230 }
231 if (arm_get_bit (ir, 19)) {
232 strcat (dst1, "f");
233 }
234 return (1);
235
236 case ARG_AMODE2:
237 {
238 int i, p, w;
239 char *fmt;
240
241 i = arm_get_bit (ir, 25);
242 p = arm_get_bit (ir, 24);
243 /* u = arm_get_bit (ir, 23); */
244 w = arm_get_bit (ir, 21);
245
246 if (i) {
247 if (p) {
248 fmt = w ? "[r%u %c r%u %s %u]!" : "[r%u %c r%u %s %u]";
249 }
250 else {
251 fmt = "[r%u] %c r%u %s %u";
252 }
253 sprintf (dst1, fmt, (unsigned) arm_ir_rn (ir),
254 arm_get_bit (ir, 23) ? '+' : '-',
255 (unsigned) arm_ir_rm (ir),
256 arm_shifts[arm_get_bits (ir, 5, 2)],
257 arm_get_bits (ir, 7, 5)
258 );
259 }
260 else {
261 unsigned long ofs = arm_extu (ir, 12);
262
263 if (p) {
264 if (w) {
265 fmt = "[r%u %c 0x%08lx]!";
266 }
267 else {
268 if (ofs == 0) {
269 fmt = "[r%u]";
270 }
271 else {
272 fmt = "[r%u %c 0x%08lx]";
273 }
274 }
275 }
276 else {
277 fmt = "[r%u] %c 0x%08lx";
278 }
279 sprintf (dst1, fmt, (unsigned) arm_ir_rn (ir),
280 arm_get_bit (ir, 23) ? '+' : '-', ofs
281 );
282 }
283 }
284 return (1);
285
286 case ARG_AMODE3:
287 {
288 int i, p, u, w;
289 char *fmt;
290
291 p = arm_get_bit (ir, 24);
292 u = arm_get_bit (ir, 23);
293 i = arm_get_bit (ir, 22);
294 w = arm_get_bit (ir, 21);
295
296 if (i == 0) {
297 if (p) {
298 fmt = w ? "[r%u %c r%u]!" : "[r%u %c r%u]";
299 }
300 else {
301 fmt = "[r%u] %c r%u";
302 }
303 sprintf (dst1, fmt, (unsigned) arm_ir_rn (ir),
304 u ? '+' : '-',
305 (unsigned) arm_ir_rm (ir)
306 );
307 }
308 else {
309 unsigned long ofs;
310
311 ofs = (arm_get_bits (ir, 8, 4) << 4) | arm_get_bits (ir, 0, 4);
312
313 if (p) {
314 if (w) {
315 fmt = "[r%u %c 0x%08lx]!";
316 }
317 else {
318 if (ofs == 0) {
319 fmt = "[r%u]";
320 }
321 else {
322 fmt = "[r%u %c 0x%08lx]";
323 }
324 }
325 }
326 else {
327 fmt = "[r%u] %c 0x%08lx";
328 }
329 sprintf (dst1, fmt, (unsigned) arm_ir_rn (ir),
330 arm_get_bit (ir, 23) ? '+' : '-', ofs
331 );
332 }
333 }
334 return (1);
335
336 case ARG_AMODE4:
337 {
338 unsigned i, j, n;
339
340 sprintf (dst1, "r%u", (unsigned) arm_ir_rn (ir));
341 if (arm_get_bit (ir, 21)) {
342 strcat (dst1, "!");
343 }
344
345 j = sprintf (dst2, "{ ");
346 n = 0;
347
348 for (i = 0; i < 16; i++) {
349 if (ir & (1UL << i)) {
350 if (n > 0) {
351 j += sprintf (dst2 + j, ", r%u", i);
352 }
353 else {
354 j += sprintf (dst2 + j, "r%u", i);
355 }
356
357 n += 1;
358 }
359 }
360 strcpy (dst2 + j, " }");
361
362 if (arm_get_bit (ir, 22)) {
363 strcat (dst2, "^");
364 }
365
366 return (2);
367 }
368 }
369
370 return (0);
371}
372
373static
374const char *dasm_cond (uint32_t ir)
375{
376 return (arm_cond_names[(ir >> 28) & 0x0f]);
377}
378
379static
380int dasm_op0 (arm_dasm_t *da, const char *op, unsigned flg)
381{
382 strcpy (da->op, op);
383
384 if (flg & FLG_COND) {
385 strcat (da->op, dasm_cond (da->ir));
386 }
387
388 if (flg & FLG_S) {
389 if (arm_ir_s (da->ir)) {
390 strcat (da->op, "s");
391 }
392 }
393
394 da->argn = 0;
395
396 return (0);
397}
398
399static
400int dasm_op1 (arm_dasm_t *da, const char *op, unsigned flg,
401 unsigned arg1)
402{
403 dasm_op0 (da, op, flg);
404
405 da->argn = dasm_arg (da->arg[0], da->arg[1], da->ir, arg1);
406
407 return (0);
408}
409
410static
411int dasm_op2 (arm_dasm_t *da, const char *op, unsigned flg,
412 unsigned arg1, unsigned arg2)
413{
414 dasm_op0 (da, op, flg);
415
416 da->argn = dasm_arg (da->arg[0], da->arg[1], da->ir, arg1);
417 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg2);
418
419 return (0);
420}
421
422static
423int dasm_op3 (arm_dasm_t *da, const char *op, unsigned flg,
424 unsigned arg1, unsigned arg2, unsigned arg3)
425{
426 dasm_op0 (da, op, flg);
427
428 da->argn = dasm_arg (da->arg[0], da->arg[1], da->ir, arg1);
429 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg2);
430 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg3);
431
432 return (0);
433}
434
435static
436int dasm_op4 (arm_dasm_t *da, const char *op, unsigned flg,
437 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4)
438{
439 dasm_op0 (da, op, flg);
440
441 da->argn = dasm_arg (da->arg[0], da->arg[1], da->ir, arg1);
442 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg2);
443 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg3);
444 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg4);
445
446 return (0);
447}
448
449static
450int dasm_op5 (arm_dasm_t *da, const char *op, unsigned flg,
451 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5)
452{
453 dasm_op0 (da, op, flg);
454
455 da->argn = dasm_arg (da->arg[0], da->arg[1], da->ir, arg1);
456 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg2);
457 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg3);
458 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg4);
459 da->argn += dasm_arg (da->arg[da->argn], da->arg[da->argn + 1], da->ir, arg5);
460
461 return (0);
462}
463
464
465static void opdud (arm_dasm_t *da)
466{
467 dasm_op1 (da, "???", FLG_COND, ARG_UIMM32);
468}
469
470/* 00 09: mul[cond][s] rn, rm, rs */
471static void opd00_09 (arm_dasm_t *da)
472{
473 dasm_op3 (da, "mul", FLG_COND | FLG_S, ARG_RN, ARG_RM, ARG_RS);
474}
475
476/* 00 0B: ldr/str[cond][h|sh|sb|d] rd, addressing_mode */
477static void opd00_0b (arm_dasm_t *da)
478{
479 if (arm_get_bits (da->ir, 5, 2) == 0) {
480 opdud (da);
481 return;
482 }
483
484 if (arm_get_bit (da->ir, 20)) {
485 dasm_op2 (da, "ldr", FLG_COND, ARG_RD, ARG_AMODE3);
486
487 if (arm_get_bit (da->ir, 6)) {
488 strcat (da->op, "s");
489 }
490
491 if (arm_get_bit (da->ir, 5)) {
492 strcat (da->op, "h");
493 }
494 else {
495 strcat (da->op, "b");
496 }
497 }
498 else {
499 if (arm_get_bit (da->ir, 6)) {
500 if (arm_get_bit (da->ir, 5)) {
501 dasm_op2 (da, "str", FLG_COND, ARG_RD, ARG_AMODE3);
502 }
503 else {
504 dasm_op2 (da, "ldr", FLG_COND, ARG_RD, ARG_AMODE3);
505 }
506
507 strcat (da->op, "d");
508 }
509 else {
510 dasm_op2 (da, "str", FLG_COND, ARG_RD, ARG_AMODE3);
511
512 if (arm_get_bit (da->ir, 5)) {
513 strcat (da->op, "h");
514 }
515 else {
516 strcat (da->op, "b");
517 }
518 }
519 }
520}
521
522/* 00 ext */
523static void opd00_ext (arm_dasm_t *da)
524{
525 switch (arm_get_shext (da->ir)) {
526 case 0x09:
527 opd00_09 (da);
528 break;
529
530 default:
531 opd00_0b (da);
532 break;
533 }
534}
535
536/* 00: and[cond][s] rd, rn, shifter_operand */
537static void opd00 (arm_dasm_t *da)
538{
539 if (arm_is_shext (da->ir)) {
540 opd00_ext (da);
541 }
542 else {
543 dasm_op3 (da, "and", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
544 }
545}
546
547/* 02 09: mla[cond][s] rd, rm, rs, rn */
548static void opd02_09 (arm_dasm_t *da)
549{
550 dasm_op4 (da, "mla", FLG_COND | FLG_S, ARG_RN, ARG_RM, ARG_RS, ARG_RD);
551}
552
553/* 02 ext */
554static void opd02_ext (arm_dasm_t *da)
555{
556 switch (arm_get_shext (da->ir)) {
557 case 0x09:
558 opd02_09 (da);
559 break;
560
561 default:
562 opd00_0b (da);
563 break;
564 }
565}
566
567/* 02: eor[cond][s] rd, rn, shifter_operand */
568static void opd02 (arm_dasm_t *da)
569{
570 if (arm_is_shext (da->ir)) {
571 opd02_ext (da);
572 }
573 else {
574 dasm_op3 (da, "eor", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
575 }
576}
577
578/* 04: sub[cond][s] rd, rn, shifter_operand */
579static void opd04 (arm_dasm_t *da)
580{
581 if (arm_is_shext (da->ir)) {
582 opd00_0b (da);
583 }
584 else {
585 dasm_op3 (da, "sub", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
586 }
587}
588
589/* 06: rsb[cond][s] rd, rn, shifter_operand */
590static void opd06 (arm_dasm_t *da)
591{
592 if (arm_is_shext (da->ir)) {
593 opd00_0b (da);
594 }
595 else {
596 dasm_op3 (da, "rsb", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
597 }
598}
599
600/* 08: add[cond][s] rd, rn, shifter_operand */
601static void opd08 (arm_dasm_t *da)
602{
603 if (arm_is_shext (da->ir)) {
604 if (arm_get_shext (da->ir) == 0x09) {
605 dasm_op4 (da, "umull", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_RM, ARG_RS);
606 }
607 else {
608 opd00_0b (da);
609 }
610 }
611 else {
612 dasm_op3 (da, "add", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
613 }
614}
615
616/* 0A: adc[cond][s] rd, rn, shifter_operand */
617static void opd0a (arm_dasm_t *da)
618{
619 if (arm_is_shext (da->ir)) {
620 if (arm_get_shext (da->ir) == 0x09) {
621 dasm_op4 (da, "umlal", FLG_COND | FLG_S, ARG_RN, ARG_RD, ARG_RM, ARG_RS);
622 }
623 else {
624 opd00_0b (da);
625 }
626 }
627 else {
628 dasm_op3 (da, "adc", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
629 }
630}
631
632/* 0C: sbc[cond][s] rd, rn, shifter_operand */
633static void opd0c (arm_dasm_t *da)
634{
635 if (arm_is_shext (da->ir)) {
636 if (arm_get_shext (da->ir) == 0x09) {
637 dasm_op4 (da, "smull", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_RM, ARG_RS);
638 }
639 else {
640 opd00_0b (da);
641 }
642 }
643 else {
644 dasm_op3 (da, "sbc", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
645 }
646}
647
648/* 0E: rsc[cond][s] rd, rn, shifter_operand */
649static void opd0e (arm_dasm_t *da)
650{
651 if (arm_is_shext (da->ir)) {
652 if (arm_get_shext (da->ir) == 0x09) {
653 dasm_op4 (da, "smlal", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_RM, ARG_RS);
654 }
655 else {
656 opd00_0b (da);
657 }
658 }
659 else {
660 dasm_op3 (da, "rsc", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
661 }
662}
663
664/* 10 00: mrs[cond] rd, cpsr */
665static void opd10_00 (arm_dasm_t *da)
666{
667 dasm_op2 (da, "mrs", FLG_COND, ARG_RD, ARG_CPSR);
668}
669
670/* 10 09: swp[cond] rd, rm, rn */
671static void opd10_09 (arm_dasm_t *da)
672{
673 dasm_op3 (da, "swp", FLG_COND, ARG_RD, ARG_RM, ARG_RNI);
674}
675
676/* 10 */
677static void opd10 (arm_dasm_t *da)
678{
679 switch (arm_get_bits (da->ir, 4, 4)) {
680 case 0x00:
681 opd10_00 (da);
682 break;
683
684 case 0x09:
685 opd10_09 (da);
686 break;
687
688 case 0x0b:
689 case 0x0d:
690 case 0x0f:
691 opd00_0b (da);
692 break;
693
694 default:
695 opdud (da);
696 break;
697 }
698}
699
700/* 11: tst[cond] rn, shifter_operand */
701static void opd11 (arm_dasm_t *da)
702{
703 if (arm_is_shext (da->ir)) {
704 opd00_0b (da);
705 }
706 else {
707 dasm_op2 (da, "tst", FLG_COND, ARG_RN, ARG_SH);
708 }
709}
710
711/* 12 00: msr[cond] fields, rm */
712static void opd12_00 (arm_dasm_t *da)
713{
714 dasm_op2 (da, "msr", FLG_COND, ARG_PSR_FLD, ARG_RM);
715}
716
717/* 12 01: bx[cond] rm */
718static void opd12_01 (arm_dasm_t *da)
719{
720 dasm_op1 (da, "bx", FLG_COND, ARG_RM);
721}
722
723/* 12 03: blx[cond] rm */
724static void opd12_03 (arm_dasm_t *da)
725{
726 dasm_op1 (da, "blx", FLG_COND, ARG_RM);
727
728 da->flags |= ARM_DFLAG_CALL;
729}
730
731/* 12 07: bkpt uimm16 */
732static void opd12_07 (arm_dasm_t *da)
733{
734 uint32_t v;
735
736 v = (da->ir & 0x0f) | ((da->ir >> 4) & 0xfff0);
737
738 dasm_op0 (da, "bkpt", FLG_COND);
739 da->argn = dasm_arg (da->arg[0], da->arg[1], v, ARG_UIMM16);
740}
741
742/* 12 */
743static void opd12 (arm_dasm_t *da)
744{
745 switch (da->ir & 0x0ff000f0) {
746 case 0x01200000:
747 opd12_00 (da);
748 break;
749
750 case 0x01200010:
751 opd12_01 (da);
752 break;
753
754 case 0x01200030:
755 opd12_03 (da);
756 break;
757
758 case 0x01200070:
759 opd12_07 (da);
760 break;
761
762 case 0x012000b0:
763 case 0x012000d0:
764 case 0x012000f0:
765 opd00_0b (da);
766 break;
767
768 default:
769 opdud (da);
770 break;
771 }
772}
773
774/* 13: teq[cond] rn, shifter_operand */
775static void opd13 (arm_dasm_t *da)
776{
777 if (arm_is_shext (da->ir)) {
778 opd00_0b (da);
779 }
780 else {
781 dasm_op2 (da, "teq", FLG_COND, ARG_RN, ARG_SH);
782 }
783}
784
785/* 14 00: mrs[cond] rd, spsr */
786static void opd14_00 (arm_dasm_t *da)
787{
788 dasm_op2 (da, "mrs", FLG_COND, ARG_RD, ARG_SPSR);
789}
790
791/* 14 09: swp[cond]b rd, rm, rn */
792static void opd14_09 (arm_dasm_t *da)
793{
794 dasm_op3 (da, "swp", FLG_COND, ARG_RD, ARG_RM, ARG_RNI);
795 strcat (da->op, "b");
796}
797
798/* 14 */
799static void opd14 (arm_dasm_t *da)
800{
801 switch (arm_get_bits (da->ir, 4, 4)) {
802 case 0x00:
803 opd14_00 (da);
804 break;
805
806 case 0x09:
807 opd14_09 (da);
808 break;
809
810 case 0x0b:
811 case 0x0d:
812 case 0x0f:
813 opd00_0b (da);
814 break;
815
816 default:
817 opdud (da);
818 break;
819 }
820}
821
822/* 15: cmp[cond] rn, shifter_operand */
823static void opd15 (arm_dasm_t *da)
824{
825 if (arm_is_shext (da->ir)) {
826 opd00_0b (da);
827 }
828 else {
829 dasm_op2 (da, "cmp", FLG_COND, ARG_RN, ARG_SH);
830 }
831}
832
833/* 16 01: clz rd, rm */
834static void opd16_01 (arm_dasm_t *da)
835{
836 dasm_op2 (da, "clz", FLG_COND, ARG_RD, ARG_RM);
837}
838
839/* 16 08: smulxy[cond] rd, rm, rs */
840static void opd16_08 (arm_dasm_t *da)
841{
842 char op[16];
843
844 strcpy (op, "smul");
845 strcat (op, arm_get_bit (da->ir, 5) ? "t" : "b");
846 strcat (op, arm_get_bit (da->ir, 6) ? "t" : "b");
847
848 dasm_op3 (da, op, FLG_COND, ARG_RN, ARG_RM, ARG_RS);
849}
850
851/* 16 */
852static void opd16 (arm_dasm_t *da)
853{
854 switch (da->ir & 0x0ff000f0UL) {
855 case 0x01600000UL:
856 opd12_00 (da);
857 break;
858
859 case 0x01600010UL:
860 opd16_01 (da);
861 break;
862
863 case 0x01600080UL:
864 case 0x016000a0UL:
865 case 0x016000c0UL:
866 case 0x016000e0UL:
867 opd16_08 (da);
868 break;
869
870 case 0x016000b0UL:
871 case 0x016000d0UL:
872 case 0x016000f0UL:
873 opd00_0b (da);
874 break;
875
876 default:
877 opdud (da);
878 break;
879 }
880}
881
882/* 17: cmn[cond] rn, shifter_operand */
883static void opd17 (arm_dasm_t *da)
884{
885 if (arm_is_shext (da->ir)) {
886 opd00_0b (da);
887 }
888 else {
889 dasm_op2 (da, "cmn", FLG_COND, ARG_RN, ARG_SH);
890 }
891}
892
893/* 18: orr[cond][s] rd, rn, shifter_operand */
894static void opd18 (arm_dasm_t *da)
895{
896 if (arm_is_shext (da->ir)) {
897 opd00_0b (da);
898 }
899 else {
900 dasm_op3 (da, "orr", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
901 }
902}
903
904/* 1A: mov[cond][s] rd, shifter_operand */
905static void opd1a (arm_dasm_t *da)
906{
907 if (arm_is_shext (da->ir)) {
908 opd00_0b (da);
909 }
910 else {
911 dasm_op2 (da, "mov", FLG_COND | FLG_S, ARG_RD, ARG_SH);
912 }
913}
914
915/* 1C: bic[cond][s] rd, rn, shifter_operand */
916static void opd1c (arm_dasm_t *da)
917{
918 if (arm_is_shext (da->ir)) {
919 opd00_0b (da);
920 }
921 else {
922 dasm_op3 (da, "bic", FLG_COND | FLG_S, ARG_RD, ARG_RN, ARG_SH);
923 }
924}
925
926/* 1E: mvn[cond][s] rd, shifter_operand */
927static void opd1e (arm_dasm_t *da)
928{
929 if (arm_is_shext (da->ir)) {
930 opd00_0b (da);
931 }
932 else {
933 dasm_op2 (da, "mvn", FLG_COND | FLG_S, ARG_RD, ARG_SH);
934 }
935}
936
937/* 32: msr[cond] fields, #imm */
938static void opd32 (arm_dasm_t *da)
939{
940 dasm_op2 (da, "msr", FLG_COND, ARG_PSR_FLD, ARG_SH);
941}
942
943/* 40: ldr/str[cond][b][t] rd, address */
944static void opd40 (arm_dasm_t *da)
945{
946 if (arm_get_bit (da->ir, 20)) {
947 dasm_op2 (da, "ldr", FLG_COND, ARG_RD, ARG_AMODE2);
948 }
949 else {
950 dasm_op2 (da, "str", FLG_COND, ARG_RD, ARG_AMODE2);
951 }
952
953 if (arm_get_bit (da->ir, 22)) {
954 strcat (da->op, "b");
955 }
956
957 if ((arm_get_bit (da->ir, 24) == 0) && (arm_get_bit (da->ir, 21) == 1)) {
958 strcat (da->op, "t");
959 }
960}
961
962/* 80: ldm/stm[cond][mode] rn[!], registers[^] */
963static void opd80 (arm_dasm_t *da)
964{
965 if (arm_get_bit (da->ir, 20)) {
966 dasm_op1 (da, "ldm", FLG_COND, ARG_AMODE4);
967 }
968 else {
969 dasm_op1 (da, "stm", FLG_COND, ARG_AMODE4);
970 }
971
972 strcat (da->op, arm_get_bit (da->ir, 23) ? "i" : "d");
973 strcat (da->op, arm_get_bit (da->ir, 24) ? "b" : "a");
974}
975
976/* A0: b[cond] target */
977static void opda0 (arm_dasm_t *da)
978{
979 uint32_t d;
980
981 d = arm_exts (da->ir, 24);
982 d = (da->pc + (d << 2) + 8) & 0xffffffffUL;
983
984 dasm_op0 (da, "b", FLG_COND);
985 da->argn = dasm_arg (da->arg[0], da->arg[1], d, ARG_UIMM32);
986}
987
988/* B0: bl[cond] target */
989static void opdb0 (arm_dasm_t *da)
990{
991 uint32_t d;
992
993 d = arm_exts (da->ir, 24);
994 d = (da->pc + (d << 2) + 8) & 0xffffffffUL;
995
996 dasm_op0 (da, "bl", FLG_COND);
997 da->argn = dasm_arg (da->arg[0], da->arg[1], d, ARG_UIMM32);
998
999 da->flags |= ARM_DFLAG_CALL;
1000}
1001
1002/* C4: mcrr[cond] coproc, opcode, rd, rn, crm */
1003static void opdc4 (arm_dasm_t *da)
1004{
1005 dasm_op5 (da, "mcrr", FLG_COND, ARG_COPR, ARG_COPR_OP3, ARG_RD, ARG_RN, ARG_RM);
1006}
1007
1008/* C5: mrrc[cond] coproc, opcode, rd, rn, crm */
1009static void opdc5 (arm_dasm_t *da)
1010{
1011 dasm_op5 (da, "mrrc", FLG_COND, ARG_COPR, ARG_COPR_OP3, ARG_RD, ARG_RN, ARG_RM);
1012}
1013
1014/* E0 00: cdp[cond] coproc, opcode1, crd, crn, crm, opcode2 */
1015static void opde0_00 (arm_dasm_t *da)
1016{
1017 unsigned n;
1018
1019 if (arm_get_bits (da->ir, 28, 4) == 0x0f) {
1020 dasm_op0 (da, "cdp2", FLG_NONE);
1021 }
1022 else {
1023 dasm_op0 (da, "cdp", FLG_COND);
1024 }
1025
1026 n = dasm_arg (da->arg[0], da->arg[1], da->ir, ARG_COPR);
1027 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP1);
1028 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CD);
1029 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CN);
1030 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CM);
1031
1032 if (arm_get_bits (da->ir, 5, 3) != 0) {
1033 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP2);
1034 }
1035
1036 da->argn = n;
1037}
1038
1039/* E0 01: mcr[cond] coproc, opcode1, rd, crn, crm, opcode2 */
1040static void opde0_01 (arm_dasm_t *da)
1041{
1042 unsigned n;
1043
1044 if (arm_get_bits (da->ir, 28, 4) == 0x0f) {
1045 dasm_op0 (da, "mcr2", FLG_NONE);
1046 }
1047 else {
1048 dasm_op0 (da, "mcr", FLG_COND);
1049 }
1050
1051 n = dasm_arg (da->arg[0], da->arg[1], da->ir, ARG_COPR);
1052 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP1);
1053 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_RD);
1054 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CN);
1055 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CM);
1056
1057 if (arm_get_bits (da->ir, 5, 3) != 0) {
1058 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP2);
1059 }
1060
1061 da->argn = n;
1062}
1063
1064/* E0 11: mrc[cond] coproc, opcode1, rd, crn, crm, opcode2 */
1065static void opde0_11 (arm_dasm_t *da)
1066{
1067 unsigned n;
1068
1069 if (arm_get_bits (da->ir, 28, 4) == 0x0f) {
1070 dasm_op0 (da, "mrc2", FLG_NONE);
1071 }
1072 else {
1073 dasm_op0 (da, "mrc", FLG_COND);
1074 }
1075
1076 n = dasm_arg (da->arg[0], da->arg[1], da->ir, ARG_COPR);
1077 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP1);
1078 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_RD);
1079 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CN);
1080 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_CM);
1081
1082 if (arm_get_bits (da->ir, 5, 3) != 0) {
1083 n += dasm_arg (da->arg[n], da->arg[n + 1], da->ir, ARG_COPR_OP2);
1084 }
1085
1086 da->argn = n;
1087}
1088
1089/* E0 */
1090static void opde0 (arm_dasm_t *da)
1091{
1092 switch (da->ir & 0x00100010UL) {
1093 case 0x00000000UL:
1094 case 0x00100000UL:
1095 opde0_00 (da);
1096 break;
1097
1098 case 0x00000010UL:
1099 opde0_01 (da);
1100 break;
1101
1102 case 0x00100010UL:
1103 opde0_11 (da);
1104 break;
1105
1106 default:
1107 opdud (da);
1108 break;
1109 }
1110}
1111
1112/* F0: swi[cond] immediate */
1113static void opdf0 (arm_dasm_t *da)
1114{
1115 dasm_op1 (da, "swi", FLG_COND, ARG_UIMM24);
1116}
1117
1118
1119void arm_dasm (arm_dasm_t *da, uint32_t pc, uint32_t ir)
1120{
1121 da->flags = 0;
1122
1123 da->pc = pc;
1124 da->ir = ir;
1125
1126 arm_dasm_op[(ir >> 20) & 0xff] (da);
1127}
1128
1129void arm_dasm_mem (arm_t *c, arm_dasm_t *da, uint32_t pc, unsigned xlat)
1130{
1131 uint32_t ir;
1132
1133 da->flags = 0;
1134
1135 if (arm_get_mem32 (c, pc, xlat, &ir)) {
1136 da->pc = pc;
1137 da->ir = 0xffffffffUL;
1138
1139 dasm_op0 (da, "<xlat>", FLG_NONE);
1140
1141 da->flags |= ARM_DFLAG_TLBM;
1142 }
1143 else {
1144 arm_dasm (da, pc, ir);
1145 }
1146}
1147
1148static
1149arm_dasm_f arm_dasm_op[256] = {
1150 opd00, opd00, opd02, opd02, opd04, opd04, opd06, opd06, /* 00 */
1151 opd08, opd08, opd0a, opd0a, opd0c, opd0c, opd0e, opd0e,
1152 opd10, opd11, opd12, opd13, opd14, opd15, opd16, opd17, /* 10 */
1153 opd18, opd18, opd1a, opd1a, opd1c, opd1c, opd1e, opd1e,
1154 opd00, opd00, opd02, opd02, opd04, opd04, opd06, opd06, /* 20 */
1155 opd08, opd08, opd0a, opd0a, opd0c, opd0c, opd0e, opd0e,
1156 opdud, opd11, opd32, opd13, opdud, opd15, opdud, opd17, /* 30 */
1157 opd18, opd18, opd1a, opd1a, opd1c, opd1c, opd1e, opd1e,
1158 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40, /* 40 */
1159 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40,
1160 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40, /* 50 */
1161 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40,
1162 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40, /* 60 */
1163 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40,
1164 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40, /* 70 */
1165 opd40, opd40, opd40, opd40, opd40, opd40, opd40, opd40,
1166 opd80, opd80, opd80, opd80, opd80, opd80, opd80, opd80, /* 80 */
1167 opd80, opd80, opd80, opd80, opd80, opd80, opd80, opd80,
1168 opd80, opd80, opd80, opd80, opd80, opd80, opd80, opd80, /* 90 */
1169 opd80, opd80, opd80, opd80, opd80, opd80, opd80, opd80,
1170 opda0, opda0, opda0, opda0, opda0, opda0, opda0, opda0, /* a0 */
1171 opda0, opda0, opda0, opda0, opda0, opda0, opda0, opda0,
1172 opdb0, opdb0, opdb0, opdb0, opdb0, opdb0, opdb0, opdb0, /* b0 */
1173 opdb0, opdb0, opdb0, opdb0, opdb0, opdb0, opdb0, opdb0,
1174 opdud, opdud, opdud, opdud, opdc4, opdc5, opdud, opdud, /* c0 */
1175 opdud, opdud, opdud, opdud, opdud, opdud, opdud, opdud,
1176 opdud, opdud, opdud, opdud, opdud, opdud, opdud, opdud, /* d0 */
1177 opdud, opdud, opdud, opdud, opdud, opdud, opdud, opdud,
1178 opde0, opde0, opde0, opde0, opde0, opde0, opde0, opde0, /* e0 */
1179 opde0, opde0, opde0, opde0, opde0, opde0, opde0, opde0,
1180 opdf0, opdf0, opdf0, opdf0, opdf0, opdf0, opdf0, opdf0, /* f0 */
1181 opdf0, opdf0, opdf0, opdf0, opdf0, opdf0, opdf0, opdf0
1182};