fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/sim405/cmd_ppc.c *
7 * Created: 2004-06-01 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2018 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#include "main.h"
30#include "cmd_ppc.h"
31#include "hook.h"
32#include "sim405.h"
33
34#include <stdio.h>
35
36#include <chipset/ppc405/uic.h>
37
38#include <cpu/ppc405/ppc405.h>
39
40#include <lib/cmd.h>
41#include <lib/console.h>
42#include <lib/monitor.h>
43#include <lib/sysdep.h>
44
45
46static mon_cmd_t par_cmd[] = {
47 { "c", "[cnt]", "clock" },
48 { "gb", "[addr...]", "run with breakpoints" },
49 { "g", "", "run" },
50 { "key", "[val...]", "send keycodes to the serial console" },
51 { "p", "[cnt]", "execute cnt instructions, skip calls [1]" },
52 { "rfi", "", "execute to next rfi or rfci" },
53 { "r", "reg [val]", "get or set a register" },
54 { "s", "[what]", "print status (mem|ppc|spr|time|uart0|uart1|uic)" },
55 { "tlb", "l [first [count]]", "list TLB entries" },
56 { "tlb", "s addr", "search the TLB" },
57 { "t", "[cnt]", "execute cnt instructions [1]" },
58 { "u", "[addr [cnt]]", "disassemble" },
59 { "x", "[c|r|v]", "set the translation mode (cpu, real, virtual)" }
60};
61
62
63void ppc_disasm_str (char *dst, p405_disasm_t *op)
64{
65 switch (op->argn) {
66 case 0:
67 sprintf (dst, "%08lX %s", (unsigned long) op->ir, op->op);
68 break;
69
70 case 1:
71 sprintf (dst, "%08lX %-8s %s",
72 (unsigned long) op->ir, op->op, op->arg1
73 );
74 break;
75
76 case 2:
77 sprintf (dst, "%08lX %-8s %s, %s",
78 (unsigned long) op->ir, op->op, op->arg1, op->arg2
79 );
80 break;
81
82 case 3:
83 sprintf (dst, "%08lX %-8s %s, %s, %s",
84 (unsigned long) op->ir, op->op,
85 op->arg1, op->arg2, op->arg3
86 );
87 break;
88
89 case 4:
90 sprintf (dst, "%08lX %-8s %s, %s, %s, %s",
91 (unsigned long) op->ir, op->op,
92 op->arg1, op->arg2, op->arg3, op->arg4
93 );
94 break;
95
96 case 5:
97 sprintf (dst, "%08lX %-8s %s, %s, %s, %s, %s",
98 (unsigned long) op->ir, op->op,
99 op->arg1, op->arg2, op->arg3, op->arg4, op->arg5
100 );
101 break;
102
103 default:
104 strcpy (dst, "---");
105 break;
106 }
107}
108
109static
110void prt_tlb_entry (p405_tlbe_t *ent, unsigned idx)
111{
112 pce_printf (
113 "%02x: %08lx -> %08lx %06lx V%c E%c R%c W%c X%c Z=%X TID=%02x %08lx",
114 idx,
115 (unsigned long) p405_get_tlbe_epn (ent),
116 (unsigned long) p405_get_tlbe_rpn (ent),
117 (unsigned long) p405_get_tlbe_sizeb (ent),
118 p405_get_tlbe_v (ent) ? '+' : '-',
119 p405_get_tlbe_e (ent) ? '+' : '-',
120 p405_get_tlbe_v (ent) ? '+' : '-',
121 p405_get_tlbe_wr (ent) ? '+' : '-',
122 p405_get_tlbe_ex (ent) ? '+' : '-',
123 (unsigned) p405_get_tlbe_zsel (ent),
124 (unsigned) p405_get_tlbe_tid (ent),
125 (unsigned long) ent->mask
126 );
127}
128
129void s405_prt_state_ppc (sim405_t *sim)
130{
131 unsigned i;
132 unsigned long long opcnt, clkcnt;
133 unsigned long delay;
134 double t, efrq;
135 p405_t *c;
136 p405_disasm_t op;
137 char str[256];
138
139 pce_prt_sep ("PPC405");
140
141 c = sim->ppc;
142
143 opcnt = p405_get_opcnt (c);
144 clkcnt = p405_get_clkcnt (c);
145 delay = p405_get_delay (c);
146
147 t = (double) (clock() - sim->real_clk) / CLOCKS_PER_SEC;
148 efrq = (t < 0.001) ? 0.0 : (clkcnt / (1000.0 * 1000.0 * t));
149
150 pce_printf (
151 "CLK=%llx OP=%llx DLY=%lx CPI=%.4f TIME=%.4f EFRQ=%.6f\n",
152 clkcnt, opcnt, delay,
153 (opcnt > 0) ? ((double) (clkcnt + delay) / (double) opcnt) : 1.0,
154 t, efrq
155 );
156
157 pce_printf (
158 " MSR=%08lX XER=%08lX CR=%08lX XER=[%c%c%c]"
159 " CR0=[%c%c%c%c]\n",
160 (unsigned long) p405_get_msr (c),
161 (unsigned long) p405_get_xer (c),
162 (unsigned long) p405_get_cr (c),
163 (p405_get_xer_so (c)) ? 'S' : '-',
164 (p405_get_xer_ov (c)) ? 'O' : '-',
165 (p405_get_xer_ca (c)) ? 'C' : '-',
166 (p405_get_cr_lt (c, 0)) ? 'L' : '-',
167 (p405_get_cr_gt (c, 0)) ? 'G' : '-',
168 (p405_get_cr_eq (c, 0)) ? 'E' : '-',
169 (p405_get_cr_so (c, 0)) ? 'O' : '-'
170 );
171
172 pce_printf (
173 " PC=%08lX CTR=%08lX LR=%08lX PID=%08lX ZPR=%08lX\n",
174 (unsigned long) p405_get_pc (c),
175 (unsigned long) p405_get_ctr (c),
176 (unsigned long) p405_get_lr (c),
177 (unsigned long) p405_get_pid (c),
178 (unsigned long) p405_get_zpr (c)
179 );
180
181 pce_printf (
182 "SRR0=%08lX SRR1=%08lX SRR2=%08lX SRR3=%08lX ESR=%08lX\n",
183 (unsigned long) p405_get_srr (c, 0),
184 (unsigned long) p405_get_srr (c, 1),
185 (unsigned long) p405_get_srr (c, 2),
186 (unsigned long) p405_get_srr (c, 3),
187 (unsigned long) p405_get_esr (c)
188 );
189
190 for (i = 0; i < 8; i++) {
191 pce_printf (
192 " R%02u=%08lX R%02u=%08lX R%02u=%08lX R%02u=%08lX"
193 " SP%u=%08lX\n",
194 i + 0, (unsigned long) p405_get_gpr (c, i + 0),
195 i + 8, (unsigned long) p405_get_gpr (c, i + 8),
196 i + 16, (unsigned long) p405_get_gpr (c, i + 16),
197 i + 24, (unsigned long) p405_get_gpr (c, i + 24),
198 i, (unsigned long) p405_get_sprg (c, i)
199 );
200 }
201
202 p405_disasm_mem (c, &op, p405_get_pc (c), par_xlat | P405_XLAT_EXEC);
203 ppc_disasm_str (str, &op);
204
205 pce_printf ("%08lX %s\n", (unsigned long) p405_get_pc (c), str);
206}
207
208void s405_prt_state_spr (p405_t *c)
209{
210 uint32_t msr;
211
212 pce_prt_sep ("PPC405 SPR");
213
214 msr = p405_get_msr (c);
215
216 pce_printf (
217 " MSR=%08lX [%s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n",
218 (unsigned long) msr,
219 (msr & P405_MSR_AP) ? "AP" : "ap",
220 (msr & P405_MSR_APE) ? "APE" : "ape",
221 (msr & P405_MSR_WE) ? "WE" : "we",
222 (msr & P405_MSR_CE) ? "CE" : "ce",
223 (msr & P405_MSR_EE) ? "EE" : "ee",
224 (msr & P405_MSR_PR) ? "PR" : "pr",
225 (msr & P405_MSR_FP) ? "FP" : "fp",
226 (msr & P405_MSR_ME) ? "ME" : "me",
227 (msr & P405_MSR_FE0) ? "FE0" : "fe0",
228 (msr & P405_MSR_DWE) ? "DWE" : "dwe",
229 (msr & P405_MSR_DE) ? "DE" : "de",
230 (msr & P405_MSR_FE0) ? "FE1" : "fe1",
231 (msr & P405_MSR_IR) ? "IR" : "ir",
232 (msr & P405_MSR_DR) ? "DR" : "dr"
233 );
234
235 pce_printf (
236 " PC=%08lX XER=%08lX CR=%08lX PID=%08lX ZPR=%08lX\n",
237 (unsigned long) p405_get_pc (c),
238 (unsigned long) p405_get_xer (c),
239 (unsigned long) p405_get_cr (c),
240 (unsigned long) p405_get_pid (c),
241 (unsigned long) p405_get_zpr (c)
242 );
243
244 pce_printf (
245 "SPG0=%08lX SRR0=%08lX LR=%08lX CTR=%08lX ESR=%08lX\n",
246 (unsigned long) p405_get_sprg (c, 0),
247 (unsigned long) p405_get_srr (c, 0),
248 (unsigned long) p405_get_lr (c),
249 (unsigned long) p405_get_ctr (c),
250 (unsigned long) p405_get_esr (c)
251 );
252
253 pce_printf (
254 "SPG1=%08lX SRR1=%08lX TBU=%08lX TBL=%08lX DEAR=%08lX\n",
255 (unsigned long) p405_get_sprg (c, 1),
256 (unsigned long) p405_get_srr (c, 1),
257 (unsigned long) p405_get_tbu (c),
258 (unsigned long) p405_get_tbl (c),
259 (unsigned long) p405_get_dear (c)
260 );
261
262 pce_printf ("SPG2=%08lX SRR2=%08lX EVPR=%08lX\n",
263 (unsigned long) p405_get_sprg (c, 2),
264 (unsigned long) p405_get_srr (c, 2),
265 (unsigned long) p405_get_evpr (c)
266 );
267
268 pce_printf (
269 "SPG3=%08lX SRR3=%08lX DCCR=%08lX DCWR=%08lX ICCR=%08lX\n",
270 (unsigned long) p405_get_sprg (c, 3),
271 (unsigned long) p405_get_srr (c, 3),
272 (unsigned long) p405_get_dccr (c),
273 (unsigned long) p405_get_dcwr (c),
274 (unsigned long) p405_get_iccr (c)
275 );
276
277 pce_printf ("SPG4=%08lX DBC0=%08lX PIT0=%08lX PIT1=%08lX\n",
278 (unsigned long) p405_get_sprg (c, 4),
279 (unsigned long) p405_get_dbcr0 (c),
280 (unsigned long) p405_get_pit (c, 0),
281 (unsigned long) p405_get_pit (c, 1)
282 );
283
284 pce_printf ("SPG5=%08lX DBC1=%08lX TCR=%08lX TSR=%08lX\n",
285 (unsigned long) p405_get_sprg (c, 5),
286 (unsigned long) p405_get_dbcr0 (c),
287 (unsigned long) p405_get_tcr (c),
288 (unsigned long) p405_get_tsr (c)
289 );
290
291 pce_printf ("SPG6=%08lX DBSR=%08lX\n",
292 (unsigned long) p405_get_sprg (c, 6),
293 (unsigned long) p405_get_dbsr (c)
294 );
295
296 pce_printf ("SPG7=%08lX\n",
297 (unsigned long) p405_get_sprg (c, 7)
298 );
299}
300
301void s405_prt_state_uic (p405_uic_t *uic)
302{
303 pce_prt_sep ("UIC");
304
305 pce_printf (
306 " L=%08lX N00=%08lX N08=%08lX N16=%08lX N24=%08lX\n",
307 (unsigned long) p405uic_get_levels (uic),
308 p405uic_get_int_cnt (uic, 0),
309 p405uic_get_int_cnt (uic, 8),
310 p405uic_get_int_cnt (uic, 16),
311 p405uic_get_int_cnt (uic, 24)
312 );
313 pce_printf (
314 " SR=%08lX N01=%08lX N09=%08lX N17=%08lX N25=%08lX\n",
315 (unsigned long) p405uic_get_sr (uic),
316 p405uic_get_int_cnt (uic, 1),
317 p405uic_get_int_cnt (uic, 9),
318 p405uic_get_int_cnt (uic, 17),
319 p405uic_get_int_cnt (uic, 25)
320 );
321 pce_printf (
322 " ER=%08lX N02=%08lX N10=%08lX N18=%08lX N26=%08lX\n",
323 (unsigned long) p405uic_get_er (uic),
324 p405uic_get_int_cnt (uic, 2),
325 p405uic_get_int_cnt (uic, 10),
326 p405uic_get_int_cnt (uic, 18),
327 p405uic_get_int_cnt (uic, 26)
328 );
329 pce_printf (
330 "MSR=%08lX N03=%08lX N11=%08lX N19=%08lX N27=%08lX\n",
331 (unsigned long) p405uic_get_msr (uic),
332 p405uic_get_int_cnt (uic, 3),
333 p405uic_get_int_cnt (uic, 11),
334 p405uic_get_int_cnt (uic, 19),
335 p405uic_get_int_cnt (uic, 27)
336 );
337 pce_printf (
338 " CR=%08lX N04=%08lX N12=%08lX N20=%08lX N28=%08lX\n",
339 (unsigned long) p405uic_get_cr (uic),
340 p405uic_get_int_cnt (uic, 4),
341 p405uic_get_int_cnt (uic, 12),
342 p405uic_get_int_cnt (uic, 20),
343 p405uic_get_int_cnt (uic, 28)
344 );
345 pce_printf (
346 " PR=%08lX N05=%08lX N13=%08lX N21=%08lX N29=%08lX\n",
347 (unsigned long) p405uic_get_pr (uic),
348 p405uic_get_int_cnt (uic, 5),
349 p405uic_get_int_cnt (uic, 13),
350 p405uic_get_int_cnt (uic, 21),
351 p405uic_get_int_cnt (uic, 29)
352 );
353 pce_printf (
354 " TR=%08lX N06=%08lX N14=%08lX N22=%08lX N30=%08lX\n",
355 (unsigned long) p405uic_get_tr (uic),
356 p405uic_get_int_cnt (uic, 6),
357 p405uic_get_int_cnt (uic, 14),
358 p405uic_get_int_cnt (uic, 22),
359 p405uic_get_int_cnt (uic, 30)
360 );
361 pce_printf (
362 "VCR=%08lX N07=%08lX N15=%08lX N23=%08lX N31=%08lX\n",
363 (unsigned long) p405uic_get_vcr (uic),
364 p405uic_get_int_cnt (uic, 7),
365 p405uic_get_int_cnt (uic, 15),
366 p405uic_get_int_cnt (uic, 23),
367 p405uic_get_int_cnt (uic, 31)
368 );
369 pce_printf (" VR=%08lX\n", (unsigned long) p405uic_get_vr (uic));
370}
371
372static
373void s405_print_state_uart (e8250_t *uart, unsigned long base)
374{
375 char p;
376 unsigned char lsr, msr;
377
378 lsr = e8250_get_lsr (uart);
379 msr = e8250_get_msr (uart);
380
381 switch (e8250_get_parity (uart)) {
382 case E8250_PARITY_N:
383 p = 'N';
384 break;
385
386 case E8250_PARITY_E:
387 p = 'E';
388 break;
389
390 case E8250_PARITY_O:
391 p = 'O';
392 break;
393
394 case E8250_PARITY_M:
395 p = 'M';
396 break;
397
398 case E8250_PARITY_S:
399 p = 'S';
400 break;
401
402 default:
403 p = '?';
404 break;
405 }
406
407 pce_prt_sep ("8250-UART");
408
409 pce_printf (
410 "IO=%08lX %lu %u%c%u DTR=%d RTS=%d DSR=%d CTS=%d DCD=%d RI=%d\n"
411 "TxD=%02X%c RxD=%02X%c SCR=%02X DIV=%04X\n"
412 "IER=%02X IIR=%02X LCR=%02X LSR=%02X MCR=%02X MSR=%02X\n",
413 base,
414 e8250_get_bps (uart), e8250_get_databits (uart), p,
415 e8250_get_stopbits (uart),
416 e8250_get_dtr (uart), e8250_get_rts (uart),
417 (msr & E8250_MSR_DSR) != 0,
418 (msr & E8250_MSR_CTS) != 0,
419 (msr & E8250_MSR_DCD) != 0,
420 (msr & E8250_MSR_RI) != 0,
421 uart->txd, (lsr & E8250_LSR_TBE) ? ' ' : '*',
422 uart->rxd, (lsr & E8250_LSR_RRD) ? '*' : ' ',
423 uart->scratch, uart->divisor,
424 uart->ier, uart->iir, uart->lcr, lsr, uart->mcr, msr
425 );
426}
427
428static
429void s405_print_state_time (sim405_t *sim)
430{
431 p405_t *c;
432 unsigned long tcr, tsr, tbl, msk, rem;
433
434 c = sim->ppc;
435
436 tcr = p405_get_tcr (c);
437 tsr = p405_get_tsr (c);
438 tbl = p405_get_tbl (c);
439
440 msk = 0x100UL << ((tcr >> 22) & 0x0c);
441 rem = msk - (tbl & (msk - 1)) + ((tbl & msk) ? msk : 0);
442
443 pce_prt_sep ("TIME");
444
445 pce_printf ("TBU=%08lX TBL=%08lX\n",
446 (unsigned long) p405_get_tbu (c),
447 tbl
448 );
449
450 pce_printf ("TCR=%08lX [PIE=%d ARE=%d FIE=%d FP=%X WIE=%d]\n",
451 tcr,
452 (tcr & P405_TCR_PIE) != 0,
453 (tcr & P405_TCR_ARE) != 0,
454 (tcr & P405_TCR_FIE) != 0,
455 (unsigned) ((tcr >> 24) & 3),
456 (tcr & P405_TCR_WIE) != 0
457 );
458
459 pce_printf ("TSR=%08lX [PIS=%d FIS=%d WIS=%d]\n",
460 tsr,
461 (tsr & P405_TSR_PIS) != 0,
462 (tsr & P405_TSR_FIS) != 0,
463 (tsr & P405_TSR_WIS) != 0
464 );
465
466 pce_printf ("PIT VAL=%08lX REL=%08lX ARE=%d PIE=%d PIS=%d\n",
467 (unsigned long) (p405_get_pit (c, 0)),
468 (unsigned long) (p405_get_pit (c, 1)),
469 (tcr & P405_TCR_ARE) != 0,
470 (tcr & P405_TCR_PIE) != 0,
471 (tsr & P405_TSR_PIS) != 0
472 );
473
474 pce_printf ("FIT REM=%08lX TBL=%08lx MSK=%06lX FIE=%d FIS=%d\n",
475 rem,
476 tbl,
477 msk,
478 (tcr & P405_TCR_FIE) != 0,
479 (tsr & P405_TSR_FIS) != 0
480 );
481}
482
483void s405_prt_state_mem (sim405_t *sim)
484{
485 FILE *fp;
486
487 pce_prt_sep ("PPC MEM");
488
489 mem_prt_state (sim->mem, pce_get_fp_out());
490
491 fp = pce_get_redir_out();
492 if (fp != NULL) {
493 mem_prt_state (sim->mem, fp);
494 }
495}
496
497void prt_state (sim405_t *sim, const char *str)
498{
499 cmd_t cmd;
500
501 cmd_set_str (&cmd, str);
502
503 if (cmd_match_eol (&cmd)) {
504 return;
505 }
506
507 while (!cmd_match_eol (&cmd)) {
508 if (cmd_match (&cmd, "ppc") || cmd_match (&cmd, "cpu")) {
509 s405_prt_state_ppc (sim);
510 }
511 else if (cmd_match (&cmd, "spr")) {
512 s405_prt_state_spr (sim->ppc);
513 }
514 else if (cmd_match (&cmd, "uic")) {
515 s405_prt_state_uic (&sim->uic);
516 }
517 else if (cmd_match (&cmd, "uart0")) {
518 if (sim->serport[0] != NULL) {
519 s405_print_state_uart (&sim->serport[0]->uart, sim->serport[0]->io);
520 }
521 }
522 else if (cmd_match (&cmd, "uart1")) {
523 if (sim->serport[1] != NULL) {
524 s405_print_state_uart (&sim->serport[1]->uart, sim->serport[1]->io);
525 }
526 }
527 else if (cmd_match (&cmd, "time")) {
528 s405_print_state_time (sim);
529 }
530 else if (cmd_match (&cmd, "mem")) {
531 s405_prt_state_mem (sim);
532 }
533 else {
534 pce_printf ("unknown component (%s)\n",
535 cmd_get_str (&cmd)
536 );
537 return;
538 }
539 }
540}
541
542
543static
544int ppc_check_break (sim405_t *sim)
545{
546 if (bps_check (&sim->bps, 0, p405_get_pc (sim->ppc), stdout)) {
547 return (1);
548 }
549
550 if (sim->brk) {
551 return (1);
552 }
553
554 return (0);
555}
556
557static
558void ppc_exec (sim405_t *sim)
559{
560 unsigned long long old;
561
562 old = p405_get_opcnt (sim->ppc);
563
564 while (p405_get_opcnt (sim->ppc) == old) {
565 s405_clock (sim, 1);
566 }
567}
568
569static
570int ppc_exec_to (sim405_t *sim, unsigned long addr)
571{
572 while (p405_get_pc (sim->ppc) != addr) {
573 s405_clock (sim, 1);
574
575 if (sim->brk) {
576 return (1);
577 }
578 }
579
580 return (0);
581}
582
583static
584int ppc_exec_off (sim405_t *sim, unsigned long addr)
585{
586 while (p405_get_pc (sim->ppc) == addr) {
587 s405_clock (sim, 1);
588
589 if (sim->brk) {
590 return (1);
591 }
592 }
593
594 return (0);
595}
596
597void ppc_run (sim405_t *sim)
598{
599 pce_start (&sim->brk);
600 s405_clock_discontinuity (sim);
601
602 while (1) {
603 s405_clock (sim, 64);
604
605 if (sim->brk) {
606 break;
607 }
608 }
609
610 pce_stop();
611}
612
613
614static
615int s405_trap (sim405_t *sim, unsigned ofs)
616{
617 int log;
618 char *name;
619
620 log = 0;
621
622 switch (ofs) {
623 case 0x0300:
624 name = "data store";
625 break;
626
627 case 0x0400:
628 name = "instruction store";
629 break;
630
631 case 0x0500:
632 name = "external interrupt";
633 break;
634
635 case 0x0700:
636 name = "program";
637 if (sim->ppc->exception_esr & P405_ESR_PIL) {
638 log = 0;
639 }
640 else if (sim->ppc->exception_esr & P405_ESR_PTR) {
641 log = 1;
642 }
643 break;
644
645 case 0x0800:
646 name = "fpu unavailable";
647 log = 1;
648 break;
649
650 case 0x0c00:
651 name = "system call";
652 break;
653
654 case 0x1000:
655 name = "PIT";
656 break;
657
658 case 0x1010:
659 name = "FIT";
660 break;
661
662 case 0x1100:
663 name = "TLB miss data";
664 break;
665
666 case 0x1200:
667 name = "TLB miss instruction";
668 break;
669
670 default:
671 name = "unknown";
672 log = 1;
673 break;
674 }
675
676 if (log) {
677 pce_log (MSG_DEB, "%08lX: ESR=%08lX DEAR=%08lX IR=%0lX OFS=%04X %s\n",
678 (unsigned long) p405_get_pc (sim->ppc),
679 (unsigned long) sim->ppc->exception_esr,
680 (unsigned long) sim->ppc->exception_dear,
681 (unsigned long) sim->ppc->ir,
682 ofs, name
683 );
684 }
685
686 return (0);
687}
688
689static
690void ppc_log_undef (void *ext, unsigned long ir)
691{
692 unsigned op1, op2;
693 sim405_t *sim;
694
695 sim = (sim405_t *) ext;
696
697 op1 = (ir >> 26) & 0x3f;
698 op2 = (ir >> 1) & 0x3ff;
699
700 if (op1 == 4) {
701 /* various multiply-accumulate instructions */
702 return;
703 }
704
705 pce_log (MSG_DEB,
706 "%08lX: undefined operation [%08lX] op1=%02X op2=%03X\n",
707 (unsigned long) p405_get_pc (sim->ppc), ir, op1, op2
708 );
709
710 /* s405_break (sim, PCE_BRK_STOP); */
711}
712
713#if 0
714static
715void ppc_log_mem (void *ext, unsigned mode,
716 unsigned long raddr, unsigned long vaddr, unsigned long val)
717{
718 sim405_t *sim;
719
720 sim = (sim405_t *) ext;
721
722 if ((raddr >= 0xe0000000UL) && (raddr < 0xef600000UL)) {
723 pce_log (MSG_DEB, "mem: 0x%08lx 0x%08lx %02x\n", raddr, val, mode);
724 }
725}
726#endif
727
728static
729void do_c (cmd_t *cmd, sim405_t *sim)
730{
731 unsigned long cnt;
732
733 cnt = 1;
734
735 cmd_match_uint32 (cmd, &cnt);
736
737 if (!cmd_match_end (cmd)) {
738 return;
739 }
740
741 while (cnt > 0) {
742 s405_clock (sim, 1);
743 cnt -= 1;
744 }
745
746 s405_prt_state_ppc (sim);
747}
748
749static
750void do_g_b (cmd_t *cmd, sim405_t *sim)
751{
752 unsigned long addr;
753 breakpoint_t *bp;
754
755 while (cmd_match_uint32 (cmd, &addr)) {
756 bp = bp_addr_new (addr);
757 bps_bp_add (&sim->bps, bp);
758 }
759
760 if (!cmd_match_end (cmd)) {
761 return;
762 }
763
764 pce_start (&sim->brk);
765 s405_clock_discontinuity (sim);
766
767 while (1) {
768 ppc_exec (sim);
769
770 if (ppc_check_break (sim)) {
771 break;
772 }
773 }
774
775 pce_stop();
776}
777
778static
779void do_g (cmd_t *cmd, sim405_t *sim)
780{
781 if (cmd_match (cmd, "b")) {
782 do_g_b (cmd, sim);
783 return;
784 }
785
786 if (!cmd_match_end (cmd)) {
787 return;
788 }
789
790 ppc_run (sim);
791}
792
793static
794void do_key (cmd_t *cmd, sim405_t *sim)
795{
796 unsigned short c;
797
798 while (cmd_match_uint16 (cmd, &c)) {
799 s405_set_keycode (sim, c);
800 }
801
802 if (!cmd_match_end (cmd)) {
803 return;
804 }
805}
806
807static
808void do_p (cmd_t *cmd, sim405_t *sim)
809{
810 unsigned long cnt;
811 p405_disasm_t dis;
812
813 cnt = 1;
814
815 cmd_match_uint32 (cmd, &cnt);
816
817 if (!cmd_match_end (cmd)) {
818 return;
819 }
820
821 pce_start (&sim->brk);
822 s405_clock_discontinuity (sim);
823
824 while (cnt > 0) {
825 p405_disasm_mem (sim->ppc, &dis, p405_get_pc (sim->ppc), P405_XLAT_CPU | P405_XLAT_EXEC);
826
827 if (dis.flags & P405_DFLAG_CALL) {
828 if (ppc_exec_to (sim, p405_get_pc (sim->ppc) + 4)) {
829 break;
830 }
831 }
832 else {
833 uint32_t msr;
834
835 msr = p405_get_msr (sim->ppc);
836
837 if (ppc_exec_off (sim, p405_get_pc (sim->ppc))) {
838 break;
839 }
840
841 if (msr & P405_MSR_PR) {
842 /* check if exception occured */
843 while ((p405_get_msr (sim->ppc) & P405_MSR_PR) == 0) {
844 s405_clock (sim, 1);
845
846 if (sim->brk) {
847 break;
848 }
849 }
850 }
851 }
852
853 cnt -= 1;
854 }
855
856 pce_stop();
857
858 s405_prt_state_ppc (sim);
859}
860
861static
862void do_rfi (cmd_t *cmd, sim405_t *sim)
863{
864 p405_disasm_t dis;
865
866 if (!cmd_match_end (cmd)) {
867 return;
868 }
869
870 pce_start (&sim->brk);
871 s405_clock_discontinuity (sim);
872
873 while (1) {
874 p405_disasm_mem (sim->ppc, &dis, p405_get_pc (sim->ppc),
875 P405_XLAT_CPU | P405_XLAT_EXEC
876 );
877
878 if (ppc_exec_off (sim, p405_get_pc (sim->ppc))) {
879 break;
880 }
881
882 if (dis.flags & P405_DFLAG_RFI) {
883 break;
884 }
885 }
886
887 pce_stop();
888
889 s405_prt_state_ppc (sim);
890}
891
892static
893void do_r (cmd_t *cmd, sim405_t *sim)
894{
895 unsigned long val;
896 char sym[256];
897
898 if (cmd_match_eol (cmd)) {
899 s405_prt_state_ppc (sim);
900 return;
901 }
902
903 if (!cmd_match_ident (cmd, sym, 256)) {
904 pce_printf ("missing register\n");
905 return;
906 }
907
908 if (p405_get_reg (sim->ppc, sym, &val)) {
909 pce_printf ("bad register (%s)\n", sym);
910 return;
911 }
912
913 if (cmd_match_eol (cmd)) {
914 pce_printf ("%08lX\n", val);
915 return;
916 }
917
918 if (!cmd_match_uint32 (cmd, &val)) {
919 pce_printf ("missing value\n");
920 return;
921 }
922
923 if (!cmd_match_end (cmd)) {
924 return;
925 }
926
927 p405_set_reg (sim->ppc, sym, val);
928
929 s405_prt_state_ppc (sim);
930}
931
932static
933void do_s (cmd_t *cmd, sim405_t *sim)
934{
935 if (cmd_match_eol (cmd)) {
936 s405_prt_state_ppc (sim);
937 return;
938 }
939
940 prt_state (sim, cmd_get_str (cmd));
941}
942
943static
944void do_tlb_l (cmd_t *cmd, sim405_t *sim)
945{
946 unsigned long i, n, max;
947 p405_tlbe_t *ent;
948
949 i = 0;
950 n = p405_get_tlb_entry_cnt (sim->ppc);
951
952 max = n;
953
954 if (cmd_match_uint32 (cmd, &i)) {
955 cmd_match_uint32 (cmd, &n);
956 }
957
958 if (!cmd_match_end (cmd)) {
959 return;
960 }
961
962 i = i % max;
963
964 while (n > 0) {
965 ent = p405_get_tlb_entry_idx (sim->ppc, i);
966
967 if (ent != NULL) {
968 prt_tlb_entry (ent, i);
969 fputs ("\n", stdout);
970 }
971
972 i = (i + 1) % max;
973 n -= 1;
974 }
975}
976
977static
978void do_tlb_s (cmd_t *cmd, sim405_t *sim)
979{
980 unsigned long addr;
981 unsigned idx;
982 p405_tlbe_t *ent;
983
984 if (!cmd_match_uint32 (cmd, &addr)) {
985 cmd_error (cmd, "expecting address");
986 return;
987 }
988
989 if (!cmd_match_end (cmd)) {
990 return;
991 }
992
993 idx = p405_get_tlb_index (sim->ppc, addr);
994 ent = p405_get_tlb_entry_idx (sim->ppc, idx);
995
996 if (ent == NULL) {
997 pce_printf ("no match\n");
998 }
999 else {
1000 prt_tlb_entry (ent, idx);
1001 pce_puts ("\n");
1002 }
1003}
1004
1005static
1006void do_tlb (cmd_t *cmd, sim405_t *sim)
1007{
1008 if (cmd_match (cmd, "l")) {
1009 do_tlb_l (cmd, sim);
1010 }
1011 else if (cmd_match (cmd, "s")) {
1012 do_tlb_s (cmd, sim);
1013 }
1014 else {
1015 cmd_error (cmd, "unknown tlb command");
1016 }
1017}
1018
1019static
1020void do_t (cmd_t *cmd, sim405_t *sim)
1021{
1022 unsigned long i, n;
1023
1024 n = 1;
1025
1026 cmd_match_uint32 (cmd, &n);
1027
1028 if (!cmd_match_end (cmd)) {
1029 return;
1030 }
1031
1032 pce_start (&sim->brk);
1033 s405_clock_discontinuity (sim);
1034
1035 for (i = 0; i < n; i++) {
1036 ppc_exec (sim);
1037 }
1038
1039 pce_stop();
1040
1041 s405_prt_state_ppc (sim);
1042}
1043
1044static
1045void do_u (cmd_t *cmd, sim405_t *sim)
1046{
1047 unsigned i;
1048 int to;
1049 unsigned long addr, cnt;
1050 static unsigned int first = 1;
1051 static unsigned long saddr = 0;
1052 p405_disasm_t op;
1053 char str[256];
1054
1055 if (first) {
1056 first = 0;
1057 saddr = p405_get_pc (sim->ppc);
1058 }
1059
1060 to = 0;
1061 addr = saddr;
1062 cnt = 16;
1063
1064 if (cmd_match (cmd, "-")) {
1065 to = 1;
1066 }
1067
1068 if (cmd_match_uint32 (cmd, &addr)) {
1069 cmd_match_uint32 (cmd, &cnt);
1070 }
1071
1072 if (!cmd_match_end (cmd)) {
1073 return;
1074 }
1075
1076 if (to) {
1077 addr -= 4 * (cnt - 1);
1078 }
1079
1080 for (i = 0; i < cnt; i++) {
1081 p405_disasm_mem (sim->ppc, &op, addr, par_xlat | P405_XLAT_EXEC);
1082 ppc_disasm_str (str, &op);
1083
1084 pce_printf ("%08lX %s\n", addr, str);
1085
1086 addr += 4;
1087 }
1088
1089 saddr = addr;
1090}
1091
1092static
1093void do_x (cmd_t *cmd, sim405_t *sim)
1094{
1095 unsigned xlat;
1096
1097 if (cmd_match_eol (cmd)) {
1098 switch (par_xlat) {
1099 case P405_XLAT_CPU:
1100 pce_printf ("xlat cpu\n");
1101 break;
1102
1103 case P405_XLAT_REAL:
1104 pce_printf ("xlat real\n");
1105 break;
1106
1107 case P405_XLAT_VIRTUAL:
1108 pce_printf ("xlat virtual\n");
1109 break;
1110
1111 default:
1112 pce_printf ("xlat unknown\n");
1113 break;
1114 }
1115
1116 return;
1117 }
1118
1119 if (cmd_match (cmd, "c")) {
1120 xlat = P405_XLAT_CPU;
1121 }
1122 else if (cmd_match (cmd, "r")) {
1123 xlat = P405_XLAT_REAL;
1124 }
1125 else if (cmd_match (cmd, "v")) {
1126 xlat = P405_XLAT_VIRTUAL;
1127 }
1128 else {
1129 cmd_error (cmd, "unknown translation type");
1130 return;
1131 }
1132
1133 if (!cmd_match_end (cmd)) {
1134 return;
1135 }
1136
1137 par_xlat = xlat;
1138}
1139
1140int ppc_do_cmd (sim405_t *sim, cmd_t *cmd)
1141{
1142 if (cmd_match (cmd, "b")) {
1143 cmd_do_b (cmd, &sim->bps);
1144 }
1145 else if (cmd_match (cmd, "c")) {
1146 do_c (cmd, sim);
1147 }
1148 else if (cmd_match (cmd, "g")) {
1149 do_g (cmd, sim);
1150 }
1151 else if (cmd_match (cmd, "key")) {
1152 do_key (cmd, sim);
1153 }
1154 else if (cmd_match (cmd, "p")) {
1155 do_p (cmd, sim);
1156 }
1157 else if (cmd_match (cmd, "rfi")) {
1158 do_rfi (cmd, sim);
1159 }
1160 else if (cmd_match (cmd, "r")) {
1161 do_r (cmd, sim);
1162 }
1163 else if (cmd_match (cmd, "s")) {
1164 do_s (cmd, sim);
1165 }
1166 else if (cmd_match (cmd, "tlb")) {
1167 do_tlb (cmd, sim);
1168 }
1169 else if (cmd_match (cmd, "t")) {
1170 do_t (cmd, sim);
1171 }
1172 else if (cmd_match (cmd, "u")) {
1173 do_u (cmd, sim);
1174 }
1175 else if (cmd_match (cmd, "x")) {
1176 do_x (cmd, sim);
1177 }
1178 else {
1179 return (1);
1180 }
1181
1182 return (0);
1183}
1184
1185void ppc_cmd_init (sim405_t *sim, monitor_t *mon)
1186{
1187 mon_cmd_add (mon, par_cmd, sizeof (par_cmd) / sizeof (par_cmd[0]));
1188 mon_cmd_add_bp (mon);
1189
1190 sim->ppc->log_ext = sim;
1191 sim->ppc->log_opcode = NULL;
1192 sim->ppc->log_undef = &ppc_log_undef;
1193 sim->ppc->log_mem = NULL;
1194
1195 p405_set_hook_fct (sim->ppc, sim, s405_hook);
1196 p405_set_trap_fct (sim->ppc, sim, s405_trap);
1197}