fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/atarist/cmd.c *
7 * Created: 2011-03-17 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2011-2019 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 "atarist.h"
25#include "cmd.h"
26#include "dma.h"
27
28#include <string.h>
29
30#include <lib/console.h>
31#include <lib/log.h>
32#include <lib/monitor.h>
33#include <lib/msgdsk.h>
34#include <lib/sysdep.h>
35
36
37#ifndef DEBUG_BIOS
38#define DEBUG_BIOS 0
39#endif
40
41
42mon_cmd_t par_cmd[] = {
43 { "c", "[cnt]", "clock" },
44 { "gb", "[addr..]", "run with breakpoints at addr" },
45 { "ge", "[exception]", "run until exception" },
46 { "g", "", "run" },
47 { "halt", "[val]", "set halt state [2]" },
48 { "hm", "", "print help on messages" },
49 { "p", "[cnt]", "execute cnt instructions, skip calls [1]" },
50 { "reset", "", "reset" },
51 { "rte", "", "execute to next rte" },
52 { "r", "reg [val]", "get or set a register" },
53 { "s", "[what]", "print status (acia0|acia1|cpu|disks|dma|mem|mfp|psg|video)" },
54 { "t", "[cnt]", "execute cnt instructions [1]" },
55 { "u", "[w][[-]addr [cnt]]", "disassemble" },
56 { "uw", "[addr [cnt]]", "disassemble as constant words" }
57};
58
59unsigned par_cmd_cnt = sizeof (par_cmd) / sizeof (par_cmd[0]);
60
61
62static
63void st_dasm_str (char *dst, e68_dasm_t *op, int opcode)
64{
65 unsigned i, n;
66 char tmp[272];
67 const char *ins;
68
69 strcpy (dst, "");
70
71 if (opcode) {
72 for (i = 0; i < op->irn; i++) {
73 sprintf (tmp, "%04X ", (unsigned) op->ir[i]);
74 strcat (dst, tmp);
75 }
76
77 for (i = op->irn; i < 4; i++) {
78 strcat (dst, " ");
79 }
80 }
81
82 if (op->flags & E68_DFLAG_PRIV) {
83 strcat (dst, "*");
84 }
85 else if (op->flags & E68_DFLAG_CALL) {
86 strcat (dst, ">");
87 }
88 else if (op->flags & E68_DFLAG_RTS) {
89 strcat (dst, "<");
90 }
91 else {
92 strcat (dst, " ");
93 }
94
95 ins = op->op;
96
97 switch (op->argn) {
98 case 0:
99 sprintf (tmp, "%s", ins);
100 break;
101
102 case 1:
103 sprintf (tmp, "%-8s %s", ins, op->arg1);
104 break;
105
106 case 2:
107 sprintf (tmp, "%-8s %s, %s", ins, op->arg1, op->arg2);
108 break;
109
110 case 3:
111 sprintf (tmp, "%-8s %s, %s, %s",
112 ins, op->arg1, op->arg2, op->arg3
113 );
114 break;
115
116 default:
117 strcpy (tmp, "---");
118 break;
119 }
120
121 strcat (dst, tmp);
122
123 if (op->comm[0] != 0) {
124 n = strlen (dst);
125
126 dst += n;
127
128 while (n < 50) {
129 *(dst++) = ' ';
130 n += 1;
131 }
132
133 strcpy (dst, "; ");
134 strcat (dst, op->comm);
135 }
136}
137
138void st_print_state_cpu (atari_st_t *sim)
139{
140 e68000_t *c;
141 e68_dasm_t op;
142 char str[256];
143
144 pce_prt_sep ("68000");
145
146 c = sim->cpu;
147
148 pce_printf ("SR=%04X [%c%c %c%c%c%c%c] EX=%02X(%-4s) TA=%04X IL=%X/%X\n",
149 (unsigned) e68_get_sr (c),
150 (e68_get_sr_t (c)) ? 'T' : '-',
151 (e68_get_sr_s (c)) ? 'S' : '-',
152 (e68_get_sr_x (c)) ? 'X' : '-',
153 (e68_get_sr_n (c)) ? 'N' : '-',
154 (e68_get_sr_z (c)) ? 'Z' : '-',
155 (e68_get_sr_v (c)) ? 'V' : '-',
156 (e68_get_sr_c (c)) ? 'C' : '-',
157 e68_get_exception (c),
158 e68_get_exception_name (c),
159 e68_get_last_trap_a (c),
160 e68_get_ipl (c),
161 e68_get_iml (c)
162 );
163
164 pce_printf ("D0=%08lX D4=%08lX A0=%08lX A4=%08lX PC=%08lX PC1=%08lX\n",
165 (unsigned long) e68_get_dreg32 (c, 0),
166 (unsigned long) e68_get_dreg32 (c, 4),
167 (unsigned long) e68_get_areg32 (c, 0),
168 (unsigned long) e68_get_areg32 (c, 4),
169 (unsigned long) e68_get_pc (c),
170 (unsigned long) e68_get_last_pc (c, 0)
171 );
172
173 pce_printf ("D1=%08lX D5=%08lX A1=%08lX A5=%08lX PPC=%08lX PC2=%08lX\n",
174 (unsigned long) e68_get_dreg32 (c, 1),
175 (unsigned long) e68_get_dreg32 (c, 5),
176 (unsigned long) e68_get_areg32 (c, 1),
177 (unsigned long) e68_get_areg32 (c, 5),
178 e68_get_ir_pc (c),
179 (unsigned long) e68_get_last_pc (c, 1)
180 );
181
182 pce_printf ("D2=%08lX D6=%08lX A2=%08lX A6=%08lX USP=%08lX PC3=%08lX\n",
183 (unsigned long) e68_get_dreg32 (c, 2),
184 (unsigned long) e68_get_dreg32 (c, 6),
185 (unsigned long) e68_get_areg32 (c, 2),
186 (unsigned long) e68_get_areg32 (c, 6),
187 (unsigned long) e68_get_usp (c),
188 (unsigned long) e68_get_last_pc (c, 2)
189 );
190
191 pce_printf ("D3=%08lX D7=%08lX A3=%08lX A7=%08lX SSP=%08lX PC4=%08lX\n",
192 (unsigned long) e68_get_dreg32 (c, 3),
193 (unsigned long) e68_get_dreg32 (c, 7),
194 (unsigned long) e68_get_areg32 (c, 3),
195 (unsigned long) e68_get_areg32 (c, 7),
196 (unsigned long) e68_get_ssp (c),
197 (unsigned long) e68_get_last_pc (c, 3)
198 );
199
200 e68_dasm_mem (c, &op, e68_get_pc (c));
201 st_dasm_str (str, &op, 1);
202
203 pce_printf ("%08lX %s\n", (unsigned long) e68_get_pc (c), str);
204}
205
206static
207void st_print_state_cpu_short (e68000_t *c)
208{
209 e68_dasm_t op;
210 char str[256];
211
212 e68_dasm_mem (c, &op, e68_get_pc (c));
213 st_dasm_str (str, &op, 0);
214
215 pce_printf ("D0=%08lX A0=%08lX A6=%08lX A7=%08lX SR=%04X[%c%c%c%c%c%c%c] %06lX %s\n",
216 (unsigned long) e68_get_dreg32 (c, 0),
217 (unsigned long) e68_get_areg32 (c, 0),
218 (unsigned long) e68_get_areg32 (c, 6),
219 (unsigned long) e68_get_areg32 (c, 7),
220 (unsigned) e68_get_sr (c),
221 (e68_get_sr_t (c)) ? 'T' : '-',
222 (e68_get_sr_s (c)) ? 'S' : '-',
223 (e68_get_sr_c (c)) ? 'C' : '-',
224 (e68_get_sr_v (c)) ? 'V' : '-',
225 (e68_get_sr_z (c)) ? 'Z' : '-',
226 (e68_get_sr_n (c)) ? 'N' : '-',
227 (e68_get_sr_x (c)) ? 'X' : '-',
228 (unsigned long) e68_get_pc (c), str
229 );
230}
231
232static
233void st_print_state_mfp_timer (e68901_timer_t *tmr, const char *label)
234{
235 pce_printf ("TM-%s: CR=%02X DR=%02X/%02X DIV=%04X CLK=%04X OUT=%d (%u/%u)\n",
236 label,
237 tmr->cr, tmr->dr[0], tmr->dr[1],
238 tmr->clk_div_set, tmr->clk_val / tmr->clk_div_inp,
239 tmr->out != 0, tmr->clk_val, tmr->clk_div
240 );
241}
242
243static
244void st_print_state_mfp (atari_st_t *sim)
245{
246 e68901_t *mfp;
247
248 static char parity[4] = { 'N', 'N', 'O', 'E' };
249
250 mfp = &sim->mfp;
251
252 pce_prt_sep ("68901-MFP");
253
254 pce_printf ("GPIP: INP=%02X/%02X OUT=%02X AER=%02X DDR=%02X\n",
255 mfp->gpip_inp, mfp->gpip_xor, mfp->gpip_val, mfp->gpip_aer, mfp->gpip_ddr
256 );
257
258 pce_printf ("INTR: IRR=%04X/%04X IER=%04X IPR=%04X IMR=%04X ISR=%04X IVR=%02X VEC=%02X IRQ=%d\n",
259 mfp->irr1, mfp->irr2, mfp->ier, mfp->ipr, mfp->imr, mfp->isr, mfp->ivr, mfp->vec, mfp->irq_val
260 );
261
262 pce_printf ("UART: PAR=%u%c%u UCR=%02X RSR=%02X RDR=%02X TSR=%02X TDR=%02X RCLK=%u/%u SCLK=%u/%u\n",
263 8 - ((mfp->ucr >> 5) & 3),
264 parity[(mfp->ucr >> 1) & 3],
265 (((mfp->ucr >> 3) & 3) + 1) / 2,
266 mfp->ucr, mfp->rsr[0], mfp->rdr[0], mfp->tsr[0], mfp->tdr[0],
267 mfp->recv_clk_cnt, mfp->recv_clk_max,
268 mfp->send_clk_cnt, mfp->send_clk_max
269 );
270
271 st_print_state_mfp_timer (mfp->timer + 0, "A");
272 st_print_state_mfp_timer (mfp->timer + 1, "B");
273 st_print_state_mfp_timer (mfp->timer + 2, "C");
274 st_print_state_mfp_timer (mfp->timer + 3, "D");
275}
276
277static
278void st_print_state_acia (atari_st_t *sim, unsigned idx)
279{
280 e6850_t *acia;
281
282 if (idx == 0) {
283 acia = &sim->acia0;
284 pce_prt_sep ("6850-ACIA-0");
285 }
286 else {
287 acia = &sim->acia1;
288 pce_prt_sep ("6850-ACIA-1");
289 }
290
291 pce_printf ("CR=%02X SR=%02X TDR=%02X RDR=%02X IRQ=%d\n",
292 acia->cr, acia->sr, acia->tdr, acia->rdr, acia->irq_val
293 );
294}
295
296static
297void st_print_state_dma (atari_st_t *sim)
298{
299 st_dma_t *dma;
300
301 dma = &sim->dma;
302
303 pce_prt_sep ("DMA");
304
305 pce_printf ("MODE=%04X STATUS=%04X ADDR=%06lX MASK=%06lX\n",
306 dma->mode, dma->status, dma->addr, dma->mask
307 );
308}
309
310static
311void st_print_state_mem (atari_st_t *sim)
312{
313 pce_prt_sep ("MEM");
314 mem_prt_state (sim->mem, stdout);
315}
316
317static
318void st_print_state_psg (atari_st_t *sim)
319{
320 st_psg_t *psg;
321
322 pce_prt_sep ("PSG");
323
324 psg = &sim->psg;
325
326 pce_printf ("R%02X=%02X PA=%u\n", 0, psg->reg[0],
327 ((psg->reg[1] << 8) | (psg->reg[0])) & 0x3ff
328 );
329
330 pce_printf ("R%02X=%02X\n", 1, psg->reg[1]);
331
332 pce_printf ("R%02X=%02X PB=%u\n", 2, psg->reg[2],
333 ((psg->reg[3] << 8) | (psg->reg[2])) & 0x3ff
334 );
335
336 pce_printf ("R%02X=%02X\n", 3, psg->reg[3]);
337
338 pce_printf ("R%02X=%02X PC=%u\n", 4, psg->reg[4],
339 ((psg->reg[5] << 8) | (psg->reg[4])) & 0x3ff
340 );
341
342 pce_printf ("R%02X=%02X\n", 5, psg->reg[5]);
343
344 pce_printf ("R%02X=%02X PN=%u\n", 6, psg->reg[6],
345 psg->reg[6] & 0x1f
346 );
347
348 pce_printf ("R%02X=%02X N=%c%c%c T=%c%c%c\n", 7, psg->reg[7],
349 (psg->reg[7] & 8) ? 'a' : 'A',
350 (psg->reg[7] & 16) ? 'b' : 'B',
351 (psg->reg[7] & 32) ? 'c' : 'C',
352 (psg->reg[7] & 1) ? 'a' : 'A',
353 (psg->reg[7] & 2) ? 'b' : 'B',
354 (psg->reg[7] & 4) ? 'c' : 'C'
355 );
356
357 pce_printf ("R%02X=%02X VA=%u %c\n", 8, psg->reg[8],
358 psg->reg[8] & 0x0f,
359 (psg->reg[8] & 0x10) ? 'M' : '-'
360 );
361
362 pce_printf ("R%02X=%02X VB=%u %c\n", 9, psg->reg[9],
363 psg->reg[9] & 0x0f,
364 (psg->reg[9] & 0x10) ? 'M' : '-'
365 );
366
367 pce_printf ("R%02X=%02X VC=%u %c\n", 10, psg->reg[10],
368 psg->reg[10] & 0x0f,
369 (psg->reg[10] & 0x10) ? 'M' : '-'
370 );
371
372 pce_printf ("R%02X=%02X PE=%u\n", 11, psg->reg[11],
373 ((psg->reg[12] << 8) | (psg->reg[11])) & 0xffff
374 );
375
376 pce_printf ("R%02X=%02X\n", 12, psg->reg[12]);
377
378 pce_printf ("R%02X=%02X ENV=%X\n", 13, psg->reg[13],
379 psg->reg[13] & 0x0f
380 );
381
382 pce_printf ("R%02X=%02X\n", 14, psg->reg[14]);
383 pce_printf ("R%02X=%02X\n", 15, psg->reg[15]);
384}
385
386static
387void st_print_state_video (atari_st_t *sim)
388{
389 unsigned i;
390 st_video_t *vid;
391
392 vid = sim->video;
393
394 pce_prt_sep ("VIDEO");
395
396 pce_printf ("B=%06lX A=%06lX HB=%-3d VB=%-3d\n",
397 vid->base, vid->addr, vid->hb_val != 0, vid->vb_val != 0
398 );
399
400 pce_printf ("X=%-3u HB1=%-3u HB2=%-3u %lu Hz\n",
401 vid->clk, vid->hb1, vid->hb2,
402 (8000000UL + vid->hb2 / 2) / vid->hb2
403 );
404
405 pce_printf ("Y=%-3u VB1=%-3u VB2=%-3u %lu Hz\n",
406 vid->line, vid->vb1, vid->vb2,
407 (8000000UL + (vid->hb2 * vid->vb2) / 2) / (vid->hb2 * vid->vb2)
408 );
409
410 for (i = 0; i < 8; i++) {
411 pce_printf ("PAL%X=%04X [%02X %02X %02X] PAL%X=%04X [%02X %02X %02X]\n",
412 i, vid->palette[i],
413 vid->pal_col[i][0], vid->pal_col[i][1], vid->pal_col[i][2],
414 i + 8, vid->palette[i + 8],
415 vid->pal_col[i + 8][0], vid->pal_col[i + 8][1], vid->pal_col[i + 8][2]
416 );
417 }
418}
419
420static
421void st_print_state (atari_st_t *sim, const char *str)
422{
423 cmd_t cmd;
424
425 cmd_set_str (&cmd, str);
426
427 if (cmd_match_eol (&cmd)) {
428 return;
429 }
430
431 while (!cmd_match_eol (&cmd)) {
432 if (cmd_match (&cmd, "cpu")) {
433 st_print_state_cpu (sim);
434 }
435 else if (cmd_match (&cmd, "disks")) {
436 dsks_print_info (sim->dsks);
437 }
438 else if (cmd_match (&cmd, "dma")) {
439 st_print_state_dma (sim);
440 }
441 else if (cmd_match (&cmd, "mem")) {
442 st_print_state_mem (sim);
443 }
444 else if (cmd_match (&cmd, "acia0")) {
445 st_print_state_acia (sim, 0);
446 }
447 else if (cmd_match (&cmd, "acia1")) {
448 st_print_state_acia (sim, 1);
449 }
450 else if (cmd_match (&cmd, "mfp")) {
451 st_print_state_mfp (sim);
452 }
453 else if (cmd_match (&cmd, "psg")) {
454 st_print_state_psg (sim);
455 }
456 else if (cmd_match (&cmd, "video")) {
457 st_print_state_video (sim);
458 }
459 else {
460 pce_printf ("unknown component (%s)\n", cmd_get_str (&cmd));
461 return;
462 }
463 }
464}
465
466
467/*
468 * Check if a breakpoint has triggered
469 */
470static
471int st_check_break (atari_st_t *sim)
472{
473 unsigned long pc;
474
475 pc = e68_get_pc (sim->cpu) & 0x00ffffff;
476
477 if (bps_check (&sim->bps, 0, pc, stdout)) {
478 return (1);
479 }
480
481 if (sim->brk) {
482 return (1);
483 }
484
485 return (0);
486}
487
488/*
489 * Execute one instruction
490 */
491static
492int st_exec (atari_st_t *sim)
493{
494 unsigned long old;
495
496 old = e68_get_opcnt (sim->cpu);
497
498 while (e68_get_opcnt (sim->cpu) == old) {
499 st_clock (sim, 1);
500
501 if (st_check_break (sim)) {
502 return (1);
503 }
504 }
505
506 return (0);
507}
508
509/*
510 * Execute until a specific PC is reached
511 */
512static
513int st_exec_to (atari_st_t *sim, unsigned long addr)
514{
515 while (e68_get_pc (sim->cpu) != addr) {
516 st_clock (sim, 1);
517
518 if (st_check_break (sim)) {
519 return (1);
520 }
521 }
522
523 return (0);
524}
525
526/*
527 * Run the simulation
528 */
529void st_run (atari_st_t *sim)
530{
531 pce_start (&sim->brk);
532
533 st_clock_discontinuity (sim);
534
535 while (1) {
536 st_clock (par_sim, 0);
537
538 if (sim->brk) {
539 break;
540 }
541
542 while (sim->pause) {
543 pce_usleep (50UL * 1000UL);
544 trm_check (sim->trm);
545 }
546 }
547
548 pce_stop();
549}
550
551
552static
553void st_log_trap_bios (atari_st_t *sim, unsigned iw)
554{
555 unsigned i;
556 unsigned short par[8];
557
558#if (DEBUG_BIOS == 0)
559 return;
560#endif
561
562 for (i = 0; i < 8; i++) {
563 par[i] = mem_get_uint16_be (sim->mem, e68_get_areg32 (sim->cpu, 7) + 2 * i);
564 }
565
566 switch (par[0]) {
567 case 1:
568 //st_log_deb ("bios_constat (%u)\n", par[1]);
569 break;
570
571 case 2:
572 st_log_deb ("bios_conin (%u)\n", par[1]);
573 break;
574
575 case 3:
576 st_log_deb ("bios_conout (%u, %u)\n", par[1], par[2]);
577 break;
578
579 case 4:
580 st_log_deb ("bios_rwabs (%u, 0x%08lx, %u, %u, %u)\n",
581 par[1], ((unsigned long) par[2] << 16) | par[3],
582 par[4], par[5], par[6]
583 );
584 break;
585
586 case 5:
587 st_log_deb ("bios_setexc (%u, %lu)\n",
588 par[1], ((unsigned long) par[2] << 16) | par[3]
589 );
590 break;
591
592 case 9:
593 st_log_deb ("bios_media_change (%u)\n", par[1]);
594 break;
595
596 default:
597 st_log_deb ("bios (%u, %u, %u, %u)\n", par[0], par[1], par[2], par[3]);
598 break;
599 }
600}
601
602static
603void st_log_exception (void *ext, unsigned tn)
604{
605 unsigned iw;
606 atari_st_t *sim = ext;
607
608 iw = e68_get_mem16 (sim->cpu, e68_get_last_pc (sim->cpu, 0));
609
610 switch (tn) {
611 case 0x00:
612 st_reset (sim);
613 return;
614
615 case 0x02: /* BUSE */
616 return;
617
618 case 0x04: /* ILLG */
619 case 0x09: /* TRACE */
620 case 0x0a: /* AXXX */
621 case 0x0b: /* FXXX */
622 return;
623
624 case 0x1a: /* AVEC 2 */
625 case 0x1c: /* AVEC 4 */
626 case 0x1e: /* AVEC 6 */
627 return;
628
629 case 0x20: /* trap */
630 case 0x21:
631 case 0x22:
632 case 0x27:
633 case 0x28:
634 case 0x29:
635 case 0x2a:
636 case 0x2b:
637 case 0x2c:
638 case 0x2e:
639 case 0x2f:
640 return;
641
642 case 0x2d:
643 st_log_trap_bios (sim, iw);
644 return;
645
646 case 0x06:
647 case 0x08:
648 case 0x42: /* MFP RS232 CTS */
649 case 0x44: /* MFP Timer D */
650 case 0x45: /* MFP Timer C */
651 case 0x46: /* MFP I4 (ACIA0) */
652 case 0x48: /* HB counter */
653 case 0x49: /* USART send data */
654 case 0x4a: /* USART send error */
655 case 0x4b: /* USART recv data */
656 case 0x4c: /* USART recv error */
657 case 0x4d: /* MFP Timer A */
658 return;
659 }
660
661 pce_log (MSG_DEB,
662 "%08lX: exception %02X (%s) IW=%04X\n",
663 (unsigned long) e68_get_last_pc (sim->cpu, 0),
664 tn, e68_get_exception_name (sim->cpu), iw
665 );
666}
667
668
669/*
670 * c - clock
671 */
672static
673void st_cmd_c (cmd_t *cmd, atari_st_t *sim)
674{
675 unsigned long cnt;
676
677 cnt = 1;
678
679 cmd_match_uint32 (cmd, &cnt);
680
681 if (!cmd_match_end (cmd)) {
682 return;
683 }
684
685 while (cnt > 0) {
686 st_clock (sim, 1);
687 cnt -= 1;
688 }
689
690 st_print_state_cpu (sim);
691}
692
693/*
694 * gb - run with breakpoints
695 */
696static
697void st_cmd_g_b (cmd_t *cmd, atari_st_t *sim)
698{
699 unsigned long addr;
700 breakpoint_t *bp;
701
702 while (cmd_match_uint32 (cmd, &addr)) {
703 bp = bp_addr_new (addr);
704 bps_bp_add (&sim->bps, bp);
705 }
706
707 if (!cmd_match_end (cmd)) {
708 return;
709 }
710
711 pce_start (&sim->brk);
712
713 st_clock_discontinuity (sim);
714
715 while (1) {
716 if (st_exec (sim)) {
717 break;
718 }
719 }
720
721 pce_stop();
722}
723
724/*
725 * ge - run until an exception is raised
726 */
727static
728void st_cmd_g_e (cmd_t *cmd, atari_st_t *sim)
729{
730 unsigned short tn;
731 unsigned cnt;
732
733 if (!cmd_match_uint16 (cmd, &tn)) {
734 tn = 0xffff;
735 }
736
737 if (!cmd_match_end (cmd)) {
738 return;
739 }
740
741 cnt = e68_get_exception_cnt (sim->cpu);
742
743 pce_start (&sim->brk);
744
745 st_clock_discontinuity (sim);
746
747 while (1) {
748 st_exec (sim);
749
750 if (st_check_break (sim)) {
751 break;
752 }
753
754 if (e68_get_exception_cnt (sim->cpu) == cnt) {
755 continue;
756 }
757
758 if (tn == 0xffff) {
759 pce_printf ("exception %02X (%s)\n",
760 e68_get_exception (sim->cpu),
761 e68_get_exception_name (sim->cpu)
762 );
763 break;
764 }
765 else {
766 if (e68_get_exception (sim->cpu) == tn) {
767 pce_printf ("exception %02X (%s)\n",
768 e68_get_exception (sim->cpu),
769 e68_get_exception_name (sim->cpu)
770 );
771 break;
772 }
773 }
774
775 }
776
777 pce_stop();
778}
779
780/*
781 * g - run
782 */
783static
784void st_cmd_g (cmd_t *cmd, atari_st_t *sim)
785{
786 if (cmd_match (cmd, "b")) {
787 st_cmd_g_b (cmd, sim);
788 return;
789 }
790 else if (cmd_match (cmd, "e")) {
791 st_cmd_g_e (cmd, sim);
792 return;
793 }
794
795 if (!cmd_match_end (cmd)) {
796 return;
797 }
798
799 st_run (sim);
800}
801
802/*
803 * halt - halt the cpu
804 */
805static
806void st_cmd_halt (cmd_t *cmd, atari_st_t *sim)
807{
808 unsigned short val;
809
810 if (cmd_match_uint16 (cmd, &val) == 0) {
811 val = 2;
812 }
813
814 if (!cmd_match_end (cmd)) {
815 return;
816 }
817
818 e68_set_halt (sim->cpu, val);
819
820 st_print_state_cpu (sim);
821}
822
823/*
824 * hm - help on messages
825 */
826static
827void st_cmd_hm (cmd_t *cmd)
828{
829 pce_puts (
830 "emu.exit\n"
831 "emu.stop\n"
832 "emu.pause \"0\" | \"1\"\n"
833 "emu.pause.toggle\n"
834 "emu.reset\n"
835 "\n"
836 "emu.cpu.model \"68000\" | \"68010\" | \"68020\"\n"
837 "emu.cpu.speed <factor>\n"
838 "emu.cpu.speed.step <adjustment>\n"
839 "\n"
840 "emu.midi.file <fname>\n"
841 "\n"
842 "emu.fdc.ro <drive>\n"
843 "emu.fdc.rw <drive>\n"
844 "\n"
845 "emu.par.driver <driver>\n"
846 "emu.par.file <filename>\n"
847 "\n"
848 "emu.psg.aym.file <filename>\n"
849 "emu.psg.aym.res <usec>\n"
850 "emu.psg.driver <driver>\n"
851 "emu.psg.lowpass <freq>\n"
852 "\n"
853 "emu.ser.driver <driver>\n"
854 "emu.ser.file <filename>\n"
855 "\n"
856 "emu.viking \"0\" | \"1\"\n"
857 "emu.viking.toggle\n"
858 "\n"
859 "term.fullscreen \"0\" | \"1\"\n"
860 "term.fullscreen.toggle\n"
861 "term.grab\n"
862 "term.release\n"
863 "term.screenshot [<filename>]\n"
864 "term.title <title>\n"
865 "\n"
866 );
867
868 msg_dsk_print_help();
869}
870
871/*
872 * p - step
873 */
874static
875void st_cmd_p (cmd_t *cmd, atari_st_t *sim)
876{
877 unsigned ecnt;
878 unsigned long cnt;
879 e68_dasm_t da;
880
881 cnt = 1;
882
883 while (cmd_match (cmd, "p")) {
884 cnt += 1;
885 }
886
887 cmd_match_uint32 (cmd, &cnt);
888
889 if (!cmd_match_end (cmd)) {
890 return;
891 }
892
893 pce_start (&sim->brk);
894
895 st_clock_discontinuity (sim);
896
897 while (cnt > 0) {
898 e68_dasm_mem (sim->cpu, &da, e68_get_pc (sim->cpu));
899
900 if (da.flags & E68_DFLAG_CALL) {
901 if (st_exec_to (sim, e68_get_pc (sim->cpu) + 2 * da.irn)) {
902 break;
903 }
904 }
905 else {
906 ecnt = e68_get_exception_cnt (sim->cpu);
907
908 if (st_exec (sim)) {
909 break;
910 }
911
912 if (e68_get_exception_cnt (sim->cpu) != ecnt) {
913 if (st_exec_to (sim, sim->cpu->except_addr)) {
914 break;
915 }
916 }
917 }
918
919 cnt -= 1;
920 }
921
922 pce_stop();
923
924 st_print_state_cpu (sim);
925}
926
927/*
928 * n - run to following instruction
929 */
930static
931void st_cmd_n (cmd_t *cmd, atari_st_t *sim)
932{
933 unsigned long cnt;
934 e68_dasm_t da;
935
936 cnt = 1;
937
938 while (cmd_match (cmd, "n")) {
939 cnt += 1;
940 }
941
942 cmd_match_uint32 (cmd, &cnt);
943
944 if (!cmd_match_end (cmd)) {
945 return;
946 }
947
948 pce_start (&sim->brk);
949
950 st_clock_discontinuity (sim);
951
952 while (cnt > 0) {
953 e68_dasm_mem (sim->cpu, &da, e68_get_pc (sim->cpu));
954
955 if (st_exec_to (sim, e68_get_pc (sim->cpu) + 2 * da.irn)) {
956 break;
957 }
958
959 cnt -= 1;
960 }
961
962 pce_stop();
963
964 st_print_state_cpu (sim);
965}
966
967/*
968 * reset - reset the simulation
969 */
970static
971void st_cmd_reset (cmd_t *cmd, atari_st_t *sim)
972{
973 if (!cmd_match_end (cmd)) {
974 return;
975 }
976
977 st_reset (sim);
978
979 st_print_state_cpu (sim);
980}
981
982/*
983 * rte - execute until rte
984 */
985static
986void st_cmd_rte (cmd_t *cmd, atari_st_t *sim)
987{
988 e68_dasm_t dis;
989
990 if (!cmd_match_end (cmd)) {
991 return;
992 }
993
994 pce_start (&sim->brk);
995
996 while (1) {
997 st_exec (sim);
998
999 if (st_check_break (sim)) {
1000 break;
1001 }
1002
1003 e68_dasm_mem (sim->cpu, &dis, e68_get_pc (sim->cpu));
1004
1005 if (dis.flags & E68_DFLAG_RTE) {
1006 st_print_state_cpu (sim);
1007 break;
1008 }
1009 }
1010
1011 pce_stop();
1012}
1013
1014/*
1015 * r - display or set register contents
1016 */
1017static
1018void st_cmd_r (cmd_t *cmd, atari_st_t *sim)
1019{
1020 unsigned long val;
1021 char sym[256];
1022
1023 if (cmd_match_eol (cmd)) {
1024 st_print_state_cpu (sim);
1025 return;
1026 }
1027
1028 if (!cmd_match_ident (cmd, sym, 256)) {
1029 cmd_error (cmd, "missing register\n");
1030 return;
1031 }
1032
1033 if (e68_get_reg (sim->cpu, sym, &val)) {
1034 pce_printf ("bad register (%s)\n", sym);
1035 return;
1036 }
1037
1038 if (cmd_match_eol (cmd)) {
1039 pce_printf ("%08lX\n", val);
1040 return;
1041 }
1042
1043 if (!cmd_match_uint32 (cmd, &val)) {
1044 cmd_error (cmd, "missing value\n");
1045 return;
1046 }
1047
1048 if (!cmd_match_end (cmd)) {
1049 return;
1050 }
1051
1052 e68_set_reg (sim->cpu, sym, val);
1053
1054 st_print_state_cpu (sim);
1055}
1056
1057/*
1058 * s - print state
1059 */
1060static
1061void st_cmd_s (cmd_t *cmd, atari_st_t *sim)
1062{
1063 if (cmd_match_eol (cmd)) {
1064 st_print_state_cpu (sim);
1065 return;
1066 }
1067
1068 st_print_state (sim, cmd_get_str (cmd));
1069}
1070
1071/*
1072 * t - execute one instruction
1073 */
1074static
1075void st_cmd_t (cmd_t *cmd, atari_st_t *sim)
1076{
1077 unsigned long i, n, k;
1078
1079 n = 1;
1080 k = 0;
1081
1082 while (cmd_match (cmd, "t")) {
1083 n += 1;
1084 }
1085
1086 cmd_match_uint32 (cmd, &n);
1087 cmd_match_uint32 (cmd, &k);
1088
1089 if (!cmd_match_end (cmd)) {
1090 return;
1091 }
1092
1093 pce_start (&sim->brk);
1094
1095 st_clock_discontinuity (sim);
1096
1097 for (i = 0; i < n; i++) {
1098 if ((n > 1) && (i >= k)) {
1099 st_print_state_cpu_short (sim->cpu);
1100 }
1101
1102 st_exec (sim);
1103 }
1104
1105 pce_stop();
1106
1107 st_print_state_cpu (sim);
1108}
1109
1110/*
1111 * u- - disassemble to address
1112 */
1113static
1114void st_cmd_u_to (cmd_t *cmd, atari_st_t *sim, unsigned long addr)
1115{
1116 unsigned long cnt;
1117 unsigned ins_i, ins_j, ins_n;
1118 unsigned sync;
1119 unsigned long pc;
1120 unsigned long insn[256];
1121 e68_dasm_t op;
1122 char str[256];
1123
1124 cnt = 16;
1125
1126 if (cmd_match_uint32 (cmd, &addr)) {
1127 cmd_match_uint32 (cmd, &cnt);
1128 }
1129
1130 if (!cmd_match_end (cmd)) {
1131 return;
1132 }
1133
1134 if (cnt > 256) {
1135 cnt = 256;
1136 }
1137
1138 ins_i = 0;
1139 ins_j = 0;
1140 ins_n = 0;
1141 sync = 5;
1142
1143 pc = (addr - 12 * cnt) & ~1UL;
1144
1145 while (pc <= addr) {
1146 if (sync == 0) {
1147 insn[ins_j] = pc;
1148 ins_j = (ins_j + 1) % 256;
1149 if (ins_j == ins_i) {
1150 ins_i = (ins_i + 1) % 256;
1151 }
1152 else {
1153 ins_n += 1;
1154 }
1155 }
1156 else {
1157 sync -= 1;
1158 }
1159
1160 e68_dasm_mem (sim->cpu, &op, pc);
1161
1162 pc += 2 * op.irn;
1163 }
1164
1165 if (ins_n > cnt) {
1166 ins_i = (ins_i + (ins_n - cnt)) % 256;
1167 }
1168
1169 while (ins_i != ins_j) {
1170 pc = insn[ins_i];
1171
1172 e68_dasm_mem (sim->cpu, &op, pc);
1173 st_dasm_str (str, &op, 1);
1174
1175 pce_printf ("%08lX %s\n", pc, str);
1176
1177 ins_i = (ins_i + 1) % 256;
1178 }
1179
1180
1181}
1182
1183/*
1184 * uw - disassemble as constant words
1185 */
1186static
1187void st_cmd_u_w (cmd_t *cmd, atari_st_t *sim)
1188{
1189 unsigned i, col;
1190 unsigned long addr, cnt;
1191 e68_dasm_t op;
1192 char str[256];
1193
1194 if (cmd_match_uint32 (cmd, &addr) == 0) {
1195 addr = 0;
1196 }
1197
1198 if (cmd_match_uint32 (cmd, &cnt) == 0) {
1199 cnt = 256;
1200 }
1201
1202 if (!cmd_match_end (cmd)) {
1203 return;
1204 }
1205
1206 while (1) {
1207 e68_dasm_mem (sim->cpu, &op, addr);
1208 st_dasm_str (str, &op, 0);
1209
1210 pce_printf (".word 0x%04x", op.ir[0]);
1211
1212 for (i = 1; i < op.irn; i++) {
1213 pce_printf (", 0x%04x", op.ir[i]);
1214 }
1215
1216 col = 4 + 8 * op.irn;
1217
1218 while (col < 32) {
1219 pce_printf ("\t");
1220 col = (col + 8) & ~7;
1221 }
1222
1223 pce_printf ("\t/* %06lX %s */\n", addr, str);
1224
1225 if (op.flags & E68_DFLAG_RTS) {
1226 pce_printf ("\n");
1227 }
1228
1229 if (cnt <= (2 * op.irn)) {
1230 break;
1231 }
1232
1233 addr += 2 * op.irn;
1234 cnt -= 2 * op.irn;
1235 }
1236}
1237
1238/*
1239 * u - disassemble
1240 */
1241static
1242void st_cmd_u (cmd_t *cmd, atari_st_t *sim)
1243{
1244 unsigned i;
1245 unsigned long addr, cnt;
1246 static unsigned int first = 1;
1247 static unsigned long saddr = 0;
1248 e68_dasm_t op;
1249 char str[256];
1250
1251 if (cmd_match (cmd, "w")) {
1252 st_cmd_u_w (cmd, sim);
1253 return;
1254 }
1255
1256 if (first) {
1257 first = 0;
1258 saddr = e68_get_pc (sim->cpu);
1259 }
1260
1261 addr = saddr;
1262 cnt = 16;
1263
1264 if (cmd_match (cmd, "-")) {
1265 st_cmd_u_to (cmd, sim, addr);
1266 return;
1267 }
1268
1269 if (cmd_match_uint32 (cmd, &addr)) {
1270 cmd_match_uint32 (cmd, &cnt);
1271 }
1272
1273 if (!cmd_match_end (cmd)) {
1274 return;
1275 }
1276
1277 for (i = 0; i < cnt; i++) {
1278 e68_dasm_mem (sim->cpu, &op, addr);
1279 st_dasm_str (str, &op, 1);
1280
1281 pce_printf ("%08lX %s\n", addr, str);
1282
1283 addr += 2 * op.irn;
1284 }
1285
1286 saddr = addr;
1287}
1288
1289int st_cmd (atari_st_t *sim, cmd_t *cmd)
1290{
1291 if (sim->trm != NULL) {
1292 trm_check (sim->trm);
1293 }
1294
1295 if (cmd_match (cmd, "b")) {
1296 cmd_do_b (cmd, &sim->bps);
1297 }
1298 else if (cmd_match (cmd, "c")) {
1299 st_cmd_c (cmd, sim);
1300 }
1301 else if (cmd_match (cmd, "g")) {
1302 st_cmd_g (cmd, sim);
1303 }
1304 else if (cmd_match (cmd, "halt")) {
1305 st_cmd_halt (cmd, sim);
1306 }
1307 else if (cmd_match (cmd, "hm")) {
1308 st_cmd_hm (cmd);
1309 }
1310 else if (cmd_match (cmd, "p")) {
1311 st_cmd_p (cmd, sim);
1312 }
1313 else if (cmd_match (cmd, "n")) {
1314 st_cmd_n (cmd, sim);
1315 }
1316 else if (cmd_match (cmd, "reset")) {
1317 st_cmd_reset (cmd, sim);
1318 }
1319 else if (cmd_match (cmd, "rte")) {
1320 st_cmd_rte (cmd, sim);
1321 }
1322 else if (cmd_match (cmd, "r")) {
1323 st_cmd_r (cmd, sim);
1324 }
1325 else if (cmd_match (cmd, "s")) {
1326 st_cmd_s (cmd, sim);
1327 }
1328 else if (cmd_match (cmd, "t")) {
1329 st_cmd_t (cmd, sim);
1330 }
1331 else if (cmd_match (cmd, "u")) {
1332 st_cmd_u (cmd, sim);
1333 }
1334 else {
1335 return (1);
1336 }
1337
1338 if (sim->trm != NULL) {
1339 trm_set_msg_trm (sim->trm, "term.release", "1");
1340 }
1341
1342 return (0);
1343}
1344
1345void st_cmd_init (atari_st_t *sim, monitor_t *mon)
1346{
1347 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0]));
1348 mon_cmd_add_bp (mon);
1349
1350 sim->cpu->log_ext = sim;
1351 sim->cpu->log_opcode = NULL;
1352 sim->cpu->log_undef = NULL;
1353 sim->cpu->log_exception = st_log_exception;
1354 sim->cpu->log_mem = NULL;
1355}