fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/rc759/cmd.c *
7 * Created: 2012-06-29 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-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 "rc759.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 { "c", "[cnt]", "clock the simulation [1]" },
40 { "gb", "[addr...]", "run with breakpoints" },
41 { "g", "far", "run until CS changes" },
42 { "g", "", "run" },
43 { "hm", "", "print help on messages" },
44 { "i", "[b|w] port", "input a byte or word from a port" },
45 { "key", "[[+|-]key...]", "simulate pressing or releasing keys" },
46 { "log", "int l", "list interrupt log expressions" },
47 { "log", "int n [expr]", "set interrupt n log expression to expr" },
48 { "nv", "get addr [cnt]", "read bytes from nvram" },
49 { "nv", "set addr [val...]", "write bytes to nvram" },
50 { "nv", "sum", "fix the nvram checksum" },
51 { "o", "[b|w] port val", "output a byte or word to a port" },
52 { "pq", "[c|f|s]", "prefetch queue clear/fill/status" },
53 { "p", "[cnt]", "execute cnt instructions, without trace in calls [1]" },
54 { "r", "[reg val]", "set a register" },
55 { "s", "[what]", "print status (cpu|disks|icu|mem||ppi|pic|rc759|tcu|time)" },
56 { "t", "[cnt]", "execute cnt instructions [1]" },
57 { "u", "[addr [cnt [mode]]]", "disassemble" }
58};
59
60
61static
62void disasm_str (char *dst, e86_disasm_t *op)
63{
64 unsigned i;
65 unsigned dst_i;
66
67 dst_i = 2;
68 sprintf (dst, "%02X", op->dat[0]);
69
70 for (i = 1; i < op->dat_n; i++) {
71 sprintf (dst + dst_i, " %02X", op->dat[i]);
72 dst_i += 3;
73 }
74
75 dst[dst_i++] = ' ';
76 while (dst_i < 20) {
77 dst[dst_i++] = ' ';
78 }
79
80 if ((op->flags & ~(E86_DFLAGS_CALL | E86_DFLAGS_LOOP)) != 0) {
81 unsigned flg;
82
83 flg = op->flags;
84
85 dst[dst_i++] = '[';
86
87 if (flg & E86_DFLAGS_186) {
88 dst_i += sprintf (dst + dst_i, "186");
89 flg &= ~E86_DFLAGS_186;
90 }
91
92 if (flg != 0) {
93 if (flg != op->flags) {
94 dst[dst_i++] = ' ';
95 }
96 dst_i += sprintf (dst + dst_i, " %04X", flg);
97 }
98 dst[dst_i++] = ']';
99 dst[dst_i++] = ' ';
100 }
101
102 strcpy (dst + dst_i, op->op);
103 while (dst[dst_i] != 0) {
104 dst_i += 1;
105 }
106
107 if (op->arg_n > 0) {
108 dst[dst_i++] = ' ';
109 while (dst_i < 26) {
110 dst[dst_i++] = ' ';
111 }
112 }
113
114 if (op->arg_n == 1) {
115 dst_i += sprintf (dst + dst_i, "%s", op->arg1);
116 }
117 else if (op->arg_n == 2) {
118 dst_i += sprintf (dst + dst_i, "%s, %s", op->arg1, op->arg2);
119 }
120
121 dst[dst_i] = 0;
122}
123
124static
125void prt_uint8_bin (unsigned char val)
126{
127 unsigned i;
128 unsigned char m;
129 char str[16];
130
131 m = 0x80;
132
133 for (i = 0; i < 8; i++) {
134 str[i] = (val & m) ? '1' : '0';
135 m = m >> 1;
136 }
137
138 str[8] = 0;
139
140 pce_puts (str);
141}
142
143static
144void print_state_icu (e80186_icu_t *icu)
145{
146 unsigned i;
147 unsigned char inp, irr, imr, isr;
148
149 const char *names[] = {
150 "TMR", NULL, "DMA0", "DMA1", "INT0", "INT1", "INT2", "INT3"
151 };
152
153 inp = icu->inp;
154 irr = e80186_icu_get_irr (icu);
155 imr = e80186_icu_get_imr (icu);
156 isr = e80186_icu_get_isr (icu);
157
158 pce_prt_sep ("80186-ICU");
159
160 pce_puts ("INP=");
161 prt_uint8_bin (inp);
162 pce_puts (" IRR=");
163 prt_uint8_bin (irr);
164 pce_puts (" IMR=");
165 prt_uint8_bin (imr);
166 pce_puts (" ISR=");
167 prt_uint8_bin (isr);
168 pce_puts ("\n");
169
170 pce_printf ("PMR=%04X PST=%04X INT=%d\n",
171 e80186_icu_get_pmr (icu),
172 e80186_icu_get_pollst (icu),
173 icu->intr_val
174 );
175
176 for (i = 0; i < 8; i++) {
177 pce_printf ("%4s[%u]: CTL=%04X CNT=%04lX I=%u R=%u M=%u S=%u\n",
178 (names[i] != NULL) ? names[i] : "-", i,
179 e80186_icu_get_icon (icu, i),
180 icu->int_cnt[i],
181 inp & 1, irr & 1, imr & 1, isr & 1
182 );
183
184 inp >>= 1;
185 irr >>= 1;
186 imr >>= 1;
187 isr >>= 1;
188 }
189}
190
191static
192void print_state_tcu (e80186_tcu_t *tcu)
193{
194 unsigned i;
195 unsigned short ctl;
196
197 pce_prt_sep ("80186-TCU");
198
199 for (i = 0; i < 3; i++) {
200 ctl = e80186_tcu_get_control (tcu, i);
201
202 pce_printf (
203 "%cC%d: CTL=%04X CNT=%04X MAXA=%04X MAXB=%04X\n",
204 (ctl & 0x8000) ? '*' : ' ',
205 i,
206 ctl,
207 e80186_tcu_get_count (tcu, i),
208 e80186_tcu_get_max_count_a (tcu, i),
209 e80186_tcu_get_max_count_b (tcu, i)
210 );
211 }
212}
213
214static
215void print_state_ppi (e8255_t *ppi)
216{
217 pce_prt_sep ("8255-PPI");
218
219 pce_printf (
220 "MOD=%02X MODA=%u MODB=%u",
221 ppi->mode, ppi->group_a_mode, ppi->group_b_mode
222 );
223
224 if (ppi->port[0].inp != 0) {
225 pce_printf (" A=I[%02X]", e8255_get_inp (ppi, 0));
226 }
227 else {
228 pce_printf (" A=O[%02X]", e8255_get_out (ppi, 0));
229 }
230
231 if (ppi->port[1].inp != 0) {
232 pce_printf (" B=I[%02X]", e8255_get_inp (ppi, 1));
233 }
234 else {
235 pce_printf (" B=O[%02X]", e8255_get_out (ppi, 1));
236 }
237
238 switch (ppi->port[2].inp) {
239 case 0xff:
240 pce_printf (" C=I[%02X]", e8255_get_inp (ppi, 2));
241 break;
242
243 case 0x00:
244 pce_printf (" C=O[%02X]", e8255_get_out (ppi, 2));
245 break;
246
247 case 0x0f:
248 pce_printf (" CH=O[%X] CL=I[%X]",
249 (e8255_get_out (ppi, 2) >> 4) & 0x0f,
250 e8255_get_inp (ppi, 2) & 0x0f
251 );
252 break;
253
254 case 0xf0:
255 pce_printf (" CH=I[%X] CL=O[%X]",
256 (e8255_get_inp (ppi, 2) >> 4) & 0x0f,
257 e8255_get_out (ppi, 2) & 0x0f
258 );
259 break;
260 }
261
262 pce_puts ("\n");
263}
264
265static
266void print_state_dma (e80186_dma_t *dma)
267{
268 unsigned i;
269
270 pce_prt_sep ("80186-DMA");
271
272 for (i = 0; i < 2; i++) {
273 pce_printf ("%u: CTL=%04X CNT=%04X SRC=%05lX DST=%05lX\n",
274 i,
275 e80186_dma_get_control (dma, i),
276 e80186_dma_get_count (dma, i),
277 e80186_dma_get_src (dma, i),
278 e80186_dma_get_dst (dma, i)
279 );
280 }
281}
282
283static
284void print_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 print_state_fdc (rc759_fdc_t *fdc)
322{
323 unsigned i;
324 wd179x_drive_t *drv;
325
326 pce_prt_sep ("179X-FDC");
327
328 pce_printf ("FCR=%02X RSV=%02X\n",
329 rc759_fdc_get_fcr (fdc), rc759_fdc_get_reserve (fdc)
330 );
331
332 pce_printf ("STATUS=%02X CMD=%02X\n",
333 fdc->wd179x.status, fdc->wd179x.cmd
334 );
335
336 for (i = 0; i < 2; i++) {
337 drv = &fdc->wd179x.drive[i];
338
339 pce_printf ("DRIVE %u: SEL=%d RDY=%d M=%d C=%02X H=%X POS=%lu CNT=%lu\n",
340 i,
341 fdc->wd179x.drv->d == i, drv->ready != 0, drv->motor != 0,
342 (unsigned) drv->c, (unsigned) drv->h,
343 (unsigned long) drv->trkbuf_idx, (unsigned long) drv->trkbuf_cnt
344 );
345 }
346}
347
348static
349void print_state_video (e82730_t *crt)
350{
351 unsigned i;
352
353 pce_prt_sep ("82730-CRTC");
354
355 pce_printf ("CBP: %08lX\n", crt->cbp);
356 pce_printf ("GRAPH: %-4d MONO: %d SINT: %-4d\n", crt->graphic != 0, crt->monochrome != 0, crt->sint_val != 0);
357 pce_printf ("STAT: %04X IMSK: %04X\n", crt->status, crt->intmask);
358 pce_printf ("ALF: %-4d LSSW: %-4d\n", crt->auto_lf != 0, crt->list_switch != 0);
359 pce_printf ("FATTR: %04X\n", crt->field_attrib);
360
361
362 pce_printf ("Mode:\n");
363 pce_printf ("\tline length: %u\n", crt->mode_line_length);
364 pce_printf ("\th field start: %u\n", crt->mode_hfldstrt);
365 pce_printf ("\th field stop: %u\n", crt->mode_hfldstp);
366 pce_printf ("\tframe length: %u\n", crt->mode_frame_length);
367 pce_printf ("\tv field start: %u\n", crt->mode_vfldstrt);
368 pce_printf ("\tv field stop: %u\n", crt->mode_vfldstp);
369 pce_printf ("\tlines per row: %u\n", crt->mode_lines_per_row);
370 pce_printf ("\tframe int count: %u\n", crt->frame_int_count[0]);
371
372 for (i = 0; i < 2; i++) {
373 pce_printf ("CURSOR %u: X=%02X Y=%02X OE=%d RVV=%d BE=%d FREQ=%u DUTY=%u START=%02X STOP=%02X\n",
374 i + 1,
375 crt->cursor_x[i],
376 crt->cursor_y[i],
377 crt->cursor_enable[i],
378 crt->cursor_reverse[i],
379 crt->cursor_blink[i],
380 crt->cursor_max,
381 crt->cursor_duty,
382 crt->cursor_start[i],
383 crt->cursor_stop[i]
384 );
385 }
386}
387
388void print_state_cpu (e8086_t *c)
389{
390 static char ft[2] = { '-', '+' };
391
392 pce_prt_sep ("80186");
393
394 pce_printf (
395 "AX=%04X BX=%04X CX=%04X DX=%04X "
396 "SP=%04X BP=%04X SI=%04X DI=%04X INT=%02X%c\n",
397 e86_get_ax (c), e86_get_bx (c), e86_get_cx (c), e86_get_dx (c),
398 e86_get_sp (c), e86_get_bp (c), e86_get_si (c), e86_get_di (c),
399 par_sim->current_int & 0xff,
400 (par_sim->current_int & 0x100) ? '*' : ' '
401 );
402
403 pce_printf ("CS=%04X DS=%04X ES=%04X SS=%04X IP=%04X F =%04X",
404 e86_get_cs (c), e86_get_ds (c), e86_get_es (c), e86_get_ss (c),
405 e86_get_ip (c), c->flg
406 );
407
408 pce_printf (" I%c D%c O%c S%c Z%c A%c P%c C%c\n",
409 ft[e86_get_if (c)], ft[e86_get_df (c)],
410 ft[e86_get_of (c)], ft[e86_get_sf (c)],
411 ft[e86_get_zf (c)], ft[e86_get_af (c)],
412 ft[e86_get_pf (c)], ft[e86_get_cf (c)]
413 );
414
415 if (e86_get_halt (c)) {
416 pce_printf ("HALT=1\n");
417 }
418}
419
420static
421void print_state_mem (rc759_t *sim)
422{
423 pce_prt_sep ("RC759 MEM");
424 mem_prt_state (sim->mem, stdout);
425}
426
427static
428void print_state_ports (rc759_t *sim)
429{
430 pce_prt_sep ("RC759 PORTS");
431 mem_prt_state (sim->iop, stdout);
432}
433
434static
435void print_state_rc759 (rc759_t *sim)
436{
437 print_state_ppi (&sim->ppi);
438 print_state_tcu (&sim->tcu);
439 print_state_pic (&sim->pic);
440 print_state_dma (&sim->dma);
441 print_state_cpu (sim->cpu);
442}
443
444static
445void print_state (rc759_t *sim)
446{
447 e86_disasm_t op;
448 char str[256];
449
450 e86_disasm_cur (sim->cpu, &op);
451 disasm_str (str, &op);
452
453 print_state_cpu (sim->cpu);
454
455 pce_printf ("%04X:%04X %s\n",
456 (unsigned) e86_get_cs (sim->cpu),
457 (unsigned) e86_get_ip (sim->cpu),
458 str
459 );
460}
461
462static
463int rc759_check_break (rc759_t *sim)
464{
465 unsigned short seg, ofs;
466
467 seg = e86_get_cs (sim->cpu);
468 ofs = e86_get_ip (sim->cpu);
469
470 if (bps_check (&sim->bps, seg, ofs, stdout)) {
471 return (1);
472 }
473
474 if (sim->brk) {
475 return (1);
476 }
477
478 return (0);
479}
480
481static
482void rc759_exec (rc759_t *sim)
483{
484 unsigned old;
485
486 sim->current_int &= 0xff;
487
488 old = e86_get_opcnt (sim->cpu);
489
490 while (e86_get_opcnt (sim->cpu) == old) {
491 rc759_clock (sim, 1);
492
493 if (sim->brk) {
494 break;
495 }
496 }
497}
498
499void rc759_run (rc759_t *sim)
500{
501 pce_start (&sim->brk);
502
503 rc759_clock_discontinuity (sim);
504
505 while (sim->brk == 0) {
506 if (sim->pause == 0) {
507 rc759_clock (sim, 0);
508 }
509 else {
510 pce_usleep (100000);
511 trm_check (sim->trm);
512 }
513 }
514
515 sim->current_int &= 0xff;
516
517 pce_stop();
518}
519
520static
521void pce_op_int (void *ext, unsigned char n)
522{
523 rc759_t *sim;
524
525 sim = ext;
526
527 sim->current_int = n | 0x100;
528
529 if (rc759_intlog_check (sim, n)) {
530 pce_printf ("%04X:%04X: int %02X"
531 " [AX=%04X BX=%04X CX=%04X DX=%04X DS=%04X ES=%04X]\n",
532 e86_get_cs (sim->cpu), e86_get_cur_ip (sim->cpu),
533 n,
534 e86_get_ax (sim->cpu), e86_get_bx (sim->cpu),
535 e86_get_cx (sim->cpu), e86_get_dx (sim->cpu),
536 e86_get_ds (sim->cpu), e86_get_es (sim->cpu)
537 );
538 }
539}
540
541static
542void pce_op_undef (void *ext, unsigned char op1, unsigned char op2)
543{
544 rc759_t *sim;
545
546 sim = ext;
547
548 pce_log (MSG_DEB, "%04X:%04X: undefined operation [%02X %02x]\n",
549 e86_get_cs (sim->cpu), e86_get_ip (sim->cpu), op1, op2
550 );
551
552 pce_usleep (100000UL);
553
554 trm_check (sim->trm);
555}
556
557
558static
559void rc759_cmd_c (cmd_t *cmd, rc759_t *sim)
560{
561 unsigned long cnt;
562
563 cnt = 1;
564
565 cmd_match_uint32 (cmd, &cnt);
566
567 if (!cmd_match_end (cmd)) {
568 return;
569 }
570
571 rc759_clock_discontinuity (sim);
572
573 while (cnt > 0) {
574 rc759_clock (sim, 1);
575 cnt -= 1;
576 }
577
578 print_state (sim);
579}
580
581static
582void rc759_cmd_g_b (cmd_t *cmd, rc759_t *sim)
583{
584 unsigned long seg, ofs;
585 breakpoint_t *bp;
586
587 while (cmd_match_uint32 (cmd, &seg)) {
588 if (cmd_match (cmd, ":")) {
589 if (!cmd_match_uint32 (cmd, &ofs)) {
590 cmd_error (cmd, "expecting offset");
591 return;
592 }
593
594 bp = bp_segofs_new (seg, ofs);
595 }
596 else {
597 bp = bp_addr_new (seg);
598 }
599
600 bps_bp_add (&sim->bps, bp);
601 }
602
603 if (!cmd_match_end (cmd)) {
604 return;
605 }
606
607 pce_start (&sim->brk);
608
609 rc759_clock_discontinuity (sim);
610
611 while (1) {
612 rc759_exec (sim);
613
614 if (rc759_check_break (sim)) {
615 break;
616 }
617 }
618
619 pce_stop();
620}
621
622static
623void rc759_cmd_g_far (cmd_t *cmd, rc759_t *sim)
624{
625 unsigned short seg;
626
627 if (!cmd_match_end (cmd)) {
628 return;
629 }
630
631 seg = e86_get_cs (sim->cpu);
632
633 pce_start (&sim->brk);
634
635 rc759_clock_discontinuity (sim);
636
637 while (1) {
638 rc759_exec (sim);
639
640 if (e86_get_cs (sim->cpu) != seg) {
641 print_state (sim);
642 break;
643 }
644
645 if (rc759_check_break (sim)) {
646 break;
647 }
648 }
649
650 pce_stop();
651}
652
653static
654void rc759_cmd_g (cmd_t *cmd, rc759_t *sim)
655{
656 if (cmd_match (cmd, "b")) {
657 rc759_cmd_g_b (cmd, sim);
658 }
659 else if (cmd_match (cmd, "far")) {
660 rc759_cmd_g_far (cmd, sim);
661 }
662 else {
663 if (!cmd_match_end (cmd)) {
664 return;
665 }
666
667 rc759_run (sim);
668 }
669}
670
671static
672void rc759_cmd_hm (cmd_t *cmd)
673{
674 pce_puts (
675 "emu.config.save <filename>\n"
676 "emu.exit\n"
677 "emu.stop\n"
678 "emu.pause \"0\" | \"1\"\n"
679 "emu.pause.toggle\n"
680 "emu.reset\n"
681 "\n"
682 "emu.cpu.speed <factor>\n"
683 "emu.cpu.speed.step <adjustment>\n"
684 "\n"
685 "emu.parport1.driver <driver>\n"
686 "emu.parport1.file <filename>\n"
687 "emu.parport2.driver <driver>\n"
688 "emu.parport2.file <filename>\n"
689 "\n"
690 "emu.term.fullscreen \"0\" | \"1\"\n"
691 "emu.term.fullscreen.toggle\n"
692 "emu.term.grab\n"
693 "emu.term.release\n"
694 "emu.term.screenshot [<filename>]\n"
695 "emu.term.title <title>\n"
696 "\n"
697 );
698
699 msg_dsk_print_help();
700}
701
702static
703void rc759_cmd_i (cmd_t *cmd, rc759_t *sim)
704{
705 int word;
706 unsigned short port;
707
708 if (cmd_match (cmd, "w")) {
709 word = 1;
710 }
711 else if (cmd_match (cmd, "b")) {
712 word = 0;
713 }
714 else {
715 word = 0;
716 }
717
718 if (!cmd_match_uint16 (cmd, &port)) {
719 cmd_error (cmd, "need a port address");
720 return;
721 }
722
723 if (!cmd_match_end (cmd)) {
724 return;
725 }
726
727 if (word) {
728 pce_printf ("%04X: %04X\n", port, e86_get_prt16 (sim->cpu, port));
729 }
730 else {
731 pce_printf ("%04X: %02X\n", port, e86_get_prt8 (sim->cpu, port));
732 }
733}
734
735static
736void rc759_cmd_key (cmd_t *cmd, rc759_t *sim)
737{
738 unsigned i;
739 unsigned event;
740 pce_key_t key;
741 char str[256];
742
743 while (cmd_match_str (cmd, str, 256)) {
744 i = 0;
745
746 event = PCE_KEY_EVENT_DOWN;
747
748 if (str[0] == '+') {
749 i += 1;
750 }
751 else if (str[0] == '-') {
752 i += 1;
753 event = PCE_KEY_EVENT_UP;
754 }
755
756 key = pce_key_from_string (str + i);
757
758 if (key == PCE_KEY_NONE) {
759 pce_printf ("unknown key: %s\n", str);
760 }
761 else {
762 pce_printf ("key: %s%s\n",
763 (event == PCE_KEY_EVENT_DOWN) ? "+" : "-",
764 str + i
765 );
766
767 rc759_kbd_set_key (&sim->kbd, event, key);
768 }
769 }
770
771 if (!cmd_match_end (cmd)) {
772 return;
773 }
774}
775
776static
777void rc759_cmd_log_int_l (cmd_t *cmd, rc759_t *sim)
778{
779 unsigned i;
780 const char *str;
781
782 for (i = 0; i < 256; i++) {
783 str = rc759_intlog_get (sim, i);
784
785 if (str != NULL) {
786 pce_printf ("%02X: %s\n", i, str);
787 }
788 }
789}
790
791static
792void rc759_cmd_log_int (cmd_t *cmd, rc759_t *sim)
793{
794 unsigned short n;
795 char buf[256];
796
797 if (cmd_match_eol (cmd)) {
798 rc759_cmd_log_int_l (cmd, sim);
799 return;
800 }
801
802 if (cmd_match (cmd, "l")) {
803 rc759_cmd_log_int_l (cmd, sim);
804 return;
805 }
806
807 if (!cmd_match_uint16 (cmd, &n)) {
808 cmd_error (cmd, "need an interrupt number");
809 return;
810 }
811
812 if (cmd_match_eol (cmd)) {
813 rc759_intlog_set (sim, n, NULL);
814 pce_printf ("%02X: <deleted>\n", n);
815 return;
816 }
817
818 if (!cmd_match_str (cmd, buf, 256)) {
819 cmd_error (cmd, "need an expression");
820 return;
821 }
822
823 pce_printf ("%02X: %s\n", n, buf);
824
825 rc759_intlog_set (sim, n, buf);
826}
827
828static
829void rc759_cmd_log (cmd_t *cmd, rc759_t *sim)
830{
831 if (cmd_match (cmd, "int")) {
832 rc759_cmd_log_int (cmd, sim);
833 }
834 else {
835 cmd_error (cmd, "log what?");
836 }
837}
838
839static
840int rc759_cmd_nv_match_addr (cmd_t *cmd, unsigned short *addr)
841{
842 if (cmd_match (cmd, "boot")) {
843 *addr = 0x19;
844 }
845 else if (cmd_match (cmd, "color")) {
846 *addr = 0x16;
847 }
848 else if (cmd_match (cmd, "cursor")) {
849 *addr = 0x13;
850 }
851 else if (cmd_match (cmd, "mdelay")) {
852 *addr = 0x14;
853 }
854 else if (cmd_match (cmd, "mdisk")) {
855 *addr = 0x1b;
856 }
857 else if (cmd_match (cmd, "scroll")) {
858 *addr = 0x12;
859 }
860 else if (cmd_match (cmd, "year")) {
861 *addr = 0x18;
862 }
863 else if (cmd_match_uint16 (cmd, addr)) {
864 ;
865 }
866 else {
867 cmd_error (cmd, "need an address");
868 return (0);
869 }
870
871 return (1);
872}
873
874static
875void rc759_cmd_nvget (cmd_t *cmd, rc759_t *sim)
876{
877 unsigned short addr, cnt, val;
878
879 if (!rc759_cmd_nv_match_addr (cmd, &addr)) {
880 return;
881 }
882
883 if (!cmd_match_uint16 (cmd, &cnt)) {
884 cnt = 1;
885 }
886
887 while (cnt--) {
888 val = rc759_nvm_get_uint8 (&sim->nvm, addr);
889 pce_printf ("NVM: %03X -> %02X\n", addr, val);
890 addr += 1;
891 }
892
893 cmd_match_end (cmd);
894}
895
896static
897void rc759_cmd_nvset (cmd_t *cmd, rc759_t *sim)
898{
899 unsigned short addr, val;
900
901 if (!rc759_cmd_nv_match_addr (cmd, &addr)) {
902 return;
903 }
904
905 while (cmd_match_uint16 (cmd, &val)) {
906 pce_printf ("NVM: %03X <- %02X\n", addr, val);
907 rc759_nvm_set_uint8 (&sim->nvm, addr, val);
908 addr += 1;
909 }
910
911 cmd_match_end (cmd);
912}
913
914static
915void rc759_cmd_nvsum (cmd_t *cmd, rc759_t *sim)
916{
917 unsigned v1, v2;
918
919 v1 = rc759_nvm_get_uint8 (&sim->nvm, 0);
920 rc759_nvm_fix_checksum (&sim->nvm);
921 v2 = rc759_nvm_get_uint8 (&sim->nvm, 0);
922
923 if (v1 != v2) {
924 pce_printf ("NVM: %03X <- %02X\n", 0, v2);
925 }
926 else {
927 pce_printf ("NVM: %03X -> %02X\n", 0, v1);
928 }
929
930 cmd_match_end (cmd);
931}
932
933static
934void rc759_cmd_nv (cmd_t *cmd, rc759_t *sim)
935{
936 if (cmd_match (cmd, "set")) {
937 rc759_cmd_nvset (cmd, sim);
938 }
939 else if (cmd_match (cmd, "get")) {
940 rc759_cmd_nvget (cmd, sim);
941 }
942 else if (cmd_match (cmd, "sum")) {
943 rc759_cmd_nvsum (cmd, sim);
944 }
945 else {
946 cmd_error (cmd, "nv: unknown command");
947 }
948}
949
950static
951void rc759_cmd_o (cmd_t *cmd, rc759_t *sim)
952{
953 int word;
954 unsigned short port, val;
955
956 if (cmd_match (cmd, "w")) {
957 word = 1;
958 }
959 else if (cmd_match (cmd, "b")) {
960 word = 0;
961 }
962 else {
963 word = 0;
964 }
965
966 if (!cmd_match_uint16 (cmd, &port)) {
967 cmd_error (cmd, "need a port address");
968 return;
969 }
970
971 if (!cmd_match_uint16 (cmd, &val)) {
972 cmd_error (cmd, "need a value");
973 return;
974 }
975
976 if (!cmd_match_end (cmd)) {
977 return;
978 }
979
980 if (word) {
981 e86_set_prt16 (sim->cpu, port, val);
982 }
983 else {
984 e86_set_prt8 (sim->cpu, port, val);
985 }
986}
987
988static
989void rc759_cmd_pqc (cmd_t *cmd, rc759_t *sim)
990{
991 if (!cmd_match_end (cmd)) {
992 return;
993 }
994
995 e86_pq_init (sim->cpu);
996}
997
998static
999void rc759_cmd_pqs (cmd_t *cmd, rc759_t *sim)
1000{
1001 unsigned i;
1002
1003 if (!cmd_match_end (cmd)) {
1004 return;
1005 }
1006
1007 pce_puts ("PQ:");
1008
1009 for (i = 0; i < sim->cpu->pq_cnt; i++) {
1010 pce_printf (" %02X", sim->cpu->pq[i]);
1011 }
1012
1013 pce_puts ("\n");
1014}
1015
1016static
1017void rc759_cmd_pqf (cmd_t *cmd, rc759_t *sim)
1018{
1019 if (!cmd_match_end (cmd)) {
1020 return;
1021 }
1022
1023 e86_pq_fill (sim->cpu);
1024}
1025
1026static
1027void rc759_cmd_pq (cmd_t *cmd, rc759_t *sim)
1028{
1029 if (cmd_match (cmd, "c")) {
1030 rc759_cmd_pqc (cmd, sim);
1031 }
1032 else if (cmd_match (cmd, "f")) {
1033 rc759_cmd_pqf (cmd, sim);
1034 }
1035 else if (cmd_match (cmd, "s")) {
1036 rc759_cmd_pqs (cmd, sim);
1037 }
1038 else if (cmd_match_eol (cmd)) {
1039 rc759_cmd_pqs (cmd, sim);
1040 }
1041 else {
1042 cmd_error (cmd, "pq: unknown command (%s)\n");
1043 }
1044}
1045
1046static
1047void rc759_cmd_p (cmd_t *cmd, rc759_t *sim)
1048{
1049 unsigned short seg, ofs;
1050 unsigned long i, n;
1051 int brk;
1052 e86_disasm_t op;
1053
1054 n = 1;
1055
1056 cmd_match_uint32 (cmd, &n);
1057
1058 if (!cmd_match_end (cmd)) {
1059 return;
1060 }
1061
1062 brk = 0;
1063
1064 pce_start (&sim->brk);
1065
1066 sim->current_int &= 0xff;
1067
1068 rc759_clock_discontinuity (sim);
1069
1070 for (i = 0; i < n; i++) {
1071 e86_disasm_cur (sim->cpu, &op);
1072
1073 seg = e86_get_cs (sim->cpu);
1074 ofs = e86_get_ip (sim->cpu);
1075
1076 while ((e86_get_cs (sim->cpu) == seg) && (e86_get_ip (sim->cpu) == ofs)) {
1077 rc759_clock (sim, 1);
1078
1079 if (rc759_check_break (sim)) {
1080 brk = 1;
1081 break;
1082 }
1083 }
1084
1085 if (brk) {
1086 break;
1087 }
1088
1089 if (op.flags & (E86_DFLAGS_CALL | E86_DFLAGS_LOOP)) {
1090 unsigned short ofs2 = ofs + op.dat_n;
1091
1092 while ((e86_get_cs (sim->cpu) != seg) || (e86_get_ip (sim->cpu) != ofs2)) {
1093 rc759_clock (sim, 1);
1094
1095 if (rc759_check_break (sim)) {
1096 brk = 1;
1097 break;
1098 }
1099 }
1100 }
1101
1102 if (brk) {
1103 break;
1104 }
1105
1106 if (rc759_check_break (sim)) {
1107 break;
1108 }
1109 }
1110
1111 pce_stop();
1112
1113 print_state (sim);
1114}
1115
1116static
1117void rc759_cmd_r (cmd_t *cmd, rc759_t *sim)
1118{
1119 unsigned long val;
1120 char sym[256];
1121
1122 if (cmd_match_eol (cmd)) {
1123 print_state_cpu (sim->cpu);
1124 return;
1125 }
1126
1127 if (!cmd_match_ident (cmd, sym, 256)) {
1128 pce_printf ("missing register\n");
1129 return;
1130 }
1131
1132 if (e86_get_reg (sim->cpu, sym, &val)) {
1133 pce_printf ("bad register (%s)\n", sym);
1134 return;
1135 }
1136
1137 if (cmd_match_eol (cmd)) {
1138 pce_printf ("%04lX\n", val);
1139 return;
1140 }
1141
1142 if (!cmd_match_uint32 (cmd, &val)) {
1143 pce_printf ("missing value\n");
1144 return;
1145 }
1146
1147 if (!cmd_match_end (cmd)) {
1148 return;
1149 }
1150
1151 e86_set_reg (sim->cpu, sym, val);
1152
1153 print_state (sim);
1154}
1155
1156static
1157void rc759_cmd_set (cmd_t *cmd, rc759_t *sim)
1158{
1159 unsigned short val;
1160 char str[256];
1161
1162 if (!cmd_match_str (cmd, str, 256)) {
1163 cmd_error (cmd, "missing signal\n");
1164 return;
1165 }
1166
1167 if (!cmd_match_uint16 (cmd, &val)) {
1168 cmd_error (cmd, "missing value\n");
1169 return;
1170 }
1171
1172 if (strcmp (str, "pic.irq0") == 0) {
1173 e8259_set_irq0 (&sim->pic, val);
1174 }
1175 else if (strcmp (str, "pic.irq1") == 0) {
1176 e8259_set_irq1 (&sim->pic, val);
1177 }
1178 else if (strcmp (str, "pic.irq2") == 0) {
1179 e8259_set_irq2 (&sim->pic, val);
1180 }
1181 else if (strcmp (str, "pic.irq3") == 0) {
1182 e8259_set_irq3 (&sim->pic, val);
1183 }
1184 else if (strcmp (str, "pic.irq4") == 0) {
1185 e8259_set_irq4 (&sim->pic, val);
1186 }
1187 else if (strcmp (str, "pic.irq5") == 0) {
1188 e8259_set_irq5 (&sim->pic, val);
1189 }
1190 else if (strcmp (str, "pic.irq6") == 0) {
1191 e8259_set_irq6 (&sim->pic, val);
1192 }
1193 else if (strcmp (str, "pic.irq7") == 0) {
1194 e8259_set_irq7 (&sim->pic, val);
1195 }
1196 else {
1197 pce_printf ("unknown signal (%s)\n", str);
1198 }
1199
1200 cmd_match_end (cmd);
1201}
1202
1203static
1204void rc759_cmd_s (cmd_t *cmd, rc759_t *sim)
1205{
1206 if (cmd_match_eol (cmd)) {
1207 print_state (sim);
1208 return;
1209 }
1210
1211 while (!cmd_match_eol (cmd)) {
1212 if (cmd_match (cmd, "rc759")) {
1213 print_state_rc759 (sim);
1214 }
1215 else if (cmd_match (cmd, "cpu")) {
1216 print_state_cpu (sim->cpu);
1217 }
1218 else if (cmd_match (cmd, "disks")) {
1219 dsks_print_info (sim->dsks);
1220 }
1221 else if (cmd_match (cmd, "dma")) {
1222 print_state_dma (&sim->dma);
1223 }
1224 else if (cmd_match (cmd, "fdc")) {
1225 print_state_fdc (&sim->fdc);
1226 }
1227 else if (cmd_match (cmd, "icu")) {
1228 print_state_icu (&sim->icu);
1229 }
1230 else if (cmd_match (cmd, "mem")) {
1231 print_state_mem (sim);
1232 }
1233 else if (cmd_match (cmd, "ports")) {
1234 print_state_ports (sim);
1235 }
1236 else if (cmd_match (cmd, "pic")) {
1237 print_state_pic (&sim->pic);
1238 }
1239 else if (cmd_match (cmd, "ppi")) {
1240 print_state_ppi (&sim->ppi);
1241 }
1242 else if (cmd_match (cmd, "tcu")) {
1243 print_state_tcu (&sim->tcu);
1244 }
1245 else if (cmd_match (cmd, "video")) {
1246 print_state_video (&sim->crt);
1247 }
1248 else {
1249 cmd_error (cmd, "unknown component (%s)\n");
1250 return;
1251 }
1252 }
1253}
1254
1255static
1256void rc759_cmd_t (cmd_t *cmd, rc759_t *sim)
1257{
1258 unsigned long i, n;
1259
1260 n = 1;
1261
1262 cmd_match_uint32 (cmd, &n);
1263
1264 if (!cmd_match_end (cmd)) {
1265 return;
1266 }
1267
1268 pce_start (&sim->brk);
1269
1270 rc759_clock_discontinuity (sim);
1271
1272 for (i = 0; i < n; i++) {
1273 rc759_exec (sim);
1274
1275 if (rc759_check_break (sim)) {
1276 break;
1277 }
1278 }
1279
1280 pce_stop();
1281
1282 print_state (sim);
1283}
1284
1285static
1286void rc759_cmd_u (cmd_t *cmd, rc759_t *sim)
1287{
1288 unsigned short seg, ofs, cnt, mode;
1289 static unsigned int first = 1;
1290 static unsigned short sseg = 0;
1291 static unsigned short sofs = 0;
1292 e86_disasm_t op;
1293 char str[256];
1294
1295 if (first) {
1296 first = 0;
1297 sseg = e86_get_cs (sim->cpu);
1298 sofs = e86_get_ip (sim->cpu);
1299 }
1300
1301 seg = sseg;
1302 ofs = sofs;
1303 cnt = 16;
1304 mode = 0;
1305
1306 if (cmd_match_uint16_16 (cmd, &seg, &ofs)) {
1307 cmd_match_uint16 (cmd, &cnt);
1308 }
1309
1310 cmd_match_uint16 (cmd, &mode);
1311
1312 if (!cmd_match_end (cmd)) {
1313 return;
1314 }
1315
1316 while (cnt > 0) {
1317 e86_disasm_mem (sim->cpu, &op, seg, ofs);
1318 disasm_str (str, &op);
1319
1320 pce_printf ("%04X:%04X %s\n", seg, ofs, str);
1321
1322 ofs = (ofs + op.dat_n) & 0xffff;
1323
1324 if (mode == 0) {
1325 cnt -= 1;
1326 }
1327 else {
1328 cnt = (cnt < op.dat_n) ? 0 : (cnt - op.dat_n);
1329 }
1330 }
1331
1332 sseg = seg;
1333 sofs = ofs;
1334}
1335
1336int rc759_cmd (rc759_t *sim, cmd_t *cmd)
1337{
1338 if (sim->trm != NULL) {
1339 trm_check (sim->trm);
1340 }
1341
1342 if (cmd_match (cmd, "b")) {
1343 cmd_do_b (cmd, &sim->bps);
1344 }
1345 else if (cmd_match (cmd, "c")) {
1346 rc759_cmd_c (cmd, sim);
1347 }
1348 else if (cmd_match (cmd, "g")) {
1349 rc759_cmd_g (cmd, sim);
1350 }
1351 else if (cmd_match (cmd, "hm")) {
1352 rc759_cmd_hm (cmd);
1353 }
1354 else if (cmd_match (cmd, "i")) {
1355 rc759_cmd_i (cmd, sim);
1356 }
1357 else if (cmd_match (cmd, "key")) {
1358 rc759_cmd_key (cmd, sim);
1359 }
1360 else if (cmd_match (cmd, "log")) {
1361 rc759_cmd_log (cmd, sim);
1362 }
1363 else if (cmd_match (cmd, "nv")) {
1364 rc759_cmd_nv (cmd, sim);
1365 }
1366 else if (cmd_match (cmd, "o")) {
1367 rc759_cmd_o (cmd, sim);
1368 }
1369 else if (cmd_match (cmd, "pq")) {
1370 rc759_cmd_pq (cmd, sim);
1371 }
1372 else if (cmd_match (cmd, "p")) {
1373 rc759_cmd_p (cmd, sim);
1374 }
1375 else if (cmd_match (cmd, "r")) {
1376 rc759_cmd_r (cmd, sim);
1377 }
1378 else if (cmd_match (cmd, "set")) {
1379 rc759_cmd_set (cmd, sim);
1380 }
1381 else if (cmd_match (cmd, "s")) {
1382 rc759_cmd_s (cmd, sim);
1383 }
1384 else if (cmd_match (cmd, "t")) {
1385 rc759_cmd_t (cmd, sim);
1386 }
1387 else if (cmd_match (cmd, "u")) {
1388 rc759_cmd_u (cmd, sim);
1389 }
1390 else {
1391 return (1);
1392 }
1393
1394 return (0);
1395}
1396
1397void rc759_cmd_init (rc759_t *sim, monitor_t *mon)
1398{
1399 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0]));
1400 mon_cmd_add_bp (mon);
1401
1402 sim->cpu->op_ext = sim;
1403
1404 sim->cpu->op_int = pce_op_int;
1405 sim->cpu->op_undef = pce_op_undef;
1406}