fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1475 lines 27 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/ibmpc/cmd.c * 7 * Created: 2010-09-21 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2010-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 "ibmpc.h" 25 26#include <stdio.h> 27#include <string.h> 28 29#include <lib/brkpt.h> 30#include <lib/cmd.h> 31#include <lib/console.h> 32#include <lib/log.h> 33#include <lib/monitor.h> 34#include <lib/msgdsk.h> 35#include <lib/sysdep.h> 36 37 38static mon_cmd_t par_cmd[] = { 39 { "boot", "[drive]", "set the boot drive" }, 40 { "c", "[cnt]", "clock [1]" }, 41 { "gb", "[addr...]", "run with breakpoints" }, 42 { "g", "far", "run until CS changes" }, 43 { "g", "", "run" }, 44 { "hm", "", "print help on messages" }, 45 { "i", "[b|w] port", "input a byte or word from a port" }, 46 { "key", "[[+|-]key...]", "simulate pressing or releasing keys" }, 47 { "log", "int l", "list interrupt log expressions" }, 48 { "log", "int n [expr]", "set interrupt n log expression to expr" }, 49 { "o", "[b|w] port val", "output a byte or word to a port" }, 50 { "pq", "[c|f|s]", "prefetch queue clear/fill/status" }, 51 { "p", "[cnt]", "execute cnt instructions, without trace in calls [1]" }, 52 { "r", "[reg val]", "set a register" }, 53 { "s", "[what]", "print status (pc|cpu|disks|ems|mem|pic|pit|ports|ppi|time|uart|video|xms)" }, 54 { "trace", "on|off|expr", "turn trace on or off" }, 55 { "t", "[cnt]", "execute cnt instructions [1]" }, 56 { "u", "[addr [cnt [mode]]]", "disassemble" } 57}; 58 59 60static 61void disasm_str (char *dst, e86_disasm_t *op) 62{ 63 unsigned i; 64 unsigned dst_i; 65 66 dst_i = 2; 67 sprintf (dst, "%02X", op->dat[0]); 68 69 for (i = 1; i < op->dat_n; i++) { 70 sprintf (dst + dst_i, " %02X", op->dat[i]); 71 dst_i += 3; 72 } 73 74 dst[dst_i++] = ' '; 75 while (dst_i < 20) { 76 dst[dst_i++] = ' '; 77 } 78 79 if ((op->flags & ~(E86_DFLAGS_CALL | E86_DFLAGS_LOOP)) != 0) { 80 unsigned flg; 81 82 flg = op->flags; 83 84 dst[dst_i++] = '['; 85 86 if (flg & E86_DFLAGS_186) { 87 dst_i += sprintf (dst + dst_i, "186"); 88 flg &= ~E86_DFLAGS_186; 89 } 90 91 if (flg != 0) { 92 if (flg != op->flags) { 93 dst[dst_i++] = ' '; 94 } 95 dst_i += sprintf (dst + dst_i, " %04X", flg); 96 } 97 dst[dst_i++] = ']'; 98 dst[dst_i++] = ' '; 99 } 100 101 strcpy (dst + dst_i, op->op); 102 while (dst[dst_i] != 0) { 103 dst_i += 1; 104 } 105 106 if (op->arg_n > 0) { 107 dst[dst_i++] = ' '; 108 while (dst_i < 26) { 109 dst[dst_i++] = ' '; 110 } 111 } 112 113 if (op->arg_n == 1) { 114 dst_i += sprintf (dst + dst_i, "%s", op->arg1); 115 } 116 else if (op->arg_n == 2) { 117 dst_i += sprintf (dst + dst_i, "%s, %s", op->arg1, op->arg2); 118 } 119 120 dst[dst_i] = 0; 121} 122 123static 124void prt_uint8_bin (unsigned char val) 125{ 126 unsigned i; 127 unsigned char m; 128 char str[16]; 129 130 m = 0x80; 131 132 for (i = 0; i < 8; i++) { 133 str[i] = (val & m) ? '1' : '0'; 134 m = m >> 1; 135 } 136 137 str[8] = 0; 138 139 pce_puts (str); 140} 141 142static 143void prt_state_video (video_t *vid) 144{ 145 FILE *fp; 146 147 pce_prt_sep ("video"); 148 149 pce_video_print_info (vid, pce_get_fp_out()); 150 151 fp = pce_get_redir_out(); 152 if (fp != NULL) { 153 pce_video_print_info (vid, fp); 154 } 155} 156 157static 158void prt_state_ems (ems_t *ems) 159{ 160 pce_prt_sep ("EMS"); 161 ems_prt_state (ems); 162} 163 164static 165void prt_state_xms (xms_t *xms) 166{ 167 pce_prt_sep ("XMS"); 168 xms_prt_state (xms); 169} 170 171static 172void prt_state_pit (e8253_t *pit) 173{ 174 unsigned i; 175 e8253_counter_t *cnt; 176 177 pce_prt_sep ("8253-PIT"); 178 179 for (i = 0; i < 3; i++) { 180 cnt = &pit->counter[i]; 181 182 pce_printf ( 183 "C%d: SR=%02X M=%u RW=%d CE=%04X %s=%02X %s=%02X %s=%02X %s=%02X " 184 "G=%u O=%u R=%d\n", 185 i, 186 cnt->sr, cnt->mode, cnt->rw, 187 cnt->ce, 188 (cnt->cr_wr & 2) ? "cr1" : "CR1", cnt->cr[1], 189 (cnt->cr_wr & 1) ? "cr0" : "CR0", cnt->cr[0], 190 (cnt->ol_rd & 2) ? "ol1" : "OL1", cnt->ol[1], 191 (cnt->ol_rd & 1) ? "ol0" : "OL0", cnt->ol[0], 192 (unsigned) cnt->gate_val, 193 (unsigned) cnt->out_val, 194 cnt->counting 195 ); 196 } 197} 198 199static 200void prt_state_ppi (e8255_t *ppi) 201{ 202 pce_prt_sep ("8255-PPI"); 203 204 pce_printf ( 205 "MOD=%02X MODA=%u MODB=%u", 206 ppi->mode, ppi->group_a_mode, ppi->group_b_mode 207 ); 208 209 if (ppi->port[0].inp != 0) { 210 pce_printf (" A=I[%02X]", e8255_get_inp (ppi, 0)); 211 } 212 else { 213 pce_printf (" A=O[%02X]", e8255_get_out (ppi, 0)); 214 } 215 216 if (ppi->port[1].inp != 0) { 217 pce_printf (" B=I[%02X]", e8255_get_inp (ppi, 1)); 218 } 219 else { 220 pce_printf (" B=O[%02X]", e8255_get_out (ppi, 1)); 221 } 222 223 switch (ppi->port[2].inp) { 224 case 0xff: 225 pce_printf (" C=I[%02X]", e8255_get_inp (ppi, 2)); 226 break; 227 228 case 0x00: 229 pce_printf (" C=O[%02X]", e8255_get_out (ppi, 2)); 230 break; 231 232 case 0x0f: 233 pce_printf (" CH=O[%X] CL=I[%X]", 234 (e8255_get_out (ppi, 2) >> 4) & 0x0f, 235 e8255_get_inp (ppi, 2) & 0x0f 236 ); 237 break; 238 239 case 0xf0: 240 pce_printf (" CH=I[%X] CL=O[%X]", 241 (e8255_get_inp (ppi, 2) >> 4) & 0x0f, 242 e8255_get_out (ppi, 2) & 0x0f 243 ); 244 break; 245 } 246 247 pce_puts ("\n"); 248} 249 250static 251void prt_state_dma (e8237_t *dma) 252{ 253 unsigned i; 254 255 pce_prt_sep ("8237-DMAC"); 256 257 pce_printf ("CMD=%02X PRI=%02X CHK=%d\n", 258 e8237_get_command (dma), 259 e8237_get_priority (dma), 260 dma->check != 0 261 ); 262 263 for (i = 0; i < 4; i++) { 264 unsigned short state; 265 266 state = e8237_get_state (dma, i); 267 268 pce_printf ( 269 "CHN %u: MODE=%02X ADDR=%04X[%04X] CNT=%04X[%04X] DREQ=%d SREQ=%d MASK=%d\n", 270 i, 271 e8237_get_mode (dma, i) & 0xfcU, 272 e8237_get_addr (dma, i), 273 e8237_get_addr_base (dma, i), 274 e8237_get_cnt (dma, i), 275 e8237_get_cnt_base (dma, i), 276 (state & E8237_STATE_DREQ) != 0, 277 (state & E8237_STATE_SREQ) != 0, 278 (state & E8237_STATE_MASK) != 0 279 ); 280 } 281} 282 283static 284void prt_state_pic (e8259_t *pic) 285{ 286 unsigned i; 287 288 pce_prt_sep ("8259A-PIC"); 289 290 pce_puts ("INP="); 291 prt_uint8_bin (pic->irq_inp); 292 pce_puts ("\n"); 293 294 pce_puts ("IRR="); 295 prt_uint8_bin (e8259_get_irr (pic)); 296 pce_printf (" PRIO=%u\n", pic->priority); 297 298 pce_puts ("IMR="); 299 prt_uint8_bin (e8259_get_imr (pic)); 300 pce_printf (" INTR=%d\n", pic->intr_val != 0); 301 302 pce_puts ("ISR="); 303 prt_uint8_bin (e8259_get_isr (pic)); 304 pce_puts ("\n"); 305 306 pce_printf ("ICW=[%02X %02X %02X %02X] OCW=[%02X %02X %02X]\n", 307 e8259_get_icw (pic, 0), e8259_get_icw (pic, 1), e8259_get_icw (pic, 2), 308 e8259_get_icw (pic, 3), 309 e8259_get_ocw (pic, 0), e8259_get_ocw (pic, 1), e8259_get_ocw (pic, 2) 310 ); 311 312 pce_printf ("N0=%04lX", pic->irq_cnt[0]); 313 for (i = 1; i < 8; i++) { 314 pce_printf (" N%u=%04lX", i, pic->irq_cnt[i]); 315 } 316 317 pce_puts ("\n"); 318} 319 320static 321void prt_state_uart (e8250_t *uart, unsigned base) 322{ 323 char p; 324 unsigned char lsr, msr; 325 326 lsr = e8250_get_lsr (uart); 327 msr = e8250_get_msr (uart); 328 329 switch (e8250_get_parity (uart)) { 330 case E8250_PARITY_N: 331 p = 'N'; 332 break; 333 334 case E8250_PARITY_E: 335 p = 'E'; 336 break; 337 338 case E8250_PARITY_O: 339 p = 'O'; 340 break; 341 342 case E8250_PARITY_M: 343 p = 'M'; 344 break; 345 346 case E8250_PARITY_S: 347 p = 'S'; 348 break; 349 350 default: 351 p = '?'; 352 break; 353 } 354 355 pce_prt_sep ("8250-UART"); 356 357 pce_printf ( 358 "IO=%04X %lu %u%c%u DTR=%d RTS=%d DSR=%d CTS=%d DCD=%d RI=%d\n" 359 "TxD=%02X%c RxD=%02X%c SCR=%02X DIV=%04X\n" 360 "IER=%02X IIR=%02X LCR=%02X LSR=%02X MCR=%02X MSR=%02X\n", 361 base, 362 e8250_get_bps (uart), e8250_get_databits (uart), p, 363 e8250_get_stopbits (uart), 364 e8250_get_dtr (uart), e8250_get_rts (uart), 365 (msr & E8250_MSR_DSR) != 0, 366 (msr & E8250_MSR_CTS) != 0, 367 (msr & E8250_MSR_DCD) != 0, 368 (msr & E8250_MSR_RI) != 0, 369 uart->txd, (lsr & E8250_LSR_TBE) ? ' ' : '*', 370 uart->rxd, (lsr & E8250_LSR_RRD) ? '*' : ' ', 371 uart->scratch, uart->divisor, 372 uart->ier, uart->iir, uart->lcr, lsr, uart->mcr, msr 373 ); 374} 375 376void prt_state_cpu (e8086_t *c) 377{ 378 pce_prt_sep ("8086"); 379 380 pce_printf ( 381 "AX=%04X BX=%04X CX=%04X DX=%04X " 382 "SP=%04X BP=%04X SI=%04X DI=%04X INT=%02X%c\n", 383 e86_get_ax (c), e86_get_bx (c), e86_get_cx (c), e86_get_dx (c), 384 e86_get_sp (c), e86_get_bp (c), e86_get_si (c), e86_get_di (c), 385 par_pc->current_int & 0xff, 386 (par_pc->current_int & 0x100) ? '*' : ' ' 387 ); 388 389 pce_printf ("DS=%04X ES=%04X SS=%04X CS=%04X IP=%04X F =%04X", 390 e86_get_ds (c), e86_get_es (c), e86_get_ss (c), e86_get_cs (c), 391 e86_get_ip (c), e86_get_flags (c) 392 ); 393 394 pce_printf (" [%c%c%c%c%c%c%c%c%c]\n", 395 e86_get_df (c) ? 'D' : '-', 396 e86_get_if (c) ? 'I' : '-', 397 e86_get_tf (c) ? 'T' : '-', 398 e86_get_of (c) ? 'O' : '-', 399 e86_get_sf (c) ? 'S' : '-', 400 e86_get_zf (c) ? 'Z' : '-', 401 e86_get_af (c) ? 'A' : '-', 402 e86_get_pf (c) ? 'P' : '-', 403 e86_get_cf (c) ? 'C' : '-' 404 ); 405 406 if (e86_get_halt (c)) { 407 pce_printf ("HALT=1\n"); 408 } 409} 410 411void pc_print_trace (e8086_t *c) 412{ 413 e86_disasm_t op; 414 char str[256]; 415 416 e86_disasm_cur (c, &op); 417 418 switch (op.arg_n) { 419 case 0: 420 strcpy (str, op.op); 421 break; 422 423 case 1: 424 sprintf (str, "%-5s %s", op.op, op.arg1); 425 break; 426 427 case 2: 428 sprintf (str, "%-5s %s,%s", op.op, op.arg1, op.arg2); 429 break; 430 431 default: 432 strcpy (str, "****"); 433 break; 434 } 435 436 pce_printf ( 437 "AX=%04X BX=%04X CX=%04X DX=%04X " 438 "SP=%04X BP=%04X SI=%04X DI=%04X " 439 "DS=%04X ES=%04X SS=%04X F=%04X %04X:%04X %s\n", 440 e86_get_ax (c), e86_get_bx (c), e86_get_cx (c), e86_get_dx (c), 441 e86_get_sp (c), e86_get_bp (c), e86_get_si (c), e86_get_di (c), 442 e86_get_ds (c), e86_get_es (c), e86_get_ss (c), e86_get_flags (c), 443 e86_get_cs (c), e86_get_ip (c), str 444 ); 445} 446 447static 448void prt_state_mem (ibmpc_t *pc) 449{ 450 pce_prt_sep ("PC MEM"); 451 mem_prt_state (pc->mem, stdout); 452} 453 454static 455void prt_state_ports (ibmpc_t *pc) 456{ 457 pce_prt_sep ("PC PORTS"); 458 mem_prt_state (pc->prt, stdout); 459} 460 461static 462void prt_state_pc (ibmpc_t *pc) 463{ 464 prt_state_video (pc->video); 465 prt_state_ppi (&pc->ppi); 466 prt_state_pit (&pc->pit); 467 prt_state_pic (&pc->pic); 468 prt_state_dma (&pc->dma); 469 prt_state_cpu (pc->cpu); 470} 471 472static 473void prt_state (ibmpc_t *pc) 474{ 475 e86_disasm_t op; 476 char str[256]; 477 478 e86_disasm_cur (pc->cpu, &op); 479 disasm_str (str, &op); 480 481 prt_state_cpu (pc->cpu); 482 483 pce_printf ("%04X:%04X %s\n", 484 (unsigned) e86_get_cs (pc->cpu), 485 (unsigned) e86_get_ip (pc->cpu), 486 str 487 ); 488} 489 490static 491int pc_check_break (ibmpc_t *pc) 492{ 493 unsigned short seg, ofs; 494 495 seg = e86_get_cs (pc->cpu); 496 ofs = e86_get_ip (pc->cpu); 497 498 if (bps_check (&pc->bps, seg, ofs, stdout)) { 499 return (1); 500 } 501 502 if (pc->brk) { 503 return (1); 504 } 505 506 return (0); 507} 508 509static 510void pc_exec (ibmpc_t *pc) 511{ 512 unsigned old; 513 514 pc->current_int &= 0xff; 515 516 old = e86_get_opcnt (pc->cpu); 517 518 while (e86_get_opcnt (pc->cpu) == old) { 519 pc_clock (pc, 1); 520 521 if (pc->brk) { 522 break; 523 } 524 } 525} 526 527void pc_run (ibmpc_t *pc) 528{ 529 pce_start (&pc->brk); 530 531 pc_clock_discontinuity (pc); 532 533 if (pc->pause == 0) { 534 while (pc->brk == 0) { 535 pc_clock (pc, 4 * pc->speed_current); 536 } 537 } 538 else { 539 while (pc->brk == 0) { 540 pce_usleep (100000); 541 trm_check (pc->trm); 542 } 543 } 544 545 pc->current_int &= 0xff; 546 547 pce_stop(); 548} 549 550#if 0 551static 552void pce_op_stat (void *ext, unsigned char op1, unsigned char op2) 553{ 554 ibmpc_t *pc; 555 556 pc = (ibmpc_t *) ext; 557 558} 559#endif 560 561/* 562 * Force floppy disk drive types to 40 tracks in the BIOS data area of 563 * newer PC/XT BIOSes. 564 */ 565static 566void pc_bios_set_40_track (ibmpc_t *pc, unsigned mask) 567{ 568 unsigned i, v; 569 570 for (i = 0; i < 2; i++) { 571 if (mask & (1 << i)) { 572 v = e86_get_mem8 (pc->cpu, 0x40, 0x90 + i); 573 e86_set_mem8 (pc->cpu, 0x40, 0x90 + i, v & 0xfe); 574 } 575 } 576} 577 578static 579void pce_op_int (void *ext, unsigned char n) 580{ 581 unsigned seg; 582 ibmpc_t *pc; 583 584 pc = ext; 585 586 pc->current_int = n | 0x100; 587 588 if (pc_intlog_check (pc, n)) { 589 pce_printf ("%04X:%04X: int %02X" 590 " [AX=%04X BX=%04X CX=%04X DX=%04X DS=%04X ES=%04X]\n", 591 e86_get_cs (pc->cpu), e86_get_cur_ip (pc->cpu), 592 n, 593 e86_get_ax (pc->cpu), e86_get_bx (pc->cpu), 594 e86_get_cx (pc->cpu), e86_get_dx (pc->cpu), 595 e86_get_ds (pc->cpu), e86_get_es (pc->cpu) 596 ); 597 } 598 599 if (n == 0x13) { 600 if (pc->dsk0 == NULL) { 601 return; 602 } 603 604 if ((e86_get_ah (pc->cpu) != 0x02) || (e86_get_dl (pc->cpu) == 0)) { 605 return; 606 } 607 608 dsks_add_disk (pc->dsk, pc->dsk0); 609 610 pc->dsk0 = NULL; 611 } 612 else if (n == 0x19) { 613 if ((pc->bootdrive != 0) && (pc->dsk0 == NULL)) { 614 /* If we are not booting from drive 0 then 615 * temporarily remove it. */ 616 pc->dsk0 = dsks_get_disk (pc->dsk, 0); 617 dsks_rmv_disk (pc->dsk, pc->dsk0); 618 } 619 620 if (pc->fdd40) { 621 pc_bios_set_40_track (pc, pc->fdd40); 622 } 623 624 if (pc->patch_bios_int19 == 0) { 625 return; 626 } 627 628 seg = pc_get_pcex_seg (pc); 629 630 if (seg == 0) { 631 return; 632 } 633 634 pc_log_deb ("patching int 19 (0x%04x)\n", seg); 635 636 e86_set_mem16 (pc->cpu, 0, 4 * 0x19 + 0, 0x0010); 637 e86_set_mem16 (pc->cpu, 0, 4 * 0x19 + 2, seg); 638 } 639} 640 641static 642void pce_op_undef (void *ext, unsigned char op1, unsigned char op2) 643{ 644 ibmpc_t *pc; 645 646 pc = (ibmpc_t *) ext; 647 648 pce_log (MSG_DEB, "%04X:%04X: undefined operation [%02X %02x]\n", 649 e86_get_cs (pc->cpu), e86_get_ip (pc->cpu), op1, op2 650 ); 651 652 if (pc->brk == 0) { 653 pce_usleep (100000UL); 654 } 655 656 trm_check (pc->trm); 657} 658 659 660static 661void pc_cmd_boot (cmd_t *cmd, ibmpc_t *pc) 662{ 663 unsigned short val; 664 665 if (cmd_match_eol (cmd)) { 666 pce_printf ("boot drive is 0x%02x\n", pc_get_bootdrive (pc)); 667 return; 668 } 669 670 if (!cmd_match_uint16 (cmd, &val)) { 671 cmd_error (cmd, "expecting boot drive"); 672 return; 673 } 674 675 if (!cmd_match_end (cmd)) { 676 return; 677 } 678 679 pc_set_bootdrive (pc, val); 680} 681 682static 683void pc_cmd_c (cmd_t *cmd, ibmpc_t *pc) 684{ 685 unsigned long cnt; 686 687 cnt = 1; 688 689 cmd_match_uint32 (cmd, &cnt); 690 691 if (!cmd_match_end (cmd)) { 692 return; 693 } 694 695 pc_clock_discontinuity (pc); 696 697 while (cnt > 0) { 698 pc_clock (pc, 1); 699 cnt -= 1; 700 } 701 702 prt_state (pc); 703} 704 705static 706void pc_cmd_g_b (cmd_t *cmd, ibmpc_t *pc) 707{ 708 unsigned long seg, ofs; 709 breakpoint_t *bp; 710 711 while (cmd_match_uint32 (cmd, &seg)) { 712 if (cmd_match (cmd, ":")) { 713 if (!cmd_match_uint32 (cmd, &ofs)) { 714 cmd_error (cmd, "expecting offset"); 715 return; 716 } 717 718 bp = bp_segofs_new (seg, ofs); 719 } 720 else { 721 bp = bp_addr_new (seg); 722 } 723 724 bps_bp_add (&pc->bps, bp); 725 } 726 727 if (!cmd_match_end (cmd)) { 728 return; 729 } 730 731 pce_start (&pc->brk); 732 733 pc_clock_discontinuity (pc); 734 735 while (1) { 736 if (pc->trace) { 737 pc_print_trace (pc->cpu); 738 } 739 740 pc_exec (pc); 741 742 if (pc_check_break (pc)) { 743 break; 744 } 745 } 746 747 pce_stop(); 748} 749 750static 751void pc_cmd_g_far (cmd_t *cmd, ibmpc_t *pc) 752{ 753 unsigned short seg; 754 755 if (!cmd_match_end (cmd)) { 756 return; 757 } 758 759 seg = e86_get_cs (pc->cpu); 760 761 pce_start (&pc->brk); 762 763 pc_clock_discontinuity (pc); 764 765 while (1) { 766 if (pc->trace) { 767 pc_print_trace (pc->cpu); 768 } 769 770 pc_exec (pc); 771 772 if (e86_get_cs (pc->cpu) != seg) { 773 prt_state (pc); 774 break; 775 } 776 777 if (pc_check_break (pc)) { 778 break; 779 } 780 } 781 782 pce_stop(); 783} 784 785static 786void pc_cmd_g (cmd_t *cmd, ibmpc_t *pc) 787{ 788 if (cmd_match (cmd, "b")) { 789 pc_cmd_g_b (cmd, pc); 790 } 791 else if (cmd_match (cmd, "far")) { 792 pc_cmd_g_far (cmd, pc); 793 } 794 else { 795 if (!cmd_match_end (cmd)) { 796 return; 797 } 798 799 pc_run (pc); 800 } 801} 802 803static 804void pc_cmd_hm (cmd_t *cmd) 805{ 806 pce_puts ( 807 "emu.config.save <filename>\n" 808 "emu.exit\n" 809 "emu.stop\n" 810 "emu.pause \"0\" | \"1\"\n" 811 "emu.pause.toggle\n" 812 "emu.reset\n" 813 "\n" 814 "emu.cas.commit\n" 815 "emu.cas.create <filename>\n" 816 "emu.cas.play\n" 817 "emu.cas.load [<pos>]\n" 818 "emu.cas.read <filename>\n" 819 "emu.cas.record\n" 820 "emu.cas.space\n" 821 "emu.cas.state\n" 822 "emu.cas.stop\n" 823 "emu.cas.truncate\n" 824 "emu.cas.write <filename>\n" 825 "\n" 826 "emu.cpu.model \"8086\" | \"8088\" | \"80186\" | \"80188\"\n" 827 "emu.cpu.speed <factor>\n" 828 "emu.cpu.speed.step <adjustment>\n" 829 "\n" 830 "emu.disk.boot <bootdrive>\n" 831 "emu.fdc.accurate \"0\" | \"1\"\n" 832 "emu.fdc.verbose <level>\n" 833 "\n" 834 "emu.parport.driver <driver>\n" 835 "emu.parport.file <filename>\n" 836 "\n" 837 "emu.serport.driver <driver>\n" 838 "emu.serport.file <filename>\n" 839 "\n" 840 "emu.term.fullscreen \"0\" | \"1\"\n" 841 "emu.term.fullscreen.toggle\n" 842 "emu.term.grab\n" 843 "emu.term.release\n" 844 "emu.term.screenshot [<filename>]\n" 845 "emu.term.title <title>\n" 846 "\n" 847 "emu.video.blink <blink-rate>\n" 848 "emu.video.redraw [\"now\"]\n" 849 "\n" 850 ); 851 852 msg_dsk_print_help(); 853} 854 855static 856void pc_cmd_i (cmd_t *cmd, ibmpc_t *pc) 857{ 858 int word; 859 unsigned short port; 860 861 if (cmd_match (cmd, "w")) { 862 word = 1; 863 } 864 else if (cmd_match (cmd, "b")) { 865 word = 0; 866 } 867 else { 868 word = 0; 869 } 870 871 if (!cmd_match_uint16 (cmd, &port)) { 872 cmd_error (cmd, "need a port address"); 873 return; 874 } 875 876 if (!cmd_match_end (cmd)) { 877 return; 878 } 879 880 if (word) { 881 pce_printf ("%04X: %04X\n", port, e86_get_prt16 (pc->cpu, port)); 882 } 883 else { 884 pce_printf ("%04X: %02X\n", port, e86_get_prt8 (pc->cpu, port)); 885 } 886} 887 888static 889void pc_cmd_key (cmd_t *cmd, ibmpc_t *pc) 890{ 891 unsigned i; 892 unsigned mask; 893 pce_key_t key; 894 char str[256]; 895 896 while (cmd_match_str (cmd, str, 256)) { 897 i = 0; 898 899 if (str[0] == '+') { 900 mask = 1; 901 i += 1; 902 } 903 else if (str[0] == '-') { 904 mask = 2; 905 i += 1; 906 } 907 else { 908 mask = 3; 909 } 910 911 key = pce_key_from_string (str + i); 912 913 if (key == PCE_KEY_NONE) { 914 pce_printf ("unknown key: %s\n", str); 915 } 916 else { 917 if (mask & 1) { 918 pc_kbd_set_key (&pc->kbd, PCE_KEY_EVENT_DOWN, key); 919 } 920 921 if (mask & 2) { 922 pc_kbd_set_key (&pc->kbd, PCE_KEY_EVENT_UP, key); 923 } 924 } 925 } 926 927 if (!cmd_match_end (cmd)) { 928 return; 929 } 930} 931 932static 933void pc_cmd_log_int_l (cmd_t *cmd, ibmpc_t *pc) 934{ 935 unsigned i; 936 const char *str; 937 938 for (i = 0; i < 256; i++) { 939 str = pc_intlog_get (pc, i); 940 941 if (str != NULL) { 942 pce_printf ("%02X: %s\n", i, str); 943 } 944 } 945} 946 947static 948void pc_cmd_log_int (cmd_t *cmd, ibmpc_t *pc) 949{ 950 unsigned short n; 951 char buf[256]; 952 953 if (cmd_match_eol (cmd)) { 954 pc_cmd_log_int_l (cmd, pc); 955 return; 956 } 957 958 if (cmd_match (cmd, "l")) { 959 pc_cmd_log_int_l (cmd, pc); 960 return; 961 } 962 963 if (!cmd_match_uint16 (cmd, &n)) { 964 cmd_error (cmd, "need an interrupt number"); 965 return; 966 } 967 968 if (cmd_match_eol (cmd)) { 969 pc_intlog_set (pc, n, NULL); 970 pce_printf ("%02X: <deleted>\n", n); 971 return; 972 } 973 974 if (!cmd_match_str (cmd, buf, 256)) { 975 cmd_error (cmd, "need an expression"); 976 return; 977 } 978 979 pce_printf ("%02X: %s\n", n, buf); 980 981 pc_intlog_set (pc, n, buf); 982} 983 984static 985void pc_cmd_log (cmd_t *cmd, ibmpc_t *pc) 986{ 987 if (cmd_match (cmd, "int")) { 988 pc_cmd_log_int (cmd, pc); 989 } 990 else { 991 cmd_error (cmd, "log what?"); 992 } 993} 994 995static 996void pc_cmd_o (cmd_t *cmd, ibmpc_t *pc) 997{ 998 int word; 999 unsigned short port, val; 1000 1001 if (cmd_match (cmd, "w")) { 1002 word = 1; 1003 } 1004 else if (cmd_match (cmd, "b")) { 1005 word = 0; 1006 } 1007 else { 1008 word = 0; 1009 } 1010 1011 if (!cmd_match_uint16 (cmd, &port)) { 1012 cmd_error (cmd, "need a port address"); 1013 return; 1014 } 1015 1016 if (!cmd_match_uint16 (cmd, &val)) { 1017 cmd_error (cmd, "need a value"); 1018 return; 1019 } 1020 1021 if (!cmd_match_end (cmd)) { 1022 return; 1023 } 1024 1025 if (word) { 1026 e86_set_prt16 (pc->cpu, port, val); 1027 } 1028 else { 1029 e86_set_prt8 (pc->cpu, port, val); 1030 } 1031} 1032 1033static 1034void pc_cmd_pqc (cmd_t *cmd, ibmpc_t *pc) 1035{ 1036 if (!cmd_match_end (cmd)) { 1037 return; 1038 } 1039 1040 e86_pq_init (pc->cpu); 1041} 1042 1043static 1044void pc_cmd_pqs (cmd_t *cmd, ibmpc_t *pc) 1045{ 1046 unsigned i; 1047 1048 if (!cmd_match_end (cmd)) { 1049 return; 1050 } 1051 1052 pce_puts ("PQ:"); 1053 1054 for (i = 0; i < pc->cpu->pq_cnt; i++) { 1055 pce_printf (" %02X", pc->cpu->pq[i]); 1056 } 1057 1058 pce_puts ("\n"); 1059} 1060 1061static 1062void pc_cmd_pqf (cmd_t *cmd, ibmpc_t *pc) 1063{ 1064 if (!cmd_match_end (cmd)) { 1065 return; 1066 } 1067 1068 e86_pq_fill (pc->cpu); 1069} 1070 1071static 1072void pc_cmd_pq (cmd_t *cmd, ibmpc_t *pc) 1073{ 1074 if (cmd_match (cmd, "c")) { 1075 pc_cmd_pqc (cmd, pc); 1076 } 1077 else if (cmd_match (cmd, "f")) { 1078 pc_cmd_pqf (cmd, pc); 1079 } 1080 else if (cmd_match (cmd, "s")) { 1081 pc_cmd_pqs (cmd, pc); 1082 } 1083 else if (cmd_match_eol (cmd)) { 1084 pc_cmd_pqs (cmd, pc); 1085 } 1086 else { 1087 cmd_error (cmd, "pq: unknown command (%s)\n"); 1088 } 1089} 1090 1091static 1092void pc_cmd_p (cmd_t *cmd, ibmpc_t *pc) 1093{ 1094 unsigned cnt, opcnt1, opcnt2; 1095 unsigned short seg, ofs, seg2, ofs2; 1096 unsigned long i, n; 1097 int brk, skip; 1098 e86_disasm_t op; 1099 1100 n = 1; 1101 1102 cmd_match_uint32 (cmd, &n); 1103 1104 if (!cmd_match_end (cmd)) { 1105 return; 1106 } 1107 1108 brk = 0; 1109 1110 pce_start (&pc->brk); 1111 1112 pc->current_int &= 0xff; 1113 1114 pc_clock_discontinuity (pc); 1115 1116 for (i = 0; i < n; i++) { 1117 e86_disasm_cur (pc->cpu, &op); 1118 1119 seg = e86_get_cs (pc->cpu); 1120 ofs = e86_get_ip (pc->cpu); 1121 1122 cnt = pc->cpu->int_cnt; 1123 1124 if (pc->trace) { 1125 pc_print_trace (pc->cpu); 1126 } 1127 1128 while ((e86_get_cs (pc->cpu) == seg) && (e86_get_ip (pc->cpu) == ofs)) { 1129 pc_clock (pc, 1); 1130 1131 if (pc_check_break (pc)) { 1132 brk = 1; 1133 break; 1134 } 1135 } 1136 1137 if (brk) { 1138 break; 1139 } 1140 1141 skip = 0; 1142 1143 if (op.flags & (E86_DFLAGS_CALL | E86_DFLAGS_LOOP)) { 1144 seg2 = seg; 1145 ofs2 = ofs + op.dat_n; 1146 skip = 1; 1147 } 1148 else if (pc->cpu->int_cnt != cnt) { 1149 seg2 = pc->cpu->int_cs; 1150 ofs2 = pc->cpu->int_ip; 1151 skip = 1; 1152 } 1153 1154 if (skip) { 1155 opcnt1 = -e86_get_opcnt (pc->cpu); 1156 1157 while ((e86_get_cs (pc->cpu) != seg2) || (e86_get_ip (pc->cpu) != ofs2)) { 1158 if (pc->trace) { 1159 opcnt2 = e86_get_opcnt (pc->cpu); 1160 1161 if (opcnt1 != opcnt2) { 1162 opcnt1 = opcnt2; 1163 pc_print_trace (pc->cpu); 1164 } 1165 } 1166 1167 pc_clock (pc, 1); 1168 1169 if (pc_check_break (pc)) { 1170 brk = 1; 1171 break; 1172 } 1173 } 1174 } 1175 1176 if (brk) { 1177 break; 1178 } 1179 1180 if (pc_check_break (pc)) { 1181 break; 1182 } 1183 } 1184 1185 pce_stop(); 1186 1187 prt_state (pc); 1188} 1189 1190static 1191void pc_cmd_r (cmd_t *cmd, ibmpc_t *pc) 1192{ 1193 unsigned long val; 1194 char sym[256]; 1195 1196 if (cmd_match_eol (cmd)) { 1197 prt_state_cpu (pc->cpu); 1198 return; 1199 } 1200 1201 if (!cmd_match_ident (cmd, sym, 256)) { 1202 pce_printf ("missing register\n"); 1203 return; 1204 } 1205 1206 if (e86_get_reg (pc->cpu, sym, &val)) { 1207 pce_printf ("bad register (%s)\n", sym); 1208 return; 1209 } 1210 1211 if (cmd_match_eol (cmd)) { 1212 pce_printf ("%04lX\n", val); 1213 return; 1214 } 1215 1216 if (!cmd_match_uint32 (cmd, &val)) { 1217 pce_printf ("missing value\n"); 1218 return; 1219 } 1220 1221 if (!cmd_match_end (cmd)) { 1222 return; 1223 } 1224 1225 e86_set_reg (pc->cpu, sym, val); 1226 1227 prt_state (pc); 1228} 1229 1230static 1231void pc_cmd_s (cmd_t *cmd, ibmpc_t *pc) 1232{ 1233 if (cmd_match_eol (cmd)) { 1234 prt_state (pc); 1235 return; 1236 } 1237 1238 while (!cmd_match_eol (cmd)) { 1239 if (cmd_match (cmd, "pc")) { 1240 prt_state_pc (pc); 1241 } 1242 else if (cmd_match (cmd, "cpu")) { 1243 prt_state_cpu (pc->cpu); 1244 } 1245 else if (cmd_match (cmd, "dma")) { 1246 prt_state_dma (&pc->dma); 1247 } 1248 else if (cmd_match (cmd, "disks")) { 1249 dsks_print_info (pc->dsk); 1250 } 1251 else if (cmd_match (cmd, "ems")) { 1252 prt_state_ems (pc->ems); 1253 } 1254 else if (cmd_match (cmd, "mem")) { 1255 prt_state_mem (pc); 1256 } 1257 else if (cmd_match (cmd, "pic")) { 1258 prt_state_pic (&pc->pic); 1259 } 1260 else if (cmd_match (cmd, "pit")) { 1261 prt_state_pit (&pc->pit); 1262 } 1263 else if (cmd_match (cmd, "ppi")) { 1264 prt_state_ppi (&pc->ppi); 1265 } 1266 else if (cmd_match (cmd, "ports")) { 1267 prt_state_ports (pc); 1268 } 1269 else if (cmd_match (cmd, "uart")) { 1270 unsigned short i; 1271 if (!cmd_match_uint16 (cmd, &i)) { 1272 i = 0; 1273 } 1274 if ((i < 4) && (pc->serport[i] != NULL)) { 1275 prt_state_uart ( 1276 &pc->serport[i]->uart, 1277 pc->serport[i]->io 1278 ); 1279 } 1280 } 1281 else if (cmd_match (cmd, "video")) { 1282 prt_state_video (pc->video); 1283 } 1284 else if (cmd_match (cmd, "xms")) { 1285 prt_state_xms (pc->xms); 1286 } 1287 else { 1288 cmd_error (cmd, "unknown component (%s)\n"); 1289 return; 1290 } 1291 } 1292} 1293 1294static 1295void pc_cmd_trace (cmd_t *cmd, ibmpc_t *pc) 1296{ 1297 unsigned short v; 1298 1299 if (cmd_match_eol (cmd)) { 1300 pce_printf ("trace is %s\n", pc->trace ? "on" : "off"); 1301 return; 1302 } 1303 1304 if (cmd_match (cmd, "on")) { 1305 pc->trace = 1; 1306 } 1307 else if (cmd_match (cmd, "off")) { 1308 pc->trace = 0; 1309 } 1310 else if (cmd_match_uint16 (cmd, &v)) { 1311 pc->trace = (v != 0); 1312 } 1313 else { 1314 cmd_error (cmd, "on or off expected\n"); 1315 } 1316} 1317 1318static 1319void pc_cmd_t (cmd_t *cmd, ibmpc_t *pc) 1320{ 1321 unsigned long i, n; 1322 1323 n = 1; 1324 1325 cmd_match_uint32 (cmd, &n); 1326 1327 if (!cmd_match_end (cmd)) { 1328 return; 1329 } 1330 1331 pce_start (&pc->brk); 1332 1333 pc_clock_discontinuity (pc); 1334 1335 for (i = 0; i < n; i++) { 1336 if (pc->trace) { 1337 pc_print_trace (pc->cpu); 1338 } 1339 1340 pc_exec (pc); 1341 1342 if (pc_check_break (pc)) { 1343 break; 1344 } 1345 } 1346 1347 pce_stop(); 1348 1349 prt_state (pc); 1350} 1351 1352static 1353void pc_cmd_u (cmd_t *cmd, ibmpc_t *pc) 1354{ 1355 unsigned short seg, ofs, cnt, mode; 1356 static unsigned int first = 1; 1357 static unsigned short sseg = 0; 1358 static unsigned short sofs = 0; 1359 e86_disasm_t op; 1360 char str[256]; 1361 1362 if (first) { 1363 first = 0; 1364 sseg = e86_get_cs (pc->cpu); 1365 sofs = e86_get_ip (pc->cpu); 1366 } 1367 1368 seg = sseg; 1369 ofs = sofs; 1370 cnt = 16; 1371 mode = 0; 1372 1373 if (cmd_match_uint16_16 (cmd, &seg, &ofs)) { 1374 cmd_match_uint16 (cmd, &cnt); 1375 } 1376 1377 cmd_match_uint16 (cmd, &mode); 1378 1379 if (!cmd_match_end (cmd)) { 1380 return; 1381 } 1382 1383 while (cnt > 0) { 1384 e86_disasm_mem (pc->cpu, &op, seg, ofs); 1385 disasm_str (str, &op); 1386 1387 pce_printf ("%04X:%04X %s\n", seg, ofs, str); 1388 1389 ofs = (ofs + op.dat_n) & 0xffff; 1390 1391 if (mode == 0) { 1392 cnt -= 1; 1393 } 1394 else { 1395 cnt = (cnt < op.dat_n) ? 0 : (cnt - op.dat_n); 1396 } 1397 } 1398 1399 sseg = seg; 1400 sofs = ofs; 1401} 1402 1403int pc_cmd (ibmpc_t *pc, cmd_t *cmd) 1404{ 1405 if (pc->trm != NULL) { 1406 trm_check (pc->trm); 1407 } 1408 1409 if (cmd_match (cmd, "boot")) { 1410 pc_cmd_boot (cmd, pc); 1411 } 1412 else if (cmd_match (cmd, "b")) { 1413 cmd_do_b (cmd, &pc->bps); 1414 } 1415 else if (cmd_match (cmd, "c")) { 1416 pc_cmd_c (cmd, pc); 1417 } 1418 else if (cmd_match (cmd, "g")) { 1419 pc_cmd_g (cmd, pc); 1420 } 1421 else if (cmd_match (cmd, "hm")) { 1422 pc_cmd_hm (cmd); 1423 } 1424 else if (cmd_match (cmd, "i")) { 1425 pc_cmd_i (cmd, pc); 1426 } 1427 else if (cmd_match (cmd, "key")) { 1428 pc_cmd_key (cmd, pc); 1429 } 1430 else if (cmd_match (cmd, "log")) { 1431 pc_cmd_log (cmd, pc); 1432 } 1433 else if (cmd_match (cmd, "o")) { 1434 pc_cmd_o (cmd, pc); 1435 } 1436 else if (cmd_match (cmd, "pq")) { 1437 pc_cmd_pq (cmd, pc); 1438 } 1439 else if (cmd_match (cmd, "p")) { 1440 pc_cmd_p (cmd, pc); 1441 } 1442 else if (cmd_match (cmd, "r")) { 1443 pc_cmd_r (cmd, pc); 1444 } 1445 else if (cmd_match (cmd, "s")) { 1446 pc_cmd_s (cmd, pc); 1447 } 1448 else if (cmd_match (cmd, "trace")) { 1449 pc_cmd_trace (cmd, pc); 1450 } 1451 else if (cmd_match (cmd, "t")) { 1452 pc_cmd_t (cmd, pc); 1453 } 1454 else if (cmd_match (cmd, "u")) { 1455 pc_cmd_u (cmd, pc); 1456 } 1457 else { 1458 return (1); 1459 } 1460 1461 return (0); 1462} 1463 1464void pc_cmd_init (ibmpc_t *pc, monitor_t *mon) 1465{ 1466 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0])); 1467 mon_cmd_add_bp (mon); 1468 1469 pc->cpu->op_int = &pce_op_int; 1470 pc->cpu->op_undef = &pce_op_undef; 1471#if 0 1472 pc->cpu->op_stat = pce_op_stat; 1473#endif 1474 1475}