fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 804 lines 16 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/simarm/cmd_arm.c * 7 * Created: 2004-11-04 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2013 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 "main.h" 30#include "cmd_arm.h" 31#include "simarm.h" 32 33#include <cpu/arm/arm.h> 34 35#include <lib/console.h> 36#include <lib/log.h> 37#include <lib/monitor.h> 38#include <lib/sysdep.h> 39 40 41static mon_cmd_t par_cmd[] = { 42 { "c", "[cnt]", "clock" }, 43 { "gb", "[addr...]", "run with breakpoints" }, 44 { "g", "", "run" }, 45 { "key", "[val...]", "send keycodes to the serial console" }, 46 { "p", "[cnt]", "execute cnt instructions, skip calls [1]" }, 47 { "r", "reg [val]", "get or set a register" }, 48 { "s", "[what]", "print status (cpu|intc|mem|mmu|timer)" }, 49 { "t", "[cnt]", "execute cnt instructions [1]" }, 50 { "u", "[addr [cnt]]", "disassemble" }, 51 { "x", "[c|r|v]", "set the translation mode (cpu, real, virtual)" }, 52 { "xx", "[addr...]", "translate a virtual address" } 53}; 54 55 56static const char *arm_modes[32] = { 57 "0x00", "0x01", "0x02", "0x03", 58 "0x04", "0x05", "0x06", "0x07", 59 "0x08", "0x09", "0x0a", "0x0b", 60 "0x0c", "0x0d", "0x0e", "0x0f", 61 "usr", "fiq", "irq", "svc", 62 "0x14", "0x15", "0x16", "abt", 63 "0x18", "0x19", "und", "0x1b", 64 "0x1c", "0x1d", "0x1e", "sys" 65}; 66 67void sarm_dasm_str (char *dst, arm_dasm_t *op) 68{ 69 unsigned i, j; 70 71 if (op->argn == 0) { 72 sprintf (dst, "%08lX %s", (unsigned long) op->ir, op->op); 73 } 74 else { 75 j = sprintf (dst, "%08lX %-8s %s", (unsigned long) op->ir, op->op, op->arg[0]); 76 77 for (i = 1; i < op->argn; i++) { 78 j += sprintf (dst + j, ", %s", op->arg[i]); 79 } 80 } 81} 82 83void sarm_prt_state_cpu (arm_t *c, FILE *fp) 84{ 85 unsigned long long opcnt, clkcnt; 86 unsigned long delay; 87 arm_dasm_t op; 88 char str[256]; 89 90 pce_prt_sep ("ARM"); 91 92 opcnt = arm_get_opcnt (c); 93 clkcnt = arm_get_clkcnt (c); 94 delay = arm_get_delay (c); 95 96 fprintf (fp, "CLK=%llx OP=%llx DLY=%lx CPI=%.4f\n", 97 clkcnt, opcnt, delay, 98 (opcnt > 0) ? ((double) (clkcnt + delay) / (double) opcnt) : 1.0 99 ); 100 101 fprintf (fp, "r00=%08lX r04=%08lX r08=%08lX r12=%08lX CPSR=%08lX\n", 102 (unsigned long) arm_get_gpr (c, 0), 103 (unsigned long) arm_get_gpr (c, 4), 104 (unsigned long) arm_get_gpr (c, 8), 105 (unsigned long) arm_get_gpr (c, 12), 106 (unsigned long) arm_get_cpsr (c) 107 ); 108 109 fprintf (fp, "r01=%08lX r05=%08lX r09=%08lX r13=%08lX SPSR=%08lX\n", 110 (unsigned long) arm_get_gpr (c, 1), 111 (unsigned long) arm_get_gpr (c, 5), 112 (unsigned long) arm_get_gpr (c, 9), 113 (unsigned long) arm_get_gpr (c, 13), 114 (unsigned long) arm_get_spsr (c) 115 ); 116 117 fprintf (fp, "r02=%08lX r06=%08lX r10=%08lX r14=%08lX CC=[%c%c%c%c]\n", 118 (unsigned long) arm_get_gpr (c, 2), 119 (unsigned long) arm_get_gpr (c, 6), 120 (unsigned long) arm_get_gpr (c, 10), 121 (unsigned long) arm_get_gpr (c, 14), 122 (arm_get_cc_n (c)) ? 'N' : '-', 123 (arm_get_cc_z (c)) ? 'Z' : '-', 124 (arm_get_cc_c (c)) ? 'C' : '-', 125 (arm_get_cc_v (c)) ? 'V' : '-' 126 ); 127 128 fprintf (fp, "r03=%08lX r07=%08lX r11=%08lX r15=%08lX M=%02X (%s)\n", 129 (unsigned long) arm_get_gpr (c, 3), 130 (unsigned long) arm_get_gpr (c, 7), 131 (unsigned long) arm_get_gpr (c, 11), 132 (unsigned long) arm_get_gpr (c, 15), 133 (unsigned) arm_get_cpsr_m (c), 134 arm_modes[arm_get_cpsr_m (c) & 0x1f] 135 ); 136 137 arm_dasm_mem (c, &op, arm_get_pc (c), par_xlat); 138 sarm_dasm_str (str, &op); 139 140 fprintf (fp, "%08lX %s\n", (unsigned long) arm_get_pc (c), str); 141} 142 143void sarm_prt_state_mmu (arm_t *c, FILE *fp) 144{ 145 arm_copr15_t *p; 146 147 pce_prt_sep ("ARM MMU"); 148 149 p = c->copr[15]->ext; 150 151 fprintf (fp, "CR=[%c%c%c%c%c%c%c%c%c%c%c%c%c]\n", 152 (p->reg[1] & ARM_C15_CR_V) ? 'V' : 'v', 153 (p->reg[1] & ARM_C15_CR_I) ? 'I' : 'i', 154 (p->reg[1] & ARM_C15_CR_Z) ? 'Z' : 'z', 155 (p->reg[1] & ARM_C15_CR_R) ? 'R' : 'r', 156 (p->reg[1] & ARM_C15_CR_S) ? 'S' : 's', 157 (p->reg[1] & ARM_C15_CR_B) ? 'B' : 'b', 158 (p->reg[1] & ARM_C15_CR_L) ? 'L' : 'l', 159 (p->reg[1] & ARM_C15_CR_D) ? 'D' : 'd', 160 (p->reg[1] & ARM_C15_CR_P) ? 'P' : 'p', 161 (p->reg[1] & ARM_C15_CR_W) ? 'W' : 'w', 162 (p->reg[1] & ARM_C15_CR_C) ? 'C' : 'c', 163 (p->reg[1] & ARM_C15_CR_A) ? 'A' : 'a', 164 (p->reg[1] & ARM_C15_CR_M) ? 'M' : 'm' 165 ); 166 167 fprintf (fp, "c00=%08lX c04=%08lX c08=%08lX c12=%08lX\n", 168 (unsigned long) p->reg[0], 169 (unsigned long) p->reg[4], 170 (unsigned long) p->reg[8], 171 (unsigned long) p->reg[12] 172 ); 173 174 fprintf (fp, "c01=%08lX c05=%08lX c09=%08lX c13=%08lX\n", 175 (unsigned long) p->reg[1], 176 (unsigned long) p->reg[5], 177 (unsigned long) p->reg[9], 178 (unsigned long) p->reg[13] 179 ); 180 181 fprintf (fp, "c02=%08lX c06=%08lX c10=%08lX c14=%08lX\n", 182 (unsigned long) p->reg[2], 183 (unsigned long) p->reg[6], 184 (unsigned long) p->reg[10], 185 (unsigned long) p->reg[14] 186 ); 187 188 fprintf (fp, "c03=%08lX c07=%08lX c11=%08lX c15=%08lX\n", 189 (unsigned long) p->reg[3], 190 (unsigned long) p->reg[7], 191 (unsigned long) p->reg[11], 192 (unsigned long) p->reg[15] 193 ); 194} 195 196void sarm_prt_state_timer (ixp_timer_t *tmr, FILE *fp) 197{ 198 unsigned i; 199 ixp_timer_counter_t *cnt; 200 201 pce_prt_sep ("IXP TIMER"); 202 203 fprintf (fp, "ADDR=%08lX\n", tmr->base); 204 205 for (i = 0; i < 4; i++) { 206 cnt = &tmr->cntr[i]; 207 208 fprintf (fp, "T%u: %c VAL=%08lX LOAD=%08lX CTL=%08lX IRQ=%d\n", 209 i, 210 tmr_get_active (tmr, i) ? 'R' : 'S', 211 (unsigned long) cnt->status, 212 (unsigned long) cnt->load, 213 (unsigned long) cnt->ctrl, 214 cnt->irq_val != 0 215 ); 216 } 217} 218 219void sarm_prt_state_intc (simarm_t *sim, FILE *fp) 220{ 221 ixp_intc_t *ic; 222 223 pce_prt_sep ("IXP INTC"); 224 225 ic = sim->intc; 226 227 fprintf (fp, "inp raw: %08lx\n", ic->status_raw); 228 fprintf (fp, "ena irq: %08lx\n", ic->enable_irq); 229 fprintf (fp, "out irq: %08lx (%d)\n", ic->status_irq, (int) ic->irq_val); 230 fprintf (fp, "\n"); 231 fprintf (fp, "inp raw: %08lx\n", ic->status_raw); 232 fprintf (fp, "ena fiq: %08lx\n", ic->enable_fiq); 233 fprintf (fp, "out fiq: %08lx (%d)\n", ic->status_fiq, (int) ic->fiq_val); 234} 235 236void sarm_prt_state_mem (simarm_t *sim, FILE *fp) 237{ 238 pce_prt_sep ("ARM MEM"); 239 mem_prt_state (sim->mem, fp); 240} 241 242void prt_state (simarm_t *sim, FILE *fp, const char *str) 243{ 244 cmd_t cmd; 245 246 cmd_set_str (&cmd, str); 247 248 if (cmd_match_eol (&cmd)) { 249 return; 250 } 251 252 while (!cmd_match_eol (&cmd)) { 253 if (cmd_match (&cmd, "cpu")) { 254 sarm_prt_state_cpu (sim->cpu, fp); 255 } 256 else if (cmd_match (&cmd, "mmu")) { 257 sarm_prt_state_mmu (sim->cpu, fp); 258 } 259 else if (cmd_match (&cmd, "timer")) { 260 sarm_prt_state_timer (sim->timer, fp); 261 } 262 else if (cmd_match (&cmd, "intc")) { 263 sarm_prt_state_intc (sim, fp); 264 } 265 else if (cmd_match (&cmd, "mem")) { 266 sarm_prt_state_mem (sim, fp); 267 } 268 else { 269 printf ("unknown component (%s)\n", cmd_get_str (&cmd)); 270 return; 271 } 272 } 273} 274 275 276static 277void sarm_exec (simarm_t *sim) 278{ 279 unsigned long long old; 280 281 old = arm_get_opcnt (sim->cpu); 282 283 while (arm_get_opcnt (sim->cpu) == old) { 284 sarm_clock (sim, 1); 285 } 286} 287 288static 289int sarm_check_break (simarm_t *sim) 290{ 291 if (bps_check (&sim->bps, 0, arm_get_pc (sim->cpu), stdout)) { 292 return (1); 293 } 294 295 if (sim->brk) { 296 return (1); 297 } 298 299 return (0); 300} 301 302static 303int sarm_exec_to (simarm_t *sim, unsigned long addr) 304{ 305 while (arm_get_pc (sim->cpu) != addr) { 306 sarm_clock (sim, 1); 307 308 if (sim->brk) { 309 return (1); 310 } 311 } 312 313 return (0); 314} 315 316static 317int sarm_exec_off (simarm_t *sim, unsigned long addr) 318{ 319 while (arm_get_pc (sim->cpu) == addr) { 320 sarm_clock (sim, 1); 321 322 if (sim->brk) { 323 return (1); 324 } 325 } 326 327 return (0); 328} 329 330void sarm_run (simarm_t *sim) 331{ 332 pce_start (&sim->brk); 333 334 sarm_clock_discontinuity (sim); 335 336 while (1) { 337 sarm_clock (sim, 16); 338 339 if (sim->brk) { 340 break; 341 } 342 } 343 344 pce_stop(); 345} 346 347 348#if 0 349static 350int sarm_log_opcode (void *ext, unsigned long ir) 351{ 352 simarm_t *sim = ext; 353 354 return (0); 355} 356#endif 357 358static 359void sarm_log_undef (void *ext, unsigned long ir) 360{ 361 simarm_t *sim = ext; 362 363 if ((ir & 0x0f000000UL) == 0x0c000000UL) { 364 return; 365 } 366 367 if ((ir & 0x0f000000UL) == 0x0d000000UL) { 368 return; 369 } 370 371 pce_log (MSG_DEB, 372 "%08lX: undefined operation [%08lX]\n", 373 (unsigned long) arm_get_pc (sim->cpu), ir 374 ); 375} 376 377static 378void sarm_log_trap (void *ext, unsigned long addr) 379{ 380 simarm_t *sim = ext; 381 char *name; 382 383 switch (addr & 0xff) { 384 case 0x04: 385 name = "undefined operation"; 386 name = NULL; 387 break; 388 389 case 0x08: 390 name = "swi"; 391 name = NULL; 392 break; 393 394 case 0x0c: 395 name = "prefetch abort"; 396 name = NULL; 397 break; 398 399 case 0x10: 400 name = "data abort"; 401 name = NULL; 402 break; 403 404 case 0x18: 405 name = "irq"; 406 name = NULL; 407 break; 408 409 case 0x1c: 410 name = "fiq"; 411 break; 412 413 default: 414 name = "unknown"; 415 break; 416 } 417 418 if (name != NULL) { 419 pce_log (MSG_DEB, "%08lX (%08lX): exception %lx (%s)\n", 420 (unsigned long) arm_get_pc (sim->cpu), 421 (unsigned long) arm_get_last_pc (sim->cpu), 422 addr, name 423 ); 424 } 425} 426 427static 428void do_c (cmd_t *cmd, simarm_t *sim) 429{ 430 unsigned long cnt; 431 432 cnt = 1; 433 434 cmd_match_uint32 (cmd, &cnt); 435 436 if (!cmd_match_end (cmd)) { 437 return; 438 } 439 440 sarm_clock_discontinuity (sim); 441 442 while (cnt > 0) { 443 sarm_clock (sim, 1); 444 cnt -= 1; 445 } 446 447 sarm_prt_state_cpu (sim->cpu, stdout); 448} 449 450static 451void do_g_b (cmd_t *cmd, simarm_t *sim) 452{ 453 unsigned long addr; 454 breakpoint_t *bp; 455 456 while (cmd_match_uint32 (cmd, &addr)) { 457 bp = bp_addr_new (addr); 458 bps_bp_add (&sim->bps, bp); 459 } 460 461 if (!cmd_match_end (cmd)) { 462 return; 463 } 464 465 pce_start (&sim->brk); 466 467 sarm_clock_discontinuity (sim); 468 469 while (1) { 470 sarm_exec (sim); 471 472 if (sarm_check_break (sim)) { 473 break; 474 } 475 } 476 477 pce_stop(); 478} 479 480static 481void do_g (cmd_t *cmd, simarm_t *sim) 482{ 483 if (cmd_match (cmd, "b")) { 484 do_g_b (cmd, sim); 485 return; 486 } 487 488 if (!cmd_match_end (cmd)) { 489 return; 490 } 491 492 sarm_run (sim); 493} 494 495static 496void do_key (cmd_t *cmd, simarm_t *sim) 497{ 498 unsigned short c; 499 500 while (cmd_match_uint16 (cmd, &c)) { 501 sarm_set_keycode (sim, c); 502 } 503 504 if (!cmd_match_end (cmd)) { 505 return; 506 } 507} 508 509static 510void do_p (cmd_t *cmd, simarm_t *sim) 511{ 512 unsigned long cnt; 513 arm_dasm_t da; 514 515 cnt = 1; 516 517 cmd_match_uint32 (cmd, &cnt); 518 519 if (!cmd_match_end (cmd)) { 520 return; 521 } 522 523 pce_start (&sim->brk); 524 525 sarm_clock_discontinuity (sim); 526 527 while (cnt > 0) { 528 arm_dasm_mem (sim->cpu, &da, arm_get_pc (sim->cpu), ARM_XLAT_CPU); 529 530 if (da.flags & ARM_DFLAG_CALL) { 531 if (sarm_exec_to (sim, arm_get_pc (sim->cpu) + 4)) { 532 break; 533 } 534 } 535 else { 536 uint32_t cpsr; 537 538 cpsr = arm_get_cpsr (sim->cpu); 539 540 if (sarm_exec_off (sim, arm_get_pc (sim->cpu))) { 541 break; 542 } 543 544 if ((cpsr & ARM_PSR_M) == ARM_MODE_USR) { 545 /* check if exception occured */ 546 while (arm_get_cpsr_m (sim->cpu) != ARM_MODE_USR) { 547 sarm_clock (sim, 1); 548 549 if (sim->brk) { 550 break; 551 } 552 } 553 } 554 } 555 556 cnt -= 1; 557 } 558 559 pce_stop(); 560 561 sarm_prt_state_cpu (sim->cpu, stdout); 562} 563 564static 565void do_r (cmd_t *cmd, simarm_t *sim) 566{ 567 unsigned long val; 568 char sym[256]; 569 570 if (cmd_match_eol (cmd)) { 571 sarm_prt_state_cpu (sim->cpu, stdout); 572 return; 573 } 574 575 if (!cmd_match_ident (cmd, sym, 256)) { 576 printf ("missing register\n"); 577 return; 578 } 579 580 if (arm_get_reg (sim->cpu, sym, &val)) { 581 printf ("bad register (%s)\n", sym); 582 return; 583 } 584 585 if (cmd_match_eol (cmd)) { 586 printf ("%08lX\n", val); 587 return; 588 } 589 590 if (!cmd_match_uint32 (cmd, &val)) { 591 printf ("missing value\n"); 592 return; 593 } 594 595 if (!cmd_match_end (cmd)) { 596 return; 597 } 598 599 arm_set_reg (sim->cpu, sym, val); 600 601 sarm_prt_state_cpu (sim->cpu, stdout); 602} 603 604static 605void do_s (cmd_t *cmd, simarm_t *sim) 606{ 607 if (cmd_match_eol (cmd)) { 608 sarm_prt_state_cpu (sim->cpu, stdout); 609 return; 610 } 611 612 prt_state (sim, stdout, cmd_get_str (cmd)); 613} 614 615static 616void do_t (cmd_t *cmd, simarm_t *sim) 617{ 618 unsigned long i, n; 619 620 n = 1; 621 622 cmd_match_uint32 (cmd, &n); 623 624 if (!cmd_match_end (cmd)) { 625 return; 626 } 627 628 pce_start (&sim->brk); 629 630 sarm_clock_discontinuity (sim); 631 632 for (i = 0; i < n; i++) { 633 sarm_exec (sim); 634 } 635 636 pce_stop(); 637 638 sarm_prt_state_cpu (sim->cpu, stdout); 639} 640 641static 642void do_u (cmd_t *cmd, simarm_t *sim) 643{ 644 unsigned i; 645 int to; 646 unsigned long addr, cnt; 647 static unsigned int first = 1; 648 static unsigned long saddr = 0; 649 arm_dasm_t op; 650 char str[256]; 651 652 if (first) { 653 first = 0; 654 saddr = arm_get_pc (sim->cpu); 655 } 656 657 to = 0; 658 addr = saddr; 659 cnt = 16; 660 661 if (cmd_match (cmd, "-")) { 662 to = 1; 663 } 664 665 if (cmd_match_uint32 (cmd, &addr)) { 666 cmd_match_uint32 (cmd, &cnt); 667 } 668 669 if (!cmd_match_end (cmd)) { 670 return; 671 } 672 673 if (to) { 674 addr -= 4 * (cnt - 1); 675 } 676 677 for (i = 0; i < cnt; i++) { 678 arm_dasm_mem (sim->cpu, &op, addr, par_xlat); 679 sarm_dasm_str (str, &op); 680 681 fprintf (stdout, "%08lX %s\n", addr, str); 682 683 addr += 4; 684 } 685 686 saddr = addr; 687} 688 689static 690void do_xx (cmd_t *cmd, simarm_t *sim) 691{ 692 unsigned long addr1; 693 uint32_t addr2; 694 unsigned domn, perm; 695 696 while (cmd_match_uint32 (cmd, &addr1)) { 697 addr2 = addr1; 698 if (arm_translate_extern (sim->cpu, &addr2, par_xlat, &domn, &perm)) { 699 printf ("%08lX translation abort\n", addr1); 700 } 701 else { 702 printf ("%08lX -> %08lX D=%02X P=%02X\n", 703 addr1, (unsigned long) addr2, domn, perm 704 ); 705 } 706 } 707} 708 709static 710void do_x (cmd_t *cmd, simarm_t *sim) 711{ 712 if (cmd_match_eol (cmd)) { 713 switch (par_xlat) { 714 case ARM_XLAT_CPU: 715 printf ("xlat cpu\n"); 716 break; 717 718 case ARM_XLAT_REAL: 719 printf ("xlat real\n"); 720 break; 721 722 case ARM_XLAT_VIRTUAL: 723 printf ("xlat virtual\n"); 724 break; 725 726 default: 727 printf ("xlat unknown\n"); 728 break; 729 } 730 731 return; 732 } 733 734 if (cmd_match (cmd, "c")) { 735 par_xlat = ARM_XLAT_CPU; 736 } 737 else if (cmd_match (cmd, "r")) { 738 par_xlat = ARM_XLAT_REAL; 739 } 740 else if (cmd_match (cmd, "v")) { 741 par_xlat = ARM_XLAT_VIRTUAL; 742 } 743 else if (cmd_match (cmd, "x")) { 744 do_xx (cmd, sim); 745 } 746 else { 747 cmd_error (cmd, "unknown translation type"); 748 return; 749 } 750 751 if (!cmd_match_end (cmd)) { 752 return; 753 } 754} 755 756int sarm_do_cmd (simarm_t *sim, cmd_t *cmd) 757{ 758 if (cmd_match (cmd, "b")) { 759 cmd_do_b (cmd, &sim->bps); 760 } 761 else if (cmd_match (cmd, "c")) { 762 do_c (cmd, sim); 763 } 764 else if (cmd_match (cmd, "g")) { 765 do_g (cmd, sim); 766 } 767 else if (cmd_match (cmd, "key")) { 768 do_key (cmd, sim); 769 } 770 else if (cmd_match (cmd, "p")) { 771 do_p (cmd, sim); 772 } 773 else if (cmd_match (cmd, "r")) { 774 do_r (cmd, sim); 775 } 776 else if (cmd_match (cmd, "s")) { 777 do_s (cmd, sim); 778 } 779 else if (cmd_match (cmd, "t")) { 780 do_t (cmd, sim); 781 } 782 else if (cmd_match (cmd, "u")) { 783 do_u (cmd, sim); 784 } 785 else if (cmd_match (cmd, "x")) { 786 do_x (cmd, sim); 787 } 788 else { 789 return (1); 790 } 791 792 return (0); 793} 794 795void sarm_cmd_init (simarm_t *sim, monitor_t *mon) 796{ 797 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0])); 798 mon_cmd_add_bp (mon); 799 800 sim->cpu->log_ext = sim; 801 sim->cpu->log_opcode = NULL; 802 sim->cpu->log_undef = sarm_log_undef; 803 sim->cpu->log_exception = sarm_log_trap; 804}