fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1182 lines 25 kB view raw
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};