dec_prom.cc Source File

Back to the index.

dec_prom.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: DECstation PROM emulation
29  *
30  * Implementation note: Remember that only the lowest 32 bits of GPRs are
31  * actually valid when using dyntrans with e.g. R3000 CPUs.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <sys/resource.h>
40 
41 #include "console.h"
42 #include "cpu.h"
43 #include "cpu_mips.h"
44 #include "diskimage.h"
45 #include "machine.h"
46 #include "machine_pmax.h"
47 #include "memory.h"
48 #include "misc.h"
49 
50 #include "thirdparty/dec_prom.h"
51 #include "thirdparty/dec_5100.h"
52 #include "thirdparty/dec_kn01.h"
53 #include "thirdparty/dec_kn02.h"
54 #include "thirdparty/dec_kn03.h"
55 
56 
57 extern int quiet_mode;
58 
59 
60 /*
61  * mem_readchar():
62  *
63  * Reads a byte from emulated RAM, using a MIPS register as a base address.
64  * (Helper function.)
65  */
66 static unsigned char mem_readchar(struct cpu *cpu, int regbase, int offset)
67 {
68  unsigned char ch;
69  cpu->memory_rw(cpu, cpu->mem, (int32_t)cpu->cd.mips.gpr[regbase] +
70  offset, &ch, sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
71  return ch;
72 }
73 
74 
75 /*
76  * dec_jumptable_func():
77  *
78  * The jumptable is located at the beginning of the PROM, at 0xbfc00000 + i*8,
79  * where i is the decimal function number. Many of these can be converted to
80  * an identical callback function.
81  *
82  * Return value is non-zero if the vector number was converted into a callback
83  * function number, otherwise 0.
84  *
85  * Vector (dec) Function
86  * 0x0 0 reset()
87  * 0x10 2 restart()
88  * 0x18 3 reinit()
89  * 0x30 6 open()
90  * 0x38 7 read()
91  * 0x58 11 lseek()
92  * 0x68 13 putchar()
93  * 0x88 17 printf()
94  * 0x108 33 getenv2()
95  */
96 int dec_jumptable_func(struct cpu *cpu, int vector)
97 {
98  int i;
99  static int file_opened = 0;
100  static int current_file_offset = 0;
101 
102  switch (vector) {
103  case 0x0: /* reset() */
104  /* TODO */
106  cpu->running = 0;
107  break;
108  case 0x10: /* restart() */
109  /* TODO */
111  cpu->running = 0;
112  break;
113  case 0x18: /* reinit() */
114  /* TODO */
116  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
117  break;
118  case 0x30: /* open() */
119  /*
120  * TODO: This is just a hack to allow Sprite/pmax' bootblock
121  * code to load /vmsprite. The filename argument (in A0)
122  * is ignored, and a file handle value of 1 is returned.
123  */
124  if (file_opened) {
125  fatal("\ndec_jumptable_func(): opening more than one "
126  "file isn't supported yet.\n");
127  cpu->running = 0;
128  }
129  file_opened = 1;
130  cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
131  break;
132  case 0x38: /* read(handle, ptr, length) */
133  cpu->cd.mips.gpr[MIPS_GPR_V0] = (uint64_t) -1;
134  if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
135  int disk_id = diskimage_bootdev(cpu->machine, NULL);
136  int res;
137  unsigned char *tmp_buf;
138 
139  CHECK_ALLOCATION(tmp_buf = (unsigned char *)
140  malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]));
141 
142  res = diskimage_access(cpu->machine, disk_id,
143  DISKIMAGE_SCSI, 0, current_file_offset, tmp_buf,
144  cpu->cd.mips.gpr[MIPS_GPR_A2]);
145 
146  /* If the transfer was successful, transfer the data
147  to emulated memory: */
148  if (res) {
149  uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
150  store_buf(cpu, dst, (char *)tmp_buf,
151  cpu->cd.mips.gpr[MIPS_GPR_A2]);
152  cpu->cd.mips.gpr[MIPS_GPR_V0] =
153  cpu->cd.mips.gpr[MIPS_GPR_A2];
154  current_file_offset +=
155  cpu->cd.mips.gpr[MIPS_GPR_A2];
156  }
157 
158  free(tmp_buf);
159  }
160  break;
161  case 0x58: /* lseek(handle, offset[, whence]) */
162  /* TODO */
163  if (cpu->cd.mips.gpr[MIPS_GPR_A2] == 0)
164  current_file_offset = cpu->cd.mips.gpr[MIPS_GPR_A1];
165  else
166  fatal("WARNING! Unimplemented whence in "
167  "dec_jumptable_func()\n");
168  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
169  break;
170  case 0x68: /* putchar() */
172  cpu->cd.mips.gpr[MIPS_GPR_A0]);
173  break;
174  case 0x88: /* printf() */
175  return 0x30;
176  case 0x108: /* getenv2() */
177  return 0x64;
178  default:
179  cpu_register_dump(cpu->machine, cpu, 1, 0x1);
180  printf("a0 points to: ");
181  for (i=0; i<40; i++) {
182  unsigned char ch = '\0';
183  cpu->memory_rw(cpu, cpu->mem,
184  (int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch,
185  sizeof(ch), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
186  if (ch >= ' ' && ch < 126)
187  printf("%c", ch);
188  else
189  printf("[%02x]", ch);
190  }
191  printf("\n");
192  fatal("PROM emulation: unimplemented JUMP TABLE vector "
193  "0x%x (decimal function %i)\n", vector, vector/8);
194  cpu->running = 0;
195  }
196 
197  return 0;
198 }
199 
200 
201 /*
202  * decstation_prom_emul():
203  *
204  * DECstation PROM emulation.
205  *
206  * Callback functions:
207  * 0x0c strcmp()
208  * 0x14 strlen()
209  * 0x24 getchar()
210  * 0x28 gets()
211  * 0x2c puts()
212  * 0x30 printf()
213  * 0x38 iopoll()
214  * 0x54 bootinit()
215  * 0x58 bootread()
216  * 0x64 getenv()
217  * 0x6c slot_address()
218  * 0x70 wbflush()
219  * 0x7c clear_cache()
220  * 0x80 getsysid()
221  * 0x84 getbitmap()
222  * 0x88 disableintr()
223  * 0x8c enableintr()
224  * 0x9c halt()
225  * 0xa4 gettcinfo()
226  * 0xa8 execute_cmd()
227  * 0xac rex()
228  */
229 int decstation_prom_emul(struct cpu *cpu)
230 {
231  int i, j, ch, argreg, argdata;
232  int vector = cpu->pc & 0xfff;
233  int callback = (cpu->pc & 0xf000)? 1 : 0;
234  unsigned char buf[100];
235  unsigned char ch1, ch2, ch3;
236  uint64_t tmpaddr, slot_base = 0x10000000, slot_size = 0;
237 
238  if (!callback) {
239  vector = dec_jumptable_func(cpu, vector);
240  if (vector == 0)
241  return 1;
242  } else {
243  /* Vector number is n*4, PC points to n*8. */
244  vector /= 2;
245  }
246 
247  switch (vector) {
248  case 0x0c: /* strcmp(): */
249  i = j = 0;
250  do {
251  ch1 = mem_readchar(cpu, MIPS_GPR_A0, i++);
252  ch2 = mem_readchar(cpu, MIPS_GPR_A1, j++);
253  } while (ch1 == ch2 && ch1 != '\0');
254 
255  /* If ch1=='\0', then strings are equal. */
256  if (ch1 == '\0')
257  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
258  if ((signed char)ch1 > (signed char)ch2)
259  cpu->cd.mips.gpr[MIPS_GPR_V0] = 1;
260  if ((signed char)ch1 < (signed char)ch2)
261  cpu->cd.mips.gpr[MIPS_GPR_V0] = (uint64_t) -1;
262  break;
263  case 0x14: /* strlen(): */
264  i = 0;
265  do {
266  ch2 = mem_readchar(cpu, MIPS_GPR_A0, i++);
267  } while (ch2 != 0);
268  cpu->cd.mips.gpr[MIPS_GPR_V0] = i - 1;
269  break;
270  case 0x24: /* getchar() */
271  /* debug("[ DEC PROM getchar() ]\n"); */
274  break;
275  case 0x28: /* gets() */
276  /* debug("[ DEC PROM gets() ]\n"); */
277  tmpaddr = cpu->cd.mips.gpr[MIPS_GPR_A0];
278  i = 0;
279 
280  /* TODO: Make this not hang (block) the entire emulator */
281 
282  do {
283  while ((ch = console_readchar(
284  cpu->machine->main_console_handle)) < 1)
285  ;
286  if (ch == '\r')
287  ch = '\n';
288  ch2 = ch;
289 
290  if (ch == '\b') {
291  if (i > 0) {
292  console_putchar(cpu->machine->
293  main_console_handle, ch2);
294  console_putchar(cpu->machine->
295  main_console_handle, ' ');
296  console_putchar(cpu->machine->
297  main_console_handle, ch2);
298  }
299  } else
300  console_putchar(cpu->machine->
301  main_console_handle, ch2);
302 
303  fflush(stdout);
304 
305  if (ch == '\n') {
306  /* It seems that trailing newlines
307  are not included in the buffer. */
308  } else if (ch != '\b') {
309  cpu->memory_rw(cpu, cpu->mem, (int32_t)
310  cpu->cd.mips.gpr[MIPS_GPR_A0] + i,
311  &ch2, sizeof(ch2), MEM_WRITE,
313  i++;
314  } else {
315  if (i > 0)
316  i--;
317  }
318  } while (ch2 != '\n');
319 
320  /* Trailing nul-byte: */
321  ch2 = '\0';
322  cpu->memory_rw(cpu, cpu->mem, (int32_t)
323  cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &ch2, sizeof(ch2),
325 
326  /* Return the input argument: */
327  cpu->cd.mips.gpr[MIPS_GPR_V0] = cpu->cd.mips.gpr[MIPS_GPR_A0];
328  break;
329  case 0x2c: /* puts() */
330  i = 0;
331  while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
334  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
335  break;
336  case 0x30: /* printf() */
337  if (cpu->machine->register_dump ||
339  debug("PROM printf(0x%08lx): \n",
340  (long)cpu->cd.mips.gpr[MIPS_GPR_A0]);
341 
342  i = 0; ch = -1; argreg = MIPS_GPR_A1;
343  while (ch != '\0') {
344  char printfbuf[8000];
345  size_t x;
346 
347  printfbuf[0] = printfbuf[sizeof(printfbuf)-1] = '\0';
348 
349  ch = mem_readchar(cpu, MIPS_GPR_A0, i++);
350  switch (ch) {
351  case '%':
352  ch = '0';
353  while (ch >= '0' && ch <= '9')
354  ch = mem_readchar(cpu,
355  MIPS_GPR_A0, i++);
356 
357  switch (ch) {
358  case '%':
359  strlcpy(printfbuf, "%%",
360  sizeof(printfbuf));
361  break;
362  case 'c':
363  case 'd':
364  case 's':
365  case 'x':
366  /* Get argument: */
367  if (argreg > MIPS_GPR_A3) {
368 #if 1
369  /* Linux booters seem to go
370  over the edge sometimes: */
371  ch = '\0';
372  strlcpy(printfbuf, "[...]\n",
373  sizeof(printfbuf));
374 #else
375  printf("[ decstation_prom_emul"
376  "(): too many arguments ]");
377  /* This reuses the last arg,
378  which is utterly incorrect.
379  (TODO) */
380  argreg = MIPS_GPR_A3;
381 #endif
382  }
383 
384  ch2 = argdata =
385  cpu->cd.mips.gpr[argreg];
386 
387  switch (ch) {
388  case 'c':
389  snprintf(printfbuf, sizeof(
390  printfbuf), "%c", ch2);
391  break;
392  case 'd':
393  snprintf(printfbuf, sizeof(
394  printfbuf), "%d", argdata);
395  break;
396  case 'x':
397  snprintf(printfbuf, sizeof(
398  printfbuf), "%x", argdata);
399  break;
400  case 's':
401  /* Print a "%s" string. */
402  j = 0; ch3 = '\n';
403  while (ch2) {
404  ch2 = mem_readchar(cpu,
405  argreg, j++);
406  if (ch2) {
407  snprintf(
408  printfbuf +
409  strlen(
410  printfbuf),
411  sizeof(
412  printfbuf)-
413  1-strlen(
414  printfbuf),
415  "%c", ch2);
416  ch3 = ch2;
417  }
418  }
419  break;
420  }
421  argreg ++;
422  break;
423  default:
424  printf("[ unknown printf format char"
425  " '%c' ]", ch);
426  }
427  break;
428  case '\0':
429  break;
430  default:
431  snprintf(printfbuf, sizeof(printfbuf),
432  "%c", ch);
433  }
434 
435  printfbuf[sizeof(printfbuf)-1] = '\0';
436 
437  for (x=0; x<strlen(printfbuf); x++)
438  console_putchar(cpu->machine->
439  main_console_handle, printfbuf[x]);
440  }
441  if (cpu->machine->register_dump ||
443  debug("\n");
444  fflush(stdout);
445  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
446  break;
447  case 0x54: /* bootinit() */
448  /* debug("[ DEC PROM bootinit(0x%08x): TODO ]\n",
449  (int)cpu->cd.mips.gpr[MIPS_GPR_A0]); */
450  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
451  break;
452  case 0x58: /* bootread(int b, void *buffer, int n) */
453  /*
454  * Read data from the boot device.
455  * b is a sector number (512 bytes per sector),
456  * buffer is the destination address, and n
457  * is the number of _bytes_ to read.
458  *
459  * TODO: Return value? NetBSD thinks that 0 is ok.
460  */
461  debug("[ DEC PROM bootread(0x%x, 0x%08x, 0x%x) ]\n",
462  (int)cpu->cd.mips.gpr[MIPS_GPR_A0],
463  (int)cpu->cd.mips.gpr[MIPS_GPR_A1],
464  (int)cpu->cd.mips.gpr[MIPS_GPR_A2]);
465 
466  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
467 
468  if ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2] > 0) {
469  int disk_id = diskimage_bootdev(cpu->machine, NULL);
470  int res;
471  unsigned char *tmp_buf;
472 
473  CHECK_ALLOCATION(tmp_buf = (unsigned char *)
474  malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]));
475 
476  res = diskimage_access(cpu->machine, disk_id,
477  DISKIMAGE_SCSI, 0,
478  cpu->cd.mips.gpr[MIPS_GPR_A0] * 512, tmp_buf,
479  cpu->cd.mips.gpr[MIPS_GPR_A2]);
480 
481  /* If the transfer was successful, transfer the data
482  to emulated memory: */
483  if (res) {
484  uint64_t dst = cpu->cd.mips.gpr[MIPS_GPR_A1];
485  if (dst < 0x80000000ULL)
486  dst |= 0x80000000;
487 
488  store_buf(cpu, dst, (char *)tmp_buf,
489  cpu->cd.mips.gpr[MIPS_GPR_A2]);
490  cpu->cd.mips.gpr[MIPS_GPR_V0] =
491  cpu->cd.mips.gpr[MIPS_GPR_A2];
492  }
493 
494  free(tmp_buf);
495  }
496  break;
497  case 0x64: /* getenv() */
498  /* Find the environment variable given by a0: */
499  for (i=0; i<(int)sizeof(buf); i++)
500  cpu->memory_rw(cpu, cpu->mem, (int32_t)
501  cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &buf[i],
502  sizeof(char), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
503  buf[sizeof(buf)-1] = '\0';
504  debug("[ DEC PROM getenv(\"%s\") ]\n", buf);
505  for (i=0; i<0x1000; i++) {
506  /* Matching string at offset i? */
507  int nmatches = 0;
508  for (j=0; j<(int32_t)strlen((char *)buf); j++) {
509  cpu->memory_rw(cpu, cpu->mem, (int32_t)
510  (DEC_PROM_STRINGS + i + j), &ch2,
511  sizeof(char), MEM_READ, CACHE_DATA |
512  NO_EXCEPTIONS);
513  if (ch2 == buf[j])
514  nmatches++;
515  }
516  cpu->memory_rw(cpu, cpu->mem, (int32_t)(DEC_PROM_STRINGS
517  + i + strlen((char *)buf)), &ch2, sizeof(char),
519  if (nmatches == (int)strlen((char *)buf) && ch2=='=') {
520  cpu->cd.mips.gpr[MIPS_GPR_V0] =
521  DEC_PROM_STRINGS + i +
522  strlen((char *)buf) + 1;
523  return 1;
524  }
525  }
526  /* Return NULL if string wasn't found. */
527  fatal("[ DEC PROM getenv(\"%s\"): WARNING: Not in "
528  "environment! ]\n", buf);
529  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
530  break;
531  case 0x6c: /* ulong slot_address(int sn) */
532  debug("[ DEC PROM slot_address(%i) ]\n",
533  (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
534  /* TODO: This is too hardcoded. */
535  /* TODO 2: Should these be physical or virtual addresses? */
536  switch (cpu->machine->machine_subtype) {
538  slot_base = KN02_PHYS_TC_0_START;/* 0x1e000000 */
539  slot_size = 4*1048576; /* 4 MB */
540  break;
542  slot_base = 0x10000000;
543  slot_size = 0x4000000; /* 64 MB */
544  break;
546  slot_base = 0x1e000000;
547  slot_size = 0x800000; /* 8 MB */
548  break;
550  slot_base = 0x10000000;
551  slot_size = 0x4000000; /* 64 MB */
552  break;
553  default:
554  fatal("warning: DEC PROM slot_address() "
555  "unimplemented for this machine type\n");
556  }
557  cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t)(int32_t)
558  (0x80000000 + slot_base + slot_size *
559  cpu->cd.mips.gpr[MIPS_GPR_A0]);
560  break;
561  case 0x70: /* wbflush() */
562  debug("[ DEC PROM wbflush(): TODO ]\n");
563  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
564  break;
565  case 0x7c: /* clear_cache(addr, len) */
566  debug("[ DEC PROM clear_cache(0x%x,%i) ]\n",
567  (uint32_t)cpu->cd.mips.gpr[MIPS_GPR_A0],
568  (int)cpu->cd.mips.gpr[MIPS_GPR_A1]);
569  /* TODO */
570  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* ? */
571  break;
572  case 0x80: /* getsysid() */
573  /* debug("[ DEC PROM getsysid() ]\n"); */
574  /* TODO: why did I add the 0x82 stuff??? */
575  cpu->cd.mips.gpr[MIPS_GPR_V0] = ((uint32_t)0x82 << 24)
576  + (cpu->machine->machine_subtype << 16) + (0x3 << 8);
577  cpu->cd.mips.gpr[MIPS_GPR_V0] =
578  (int64_t)(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0];
579  break;
580  case 0x84: /* getbitmap() */
581  debug("[ DEC PROM getbitmap(0x%08x) ]\n",
582  (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
583  store_buf(cpu, cpu->cd.mips.gpr[MIPS_GPR_A0],
584  (char *)cpu->machine->md.pmax->memmap,
585  sizeof(struct dec_memmap));
586  cpu->cd.mips.gpr[MIPS_GPR_V0] =
587  sizeof(cpu->machine->md.pmax->memmap->bitmap);
588  break;
589  case 0x88: /* disableintr() */
590  debug("[ DEC PROM disableintr(): TODO ]\n");
591  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
592  break;
593  case 0x8c: /* enableintr() */
594  debug("[ DEC PROM enableintr(): TODO ]\n");
595  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
596  break;
597  case 0x9c: /* halt() */
598  debug("[ DEC PROM halt() ]\n");
600  cpu->running = 0;
601  break;
602  case 0xa4: /* gettcinfo() */
603  /*
604  * These are just bogus values... TODO
605  *
606  * 0: revision
607  * 4: clock period in nano seconds
608  * 8: slot size in megabytes TODO: not same for all models!
609  * 12: I/O timeout in cycles
610  * 16: DMA address range in megabytes
611  * 20: maximum DMA burst length
612  * 24: turbochannel parity (yes = 1)
613  * 28: reserved
614  */
615  store_32bit_word(cpu, DEC_PROM_TCINFO + 0, 0);
616  store_32bit_word(cpu, DEC_PROM_TCINFO + 4, 50);
617  store_32bit_word(cpu, DEC_PROM_TCINFO + 8, 4);
618  store_32bit_word(cpu, DEC_PROM_TCINFO + 12, 10);
619  store_32bit_word(cpu, DEC_PROM_TCINFO + 16, 1);
620  store_32bit_word(cpu, DEC_PROM_TCINFO + 20, 100);
621  store_32bit_word(cpu, DEC_PROM_TCINFO + 24, 0);
622  store_32bit_word(cpu, DEC_PROM_TCINFO + 28, 0);
624  break;
625  case 0xa8: /* int execute_cmd(char *) */
626  i = 0;
627  while ((ch = mem_readchar(cpu, MIPS_GPR_A0, i++)) != '\0')
630  cpu->cd.mips.gpr[MIPS_GPR_V0] = 0;
631  break;
632  case 0xac: /* rex() */
633  debug("[ DEC PROM rex('%c') ]\n",
634  (int)cpu->cd.mips.gpr[MIPS_GPR_A0]);
635  switch ((int32_t)cpu->cd.mips.gpr[MIPS_GPR_A0]) {
636  case 'h':
637  debug("DEC PROM: rex('h') ==> halt\n");
639  cpu->running = 0;
640  break;
641  case 'b':
642  debug("DEC PROM: rex('b') ==> reboot: TODO "
643  "(halting CPU instead)\n");
645  cpu->running = 0;
646  break;
647  default:
648  fatal("DEC prom emulation: unknown rex() a0=0x%" PRIx64
649  " ('%c')\n",
650  (int64_t) cpu->cd.mips.gpr[MIPS_GPR_A0],
651  (char) cpu->cd.mips.gpr[MIPS_GPR_A0]);
652  cpu->running = 0;
653  }
654  break;
655  default:
656  cpu_register_dump(cpu->machine, cpu, 1, 0x1);
657  printf("a0 points to: ");
658  for (i=0; i<40; i++) {
659  unsigned char chTmp = '\0';
660  cpu->memory_rw(cpu, cpu->mem, (int32_t)
661  cpu->cd.mips.gpr[MIPS_GPR_A0] + i, &chTmp,
662  sizeof(chTmp), MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
663  if (chTmp >= ' ' && chTmp < 126)
664  printf("%c", chTmp);
665  else
666  printf("[%02x]", chTmp);
667  }
668  printf("\n");
669  fatal("PROM emulation: unimplemented callback vector 0x%x\n",
670  vector);
671  cpu->running = 0;
672  }
673 
674  return 1;
675 }
676 
void fatal(const char *fmt,...)
Definition: main.cc:152
#define CACHE_DATA
Definition: memory.h:121
int main_console_handle
Definition: machine.h:128
int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
Definition: memory.cc:783
#define MACHINE_DEC_3MIN_5000
Definition: machine.h:267
#define MIPS_GPR_A0
union cpu::@1 cd
struct memory * mem
Definition: cpu.h:362
#define DISKIMAGE_SCSI
Definition: diskimage.h:40
struct machine * machine
Definition: cpu.h:328
#define KN02_PHYS_TC_0_START
Definition: dec_kn02.h:119
#define MEM_READ
Definition: memory.h:116
void console_putchar(int handle, int ch)
Definition: console.cc:405
int console_readchar(int handle)
Definition: console.cc:385
#define MIPS_GPR_A2
int exit_without_entering_debugger
Definition: machine.h:172
#define DEC_PROM_TCINFO
Definition: machine.h:279
uint64_t pc
Definition: cpu.h:383
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
int quiet_mode
Definition: main.cc:78
int decstation_prom_emul(struct cpu *cpu)
Definition: dec_prom.cc:229
int diskimage_bootdev(struct machine *machine, int *typep)
Definition: diskimage.cc:983
union machine::@2 md
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:365
#define MIPS_GPR_A3
int instruction_trace
Definition: machine.h:162
#define MIPS_GPR_A1
uint8_t running
Definition: cpu.h:353
#define MEM_WRITE
Definition: memory.h:117
void cpu_register_dump(struct machine *m, struct cpu *cpu, int gprs, int coprocs)
Definition: cpu.cc:203
u_char bitmap[15360]
Definition: dec_prom.h:90
#define MACHINE_DEC_3MAX_5000
Definition: machine.h:266
#define debug
Definition: dev_adb.cc:57
Definition: cpu.h:326
#define NO_EXCEPTIONS
Definition: memory.h:125
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
int register_dump
Definition: machine.h:150
int dec_jumptable_func(struct cpu *cpu, int vector)
Definition: dec_prom.cc:96
uint64_t gpr[N_MIPS_GPRS]
Definition: cpu_mips.h:209
struct mips_cpu mips
Definition: cpu.h:443
#define MACHINE_DEC_3MAXPLUS_5000
Definition: machine.h:268
#define MIPS_GPR_V0
void store_buf(struct cpu *cpu, uint64_t addr, const char *s, size_t len)
Definition: memory.cc:826
int machine_subtype
Definition: machine.h:112
struct machine_pmax * pmax
Definition: machine.h:184
int diskimage_access(struct machine *machine, int id, int type, int writeflag, off_t offset, unsigned char *buf, size_t len)
Definition: diskimage.cc:605
#define DEC_PROM_STRINGS
Definition: machine.h:278
struct dec_memmap * memmap
Definition: machine_pmax.h:38
#define MACHINE_DEC_MAXINE_5000
Definition: machine.h:271

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13