fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1097 lines 20 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/spectrum/cmd.c * 7 * Created: 2022-02-02 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2022-2025 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include "main.h" 24#include "snapshot.h" 25#include "spectrum.h" 26#include "video.h" 27 28#include <stdio.h> 29#include <string.h> 30 31#include <lib/brkpt.h> 32#include <lib/cmd.h> 33#include <lib/console.h> 34#include <lib/log.h> 35#include <lib/monitor.h> 36#include <lib/sysdep.h> 37 38 39static mon_cmd_t par_cmd[] = { 40 { "c", "[cnt]", "clock" }, 41 { "gb", "[addr...]", "run with breakpoints" }, 42 { "g", "", "run" }, 43 { "hm", "", "print help on messages" }, 44 { "i", "port", "input a byte from a port" }, 45 { "last", "on|off", "start/stop recording pc values" }, 46 { "last", "[cnt [idx]]", "print last pc values [80 0]" }, 47 { "n", "[0|1]", "execute to next instruction" }, 48 { "o", "port val", "output a byte to a port" }, 49 { "p", "[cnt]", "execute cnt instructions, skip calls [1]" }, 50 { "r", "reg [val]", "set a register" }, 51 { "s", "[what]", "print status (cpu|mem)" }, 52 { "t", "[cnt]", "execute cnt instructions [1]" }, 53 { "u", "[addr [cnt]]", "disassemble" }, 54 { "xl", "fname", "load a snapshot" }, 55 { "xs", "fname", "save a snapshot" } 56}; 57 58 59void spec_last_set (spectrum_t *sim, unsigned pc); 60 61 62static 63void spec_disasm_str (char *dst, e8080_disasm_t *op, int with_pc, int with_comment) 64{ 65 unsigned i, k, n; 66 char comment[256]; 67 68 comment[0] = 0; 69 70 if (with_pc) { 71 n = sprintf (dst, "%04X ", (unsigned) op->pc); 72 } 73 else { 74 n = 0; 75 } 76 77 for (i = 0; i < op->data_cnt; i++) { 78 n += sprintf (dst + n, "%02X ", (unsigned) op->data[i]); 79 } 80 81 for (i = op->data_cnt; i < 4; i++) { 82 dst[n++] = ' '; 83 dst[n++] = ' '; 84 dst[n++] = ' '; 85 } 86 87 k = n + 8; 88 n += sprintf (dst + n, "%s", op->op); 89 90 if (op->arg_cnt > 0) { 91 while (n < k) { 92 dst[n++] = ' '; 93 } 94 95 n += sprintf (dst + n, "%s", op->arg[0]); 96 97 for (i = 1; i < op->arg_cnt; i++) { 98 n += sprintf (dst + n, ", %s", op->arg[i]); 99 } 100 } 101 102 if (with_comment && (comment[0] != 0)) { 103 while (n < 40) { 104 dst[n++] = ' '; 105 } 106 107 dst[n++] = ';'; 108 } 109 110 dst[n] = 0; 111} 112 113static 114void spec_disasm_cur (e8080_t *c, e8080_disasm_t *op) 115{ 116 if (e8080_get_flags (c) & E8080_FLAG_Z80) { 117 z80_disasm_cur (c, op); 118 } 119 else { 120 e8080_disasm_cur (c, op); 121 } 122} 123 124static 125void spec_disasm_mem (e8080_t *c, e8080_disasm_t *op, unsigned short addr) 126{ 127 if (e8080_get_flags (c) & E8080_FLAG_Z80) { 128 z80_disasm_mem (c, op, addr); 129 } 130 else { 131 e8080_disasm_mem (c, op, addr); 132 } 133} 134 135static 136void spec_print_cpu_z80_1 (e8080_t *c) 137{ 138 e8080_disasm_t op; 139 char str[256]; 140 141 spec_disasm_cur (c, &op); 142 spec_disasm_str (str, &op, 0, 0); 143 144 if (c->halt) { 145 pce_printf ("HALT=1 "); 146 } 147 148 pce_printf ( 149 "A=%02X BC=%04X DE=%04X HL=%04X IX=%04X IY=%04X SP=%04X PC=%04X PSW=%02X[%c%c%c%c%c] %s\n", 150 (unsigned) e8080_get_a (c), (unsigned) e8080_get_bc (c), 151 (unsigned) e8080_get_de (c), (unsigned) e8080_get_hl (c), 152 (unsigned) e8080_get_ix (c), (unsigned) e8080_get_iy (c), 153 (unsigned) e8080_get_sp (c), (unsigned) e8080_get_pc (c), 154 (unsigned) e8080_get_psw (c), 155 (e8080_get_sf (c)) ? 'S' : '-', 156 (e8080_get_zf (c)) ? 'Z' : '-', 157 (e8080_get_af (c)) ? 'A' : '-', 158 (e8080_get_pf (c)) ? 'P' : '-', 159 (e8080_get_cf (c)) ? 'C' : '-', 160 str 161 ); 162} 163 164static 165void spec_print_cpu_8080_1 (e8080_t *c) 166{ 167 e8080_disasm_t op; 168 char str[256]; 169 170 spec_disasm_cur (c, &op); 171 spec_disasm_str (str, &op, 0, 0); 172 173 if (c->halt) { 174 pce_printf ("HALT=1 "); 175 } 176 177 pce_printf ( 178 "A=%02X BC=%04X DE=%04X HL=%04X SP=%04X PC=%04X PSW=%02X[%c%c%c%c%c] %s\n", 179 (unsigned) e8080_get_a (c), (unsigned) e8080_get_bc (c), 180 (unsigned) e8080_get_de (c), (unsigned) e8080_get_hl (c), 181 (unsigned) e8080_get_sp (c), (unsigned) e8080_get_pc (c), 182 (unsigned) e8080_get_psw (c), 183 (e8080_get_sf (c)) ? 'S' : '-', 184 (e8080_get_zf (c)) ? 'Z' : '-', 185 (e8080_get_af (c)) ? 'A' : '-', 186 (e8080_get_pf (c)) ? 'P' : '-', 187 (e8080_get_cf (c)) ? 'C' : '-', 188 str 189 ); 190} 191 192static 193void spec_print_cpu_z80_2 (e8080_t *c) 194{ 195 e8080_disasm_t op; 196 char str[256]; 197 198 spec_disasm_cur (c, &op); 199 spec_disasm_str (str, &op, 1, 1); 200 201 pce_printf ( 202 "A=%02X BC=%04X DE=%04X HL=%04X IX=%04X IY=%04X" 203 " SP=%04X PC=%04X F=%02X[%c%c%c%c%c] [%c%c]\n" 204 "R=%02X I=%02X IM=%u IFF=%u/%u IPC=%04X ICNT=%u HALT=%u\n" 205 "%s\n", 206 e8080_get_a (c), e8080_get_bc (c), e8080_get_de (c), 207 e8080_get_hl (c), e8080_get_ix (c), e8080_get_iy (c), 208 e8080_get_sp (c), e8080_get_pc (c), 209 e8080_get_psw (c), 210 (e8080_get_sf (c)) ? 'S' : '-', 211 (e8080_get_zf (c)) ? 'Z' : '-', 212 (e8080_get_af (c)) ? 'A' : '-', 213 (e8080_get_pf (c)) ? 'P' : '-', 214 (e8080_get_cf (c)) ? 'C' : '-', 215 c->int_val ? 'I' : '-', 216 c->nmi_val ? 'N' : '-', 217 e8080_get_r (c), 218 e8080_get_i (c), 219 e8080_get_im (c), 220 e8080_get_iff1 (c), e8080_get_iff2 (c), 221 e8080_get_int_pc (c), e8080_get_int_cnt (c), 222 e8080_get_halt (c), 223 str 224 ); 225 226} 227 228static 229void spec_print_cpu_8080_2 (e8080_t *c) 230{ 231 e8080_disasm_t op; 232 char str[256]; 233 234 spec_disasm_cur (c, &op); 235 spec_disasm_str (str, &op, 1, 1); 236 237 pce_printf ( 238 "A=%02X BC=%04X DE=%04X HL=%04X SP=%04X PC=%04X PSW=%02X[%c%c%c%c%c]\n" 239 "%s\n", 240 (unsigned) e8080_get_a (c), (unsigned) e8080_get_bc (c), 241 (unsigned) e8080_get_de (c), (unsigned) e8080_get_hl (c), 242 (unsigned) e8080_get_sp (c), (unsigned) e8080_get_pc (c), 243 (unsigned) e8080_get_psw (c), 244 (e8080_get_sf (c)) ? 'S' : '-', 245 (e8080_get_zf (c)) ? 'Z' : '-', 246 (e8080_get_af (c)) ? 'A' : '-', 247 (e8080_get_pf (c)) ? 'P' : '-', 248 (e8080_get_cf (c)) ? 'C' : '-', 249 str 250 ); 251 252 if (c->halt) { 253 pce_printf ("HALT=1\n"); 254 } 255} 256 257void spec_print_cpu (e8080_t *c, int oneline) 258{ 259 if (oneline) { 260 if (e8080_get_flags (c) & E8080_FLAG_Z80) { 261 spec_print_cpu_z80_1 (c); 262 } 263 else { 264 spec_print_cpu_8080_1 (c); 265 } 266 } 267 else { 268 if (e8080_get_flags (c) & E8080_FLAG_Z80) { 269 spec_print_cpu_z80_2 (c); 270 } 271 else { 272 spec_print_cpu_8080_2 (c); 273 } 274 } 275} 276 277void print_state_cpu (e8080_t *c) 278{ 279 if (e8080_get_flags (c) & E8080_FLAG_Z80) { 280 pce_prt_sep ("Z80"); 281 } 282 else { 283 pce_prt_sep ("8080"); 284 } 285 286 spec_print_cpu (c, 0); 287} 288 289static 290void print_state_mem (spectrum_t *sim) 291{ 292 pce_prt_sep ("MEMORY"); 293 mem_prt_state (sim->mem, stdout); 294} 295 296static 297void print_state_system (spectrum_t *sim) 298{ 299 pce_prt_sep ("SPECTRUM"); 300 301 pce_printf ("IM=%u\n", e8080_get_im (sim->cpu)); 302 pce_printf ("FE = %02X\n", sim->port_fe); 303 pce_printf ("KEY=[%02X %02X %02X %02X %02X %02X %02X %02X]\n", 304 sim->keys[0], sim->keys[1], sim->keys[2], sim->keys[3], 305 sim->keys[4], sim->keys[5], sim->keys[6], sim->keys[7] 306 ); 307} 308 309static 310void print_state_video (spectrum_t *sim) 311{ 312 spec_video_t *vid; 313 314 vid = &sim->video; 315 316 pce_prt_sep ("VIDEO"); 317 318 pce_printf ("FRAME=%lu+%lu ROW=%u+%u COL=%u DE=%d\n", 319 vid->frame_counter, vid->frame_clock, vid->row, vid->row_clock, 2 * vid->row_clock, vid->de 320 ); 321} 322 323static 324void print_state (spectrum_t *sim, const char *str) 325{ 326 cmd_t cmd; 327 328 cmd_set_str (&cmd, str); 329 330 if (cmd_match_eol (&cmd)) { 331 return; 332 } 333 334 while (!cmd_match_eol (&cmd)) { 335 if (cmd_match (&cmd, "cpu")) { 336 print_state_cpu (sim->cpu); 337 } 338 else if (cmd_match (&cmd, "mem")) { 339 print_state_mem (sim); 340 } 341 else if (cmd_match (&cmd, "sys")) { 342 print_state_system (sim); 343 } 344 else if (cmd_match (&cmd, "video")) { 345 print_state_video (sim); 346 } 347 else { 348 printf ("unknown component (%s)\n", cmd_get_str (&cmd)); 349 return; 350 } 351 } 352} 353 354static 355int spec_check_break (spectrum_t *sim) 356{ 357 if (bps_check (&sim->bps, 0, e8080_get_pc (sim->cpu), stdout)) { 358 return (1); 359 } 360 361 if (sim->brk) { 362 return (1); 363 } 364 365 return (0); 366} 367 368static 369int spec_exec (spectrum_t *sim) 370{ 371 unsigned n1, n2; 372 373 n1 = e8080_get_opcnt (sim->cpu); 374 375 do { 376 spec_clock (sim); 377 378 if (sim->brk) { 379 return (1); 380 } 381 382 n2 = e8080_get_opcnt (sim->cpu); 383 } while (n1 == n2); 384 385 return (0); 386} 387 388static 389int spec_exec_to (spectrum_t *sim, unsigned short addr) 390{ 391 while (e8080_get_pc (sim->cpu) != addr) { 392 spec_exec (sim); 393 394 if (spec_check_break (sim)) { 395 return (1); 396 } 397 } 398 399 return (0); 400} 401 402static 403int spec_exec_off (spectrum_t *sim, unsigned short addr) 404{ 405 unsigned icnt; 406 407 icnt = e8080_get_int_cnt (sim->cpu); 408 409 while (e8080_get_pc (sim->cpu) == addr) { 410 spec_exec (sim); 411 412 if (spec_check_break (sim)) { 413 return (1); 414 } 415 416 if (e8080_get_int_cnt (sim->cpu) != icnt) { 417 if (spec_exec_to (sim, e8080_get_int_pc (sim->cpu))) { 418 return (1); 419 } 420 421 icnt = e8080_get_int_cnt (sim->cpu); 422 } 423 } 424 425 return (0); 426} 427 428void spec_run (spectrum_t *sim) 429{ 430 pce_start (&sim->brk); 431 432 spec_clock_discontinuity (sim); 433 434 while (1) { 435 spec_clock (sim); 436 437 if (sim->brk) { 438 break; 439 } 440 } 441 442 pce_stop(); 443} 444 445static 446int spec_hook_exec (void *ext) 447{ 448 spectrum_t *sim = ext; 449 450 spec_last_set (sim, e8080_get_pc (sim->cpu)); 451 452 return (0); 453} 454 455static 456int spec_hook_undef (void *ext, unsigned op) 457{ 458 spectrum_t *sim = ext; 459 460 pce_log (MSG_DEB, 461 "%04X: undefined operation [%02X %02X %02X %02X]\n", 462 (unsigned) e8080_get_pc (sim->cpu), 463 (unsigned) e8080_get_mem8 (sim->cpu, e8080_get_pc (sim->cpu)), 464 (unsigned) e8080_get_mem8 (sim->cpu, e8080_get_pc (sim->cpu) + 1), 465 (unsigned) e8080_get_mem8 (sim->cpu, e8080_get_pc (sim->cpu) + 2), 466 (unsigned) e8080_get_mem8 (sim->cpu, e8080_get_pc (sim->cpu) + 3) 467 ); 468 469 /* pce_usleep (5000); */ 470 471 return (0); 472} 473 474static 475int spec_hook_rst (void *ext, unsigned n) 476{ 477 return (0); 478} 479 480void spec_last_enable (spectrum_t *sim, int enable) 481{ 482 unsigned i; 483 484 enable = (enable != 0); 485 486 if (sim->last_enabled == enable) { 487 return; 488 } 489 490 sim->last_enabled = enable; 491 sim->last_idx = 0; 492 493 for (i = 0; i < SPEC_LAST_CNT; i++) { 494 sim->last[i] = 0; 495 } 496 497 if (sim->last_enabled) { 498 e8080_set_hook_exec_fct (sim->cpu, sim, spec_hook_exec); 499 } 500 else { 501 e8080_set_hook_exec_fct (sim->cpu, NULL, NULL); 502 } 503} 504 505unsigned spec_last_get (spectrum_t *sim, unsigned idx) 506{ 507 if (sim->last_enabled == 0) { 508 return (0); 509 } 510 511 if (idx == 0) { 512 return (e8080_get_pc (sim->cpu)); 513 } 514 515 if (idx > SPEC_LAST_CNT) { 516 return (0); 517 } 518 519 idx = (sim->last_idx + SPEC_LAST_CNT - (idx - 1)) % SPEC_LAST_CNT; 520 521 return (sim->last[idx]); 522} 523 524void spec_last_set (spectrum_t *sim, unsigned pc) 525{ 526 if (sim->last[sim->last_idx] == pc) { 527 return; 528 } 529 530 sim->last_idx = (sim->last_idx + 1) % SPEC_LAST_CNT; 531 sim->last[sim->last_idx] = pc; 532} 533 534static 535void spec_cmd_c (cmd_t *cmd, spectrum_t *sim) 536{ 537 unsigned short cnt; 538 539 cnt = 1; 540 541 cmd_match_uint16 (cmd, &cnt); 542 543 if (!cmd_match_end (cmd)) { 544 return; 545 } 546 547 while (cnt > 0) { 548 spec_clock (sim); 549 cnt -= 1; 550 } 551 552 print_state_cpu (sim->cpu); 553} 554 555static 556void spec_cmd_g_b (cmd_t *cmd, spectrum_t *sim) 557{ 558 unsigned short addr; 559 breakpoint_t *bp; 560 561 while (cmd_match_uint16 (cmd, &addr)) { 562 bp = bp_addr_new (addr); 563 bps_bp_add (&sim->bps, bp); 564 } 565 566 if (!cmd_match_end (cmd)) { 567 return; 568 } 569 570 pce_start (&sim->brk); 571 572 spec_clock_discontinuity (sim); 573 574 while (1) { 575 spec_exec (sim); 576 577 if (spec_check_break (sim)) { 578 break; 579 } 580 } 581 582 pce_stop(); 583} 584 585static 586void spec_cmd_g (cmd_t *cmd, spectrum_t *sim) 587{ 588 if (cmd_match (cmd, "b")) { 589 spec_cmd_g_b (cmd, sim); 590 return; 591 } 592 593 if (!cmd_match_end (cmd)) { 594 return; 595 } 596 597 spec_run (sim); 598} 599 600static 601void spec_cmd_hm (cmd_t *cmd) 602{ 603 pce_puts ( 604 "emu.exit\n" 605 "emu.reset\n" 606 "emu.stop\n" 607 "\n" 608 "emu.cas.commit\n" 609 "emu.cas.create <filename>\n" 610 "emu.cas.play\n" 611 "emu.cas.load [<pos>]\n" 612 "emu.cas.read <filename>\n" 613 "emu.cas.record\n" 614 "emu.cas.space\n" 615 "emu.cas.state\n" 616 "emu.cas.stop\n" 617 "emu.cas.truncate\n" 618 "emu.cas.write <filename>\n" 619 "\n" 620 "emu.term.fullscreen \"0\" | \"1\"\n" 621 "emu.term.fullscreen.toggle\n" 622 "emu.term.grab\n" 623 "emu.term.release\n" 624 "emu.term.screenshot [<filename>]\n" 625 "emu.term.title <title>\n" 626 ); 627} 628 629static 630void spec_cmd_i (cmd_t *cmd, spectrum_t *sim) 631{ 632 unsigned short port; 633 634 while (cmd_match_uint16 (cmd, &port)) { 635 pce_printf ("%04X: %02X\n", 636 port, e8080_get_port8 (sim->cpu, port) 637 ); 638 } 639 640 cmd_match_end (cmd); 641} 642 643static 644void spec_cmd_last (cmd_t *cmd, spectrum_t *sim) 645{ 646 unsigned i, j, k; 647 unsigned col, pc; 648 unsigned short idx, cnt; 649 650 if (cmd_match (cmd, "on")) { 651 spec_last_enable (sim, 1); 652 cmd_match_end (cmd); 653 return; 654 } 655 656 if (cmd_match (cmd, "off")) { 657 spec_last_enable (sim, 0); 658 cmd_match_end (cmd); 659 return; 660 } 661 662 if (sim->last_enabled == 0) { 663 return; 664 } 665 666 col = 8; 667 cnt = 128; 668 idx = 0; 669 670 cmd_match_uint16 (cmd, &cnt); 671 cmd_match_uint16 (cmd, &idx); 672 673 if (!cmd_match_end (cmd)) { 674 return; 675 } 676 677 cnt = (cnt + col - 1) / col; 678 679 for (i = cnt; i > 0; i--) { 680 for (j = col; j > 0; j--) { 681 k = idx + (j - 1) * cnt + i - 1; 682 pc = spec_last_get (sim, k); 683 pce_printf (" %04X", pc); 684 } 685 pce_putc ('\n'); 686 } 687} 688 689static 690void spec_cmd_n (cmd_t *cmd, spectrum_t *sim) 691{ 692 int s; 693 unsigned pc; 694 unsigned short i, n; 695 e8080_disasm_t dis; 696 697 n = 1; 698 s = 0; 699 700 if (cmd_match_uint16 (cmd, &n)) { 701 s = 1; 702 } 703 704 if (!cmd_match_end (cmd)) { 705 return; 706 } 707 708 pce_start (&sim->brk); 709 710 spec_clock_discontinuity (sim); 711 712 for (i = 0; i < n; i++) { 713 spec_disasm_cur (sim->cpu, &dis); 714 715 if (s) { 716 spec_print_cpu (sim->cpu, 1); 717 } 718 719 pc = (e8080_get_pc (sim->cpu) + dis.data_cnt) & 0xffff; 720 721 if (spec_exec_to (sim, pc)) { 722 pce_printf ("T %04X\n", pc); 723 break; 724 } 725 } 726 727 if (s) { 728 spec_print_cpu (sim->cpu, 1); 729 } 730 731 pce_stop(); 732 733 print_state_cpu (sim->cpu); 734} 735 736static 737void spec_cmd_o (cmd_t *cmd, spectrum_t *sim) 738{ 739 unsigned short port, val; 740 741 if (!cmd_match_uint16 (cmd, &port)) { 742 cmd_error (cmd, "need a port address"); 743 return; 744 } 745 746 if (!cmd_match_uint16 (cmd, &val)) { 747 cmd_error (cmd, "need a value"); 748 return; 749 } 750 751 if (!cmd_match_end (cmd)) { 752 return; 753 } 754 755 e8080_set_port8 (sim->cpu, port, val); 756} 757 758static 759void spec_cmd_p (cmd_t *cmd, spectrum_t *sim) 760{ 761 int s; 762 unsigned short i, n; 763 unsigned pc, to, op; 764 765 if (cmd_match (cmd, "o")) { 766 spec_cmd_n (cmd, sim); 767 return; 768 } 769 770 n = 1; 771 s = 0; 772 773 if (cmd_match_uint16 (cmd, &n)) { 774 s = 1; 775 } 776 777 if (!cmd_match_end (cmd)) { 778 return; 779 } 780 781 pce_start (&sim->brk); 782 783 spec_clock_discontinuity (sim); 784 785 for (i = 0; i < n; i++) { 786 if (s) { 787 spec_print_cpu (sim->cpu, 1); 788 } 789 790 pc = e8080_get_pc (sim->cpu); 791 op = e8080_get_mem8 (sim->cpu, pc); 792 to = pc; 793 794 if ((op == 0xcd) || ((op & 0xc7) == 0xc4)) { 795 /* call */ 796 to = (pc + 3) & 0xffff; 797 } 798 else if ((op & 0xc7) == 0xc7) { 799 /* rst */ 800 to = (pc + 1) & 0xffff; 801 } 802 else if (op == 0x10) { 803 /* djnz */ 804 to = (pc + 2) & 0xffff; 805 } 806 807 if (to != pc) { 808 if (spec_exec_to (sim, to)) { 809 pce_printf ("T %04X\n", pc); 810 break; 811 } 812 } 813 else { 814 if (spec_exec_off (sim, pc)) { 815 pce_printf ("F %04X\n", pc); 816 break; 817 } 818 } 819 } 820 821 if (s) { 822 spec_print_cpu (sim->cpu, 1); 823 } 824 825 pce_stop(); 826 827 print_state_cpu (sim->cpu); 828} 829 830static 831void spec_cmd_r (cmd_t *cmd, spectrum_t *sim) 832{ 833 unsigned long val; 834 char sym[256]; 835 836 if (cmd_match_eol (cmd)) { 837 print_state_cpu (sim->cpu); 838 return; 839 } 840 841 if (!cmd_match_ident (cmd, sym, 256)) { 842 cmd_error (cmd, "missing register"); 843 return; 844 } 845 846 if (e8080_get_reg (sim->cpu, sym, &val)) { 847 cmd_error (cmd, "bad register\n"); 848 return; 849 } 850 851 if (cmd_match_eol (cmd)) { 852 pce_printf ("%02lX\n", val); 853 return; 854 } 855 856 if (!cmd_match_uint32 (cmd, &val)) { 857 cmd_error (cmd, "missing value\n"); 858 return; 859 } 860 861 if (!cmd_match_end (cmd)) { 862 return; 863 } 864 865 e8080_set_reg (sim->cpu, sym, val); 866 867 print_state_cpu (sim->cpu); 868} 869 870static 871void spec_cmd_s (cmd_t *cmd, spectrum_t *sim) 872{ 873 if (cmd_match_eol (cmd)) { 874 print_state_cpu (sim->cpu); 875 return; 876 } 877 878 print_state (sim, cmd_get_str (cmd)); 879} 880 881static 882void spec_cmd_t (cmd_t *cmd, spectrum_t *sim) 883{ 884 int s; 885 unsigned short i, n; 886 887 n = 1; 888 s = 0; 889 890 if (cmd_match_uint16 (cmd, &n)) { 891 s = 1; 892 } 893 894 if (!cmd_match_end (cmd)) { 895 return; 896 } 897 898 pce_start (&sim->brk); 899 900 spec_clock_discontinuity (sim); 901 902 for (i = 0; i < n; i++) { 903 if (s) { 904 spec_print_cpu (sim->cpu, 1); 905 } 906 907 if (spec_exec (sim)) { 908 break; 909 } 910 } 911 912 if (s) { 913 spec_print_cpu (sim->cpu, 1); 914 } 915 916 pce_stop(); 917 918 print_state_cpu (sim->cpu); 919} 920 921static 922void spec_cmd_u (cmd_t *cmd, spectrum_t *sim) 923{ 924 int to; 925 unsigned i; 926 unsigned short addr, cnt, taddr; 927 static unsigned int first = 1; 928 static unsigned short saddr = 0; 929 e8080_disasm_t op; 930 char str[256]; 931 932 if (first) { 933 first = 0; 934 saddr = e8080_get_pc (sim->cpu); 935 } 936 937 to = 0; 938 addr = saddr; 939 cnt = 16; 940 941 if (cmd_match (cmd, "t")) { 942 to = 1; 943 } 944 945 if (cmd_match_uint16 (cmd, &addr)) { 946 cmd_match_uint16 (cmd, &cnt); 947 } 948 949 if (!cmd_match_end (cmd)) { 950 return; 951 } 952 953 if (to) { 954 if (addr < (2 * cnt)) { 955 taddr = 0; 956 } 957 else { 958 taddr = addr - 2 * cnt; 959 } 960 961 while (taddr <= addr) { 962 spec_disasm_mem (sim->cpu, &op, taddr); 963 spec_disasm_str (str, &op, 1, 1); 964 965 pce_printf ("%s\n", str); 966 967 taddr += op.data_cnt; 968 } 969 } 970 else { 971 for (i = 0; i < cnt; i++) { 972 spec_disasm_mem (sim->cpu, &op, addr); 973 spec_disasm_str (str, &op, 1, 1); 974 975 pce_printf ("%s\n", str); 976 977 addr += op.data_cnt; 978 } 979 } 980 981 saddr = addr; 982} 983 984static 985void spec_cmd_xl (cmd_t *cmd, spectrum_t *sim) 986{ 987 char name[256]; 988 989 if (!cmd_match_str (cmd, name, 256)) { 990 return; 991 } 992 993 if (!cmd_match_end (cmd)) { 994 return; 995 } 996 997 if (spec_snap_load (sim, name)) { 998 pce_printf ("load error (%s)\n", name); 999 } 1000} 1001 1002static 1003void spec_cmd_xs (cmd_t *cmd, spectrum_t *sim) 1004{ 1005 char name[256]; 1006 1007 if (!cmd_match_str (cmd, name, 256)) { 1008 return; 1009 } 1010 1011 if (!cmd_match_end (cmd)) { 1012 return; 1013 } 1014 1015 if (spec_snap_save (sim, name)) { 1016 pce_printf ("load error (%s)\n", name); 1017 } 1018} 1019 1020static 1021void spec_cmd_x (cmd_t *cmd, spectrum_t *sim) 1022{ 1023 if (cmd_match (cmd, "l")) { 1024 spec_cmd_xl (cmd, sim); 1025 } 1026 else if (cmd_match (cmd, "s")) { 1027 spec_cmd_xs (cmd, sim); 1028 } 1029 else { 1030 cmd_error (cmd, "\n"); 1031 } 1032} 1033 1034int spec_cmd (spectrum_t *sim, cmd_t *cmd) 1035{ 1036 if (sim->term != NULL) { 1037 trm_check (sim->term); 1038 } 1039 1040 if (cmd_match (cmd, "b")) { 1041 cmd_do_b (cmd, &sim->bps); 1042 } 1043 else if (cmd_match (cmd, "c")) { 1044 spec_cmd_c (cmd, sim); 1045 } 1046 else if (cmd_match (cmd, "g")) { 1047 spec_cmd_g (cmd, sim); 1048 } 1049 else if (cmd_match (cmd, "hm")) { 1050 spec_cmd_hm (cmd); 1051 } 1052 else if (cmd_match (cmd, "i")) { 1053 spec_cmd_i (cmd, sim); 1054 } 1055 else if (cmd_match (cmd, "last")) { 1056 spec_cmd_last (cmd, sim); 1057 } 1058 else if (cmd_match (cmd, "n")) { 1059 spec_cmd_n (cmd, sim); 1060 } 1061 else if (cmd_match (cmd, "o")) { 1062 spec_cmd_o (cmd, sim); 1063 } 1064 else if (cmd_match (cmd, "p")) { 1065 spec_cmd_p (cmd, sim); 1066 } 1067 else if (cmd_match (cmd, "r")) { 1068 spec_cmd_r (cmd, sim); 1069 } 1070 else if (cmd_match (cmd, "s")) { 1071 spec_cmd_s (cmd, sim); 1072 } 1073 else if (cmd_match (cmd, "t")) { 1074 spec_cmd_t (cmd, sim); 1075 } 1076 else if (cmd_match (cmd, "u")) { 1077 spec_cmd_u (cmd, sim); 1078 } 1079 else if (cmd_match (cmd, "x")) { 1080 spec_cmd_x (cmd, sim); 1081 } 1082 else { 1083 return (1); 1084 } 1085 1086 return (0); 1087} 1088 1089void spec_cmd_init (spectrum_t *sim, monitor_t *mon) 1090{ 1091 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0])); 1092 mon_cmd_add_bp (mon); 1093 1094 e8080_set_hook_exec_fct (sim->cpu, NULL, NULL); 1095 e8080_set_hook_undef_fct (sim->cpu, sim, spec_hook_undef); 1096 e8080_set_hook_rst_fct (sim->cpu, sim, spec_hook_rst); 1097}