/* Simulator for the WDC 65816 architecture. Written by Steve Chamberlain of Cygnus Support. sac@cygnus.com This file is part of W65 sim THIS SOFTWARE IS NOT COPYRIGHTED Cygnus offers the following for use in the public domain. Cygnus makes no warranty with regard to the software or it's performance and the user accepts the software "AS IS" with all faults. CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "config.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include "bfd.h" #include "gdb/callback.h" #include "gdb/remote-sim.h" #include "../../newlib/libc/sys/w65/sys/syscall.h" #include "interp.h" saved_state_type saved_state; int get_now () { return time ((long *) 0); } void control_c (sig, code, scp, addr) int sig; int code; char *scp; char *addr; { saved_state.exception = SIGINT; } wai () { saved_state.exception = SIGTRAP; } wdm (acc, x) int acc; int x; { int cycles; /* The x points to where the registers live, acc has code */ #define R(arg) (x + arg * 2) unsigned R0 = R(0); unsigned R4 = R(4); unsigned R5 = R(5); unsigned R6 = R(6); unsigned R7 = R(7); unsigned R8 = R(8); unsigned char *memory = saved_state.memory; int a1 = fetch16 (R (4)); switch (a1) { case SYS_write: { int file = fetch16 (R5); unsigned char *buf = fetch24 (R6) + memory; int len = fetch16 (R8); int res = write (file, buf, len); store16 (R0, res); break; } case 0: printf ("%c", acc); fflush (stdout); break; case 1: saved_state.exception = SIGTRAP; break; default: saved_state.exception = SIGILL; break; } } void sim_resume (step, insignal) int step; int insignal; { void (*prev) (); register unsigned char *memory; if (step) { saved_state.exception = SIGTRAP; } else { saved_state.exception = 0; } prev = signal (SIGINT, control_c); do { int x = (saved_state.p >> 4) & 1; int m = (saved_state.p >> 5) & 1; if (x == 0 && m == 0) { ifunc_X0_M0 (); } else if (x == 0 && m == 1) { ifunc_X0_M1 (); } else if (x == 1 && m == 0) { ifunc_X1_M0 (); } else if (x == 1 && m == 1) { ifunc_X1_M1 (); } } while (saved_state.exception == 0); signal (SIGINT, prev); } init_pointers () { if (!saved_state.memory) { saved_state.memory = calloc (64 * 1024, NUMSEGS); } } int sim_write (addr, buffer, size) SIM_ADDR addr; unsigned char *buffer; int size; { int i; init_pointers (); for (i = 0; i < size; i++) { saved_state.memory[(addr + i) & MMASK] = buffer[i]; } return size; } int sim_read (addr, buffer, size) SIM_ADDR addr; unsigned char *buffer; int size; { int i; init_pointers (); for (i = 0; i < size; i++) { buffer[i] = saved_state.memory[(addr + i) & MMASK]; } return size; } struct { unsigned int *ptr; int size; } rinfo[] = { &saved_state.r[0], 2, &saved_state.r[1], 2, &saved_state.r[2], 2, &saved_state.r[3], 2, &saved_state.r[4], 2, &saved_state.r[5], 2, &saved_state.r[6], 2, &saved_state.r[7], 2, &saved_state.r[8], 2, &saved_state.r[9], 2, &saved_state.r[10], 2, &saved_state.r[11], 2, &saved_state.r[12], 2, &saved_state.r[13], 2, &saved_state.r[14], 2, &saved_state.r[15], 4, &saved_state.pc, 4, &saved_state.a, 4, &saved_state.x, 4, &saved_state.y, 4, &saved_state.dbr, 4, &saved_state.d, 4, &saved_state.s, 4, &saved_state.p, 4, &saved_state.ticks, 4, &saved_state.cycles, 4, &saved_state.insts, 4, 0 }; int sim_store_register (rn, value, length) int rn; unsigned char *value; int length; { unsigned int val; int i; val = 0; for (i = 0; i < rinfo[rn].size; i++) { val |= (*value++) << (i * 8); } *(rinfo[rn].ptr) = val; return -1; } int sim_fetch_register (rn, buf, length) int rn; unsigned char *buf; int length; { unsigned int val = *(rinfo[rn].ptr); int i; for (i = 0; i < rinfo[rn].size; i++) { *buf++ = val; val = val >> 8; } return -1; } sim_reg_size (n) { return rinfo[n].size; } int sim_trace () { return 0; } void sim_stop_reason (reason, sigrc) enum sim_stop *reason; int *sigrc; { *reason = sim_stopped; *sigrc = saved_state.exception; } int sim_set_pc (x) SIM_ADDR x; { saved_state.pc = x; return 0; } void sim_info (verbose) int verbose; { double timetaken = (double) saved_state.ticks; double virttime = saved_state.cycles / 2.0e6; printf ("\n\n# instructions executed %10d\n", saved_state.insts); printf ("# cycles %10d\n", saved_state.cycles); printf ("# real time taken %10.4f\n", timetaken); printf ("# virtual time taken %10.4f\n", virttime); if (timetaken != 0) { printf ("# cycles/second %10d\n", (int) (saved_state.cycles / timetaken)); printf ("# simulation ratio %10.4f\n", virttime / timetaken); } } void sim_open (kind, cb, abfd, argv) SIM_OPEN_KIND kind; host_callback *cb; struct _bfd *abfd; char **argv; { } #undef fetch8 fetch8func (x) { if (x & ~MMASK) { saved_state.exception = SIGBUS; return 0; } return saved_state.memory[x]; } fetch8 (x) { return fetch8func(x); } void sim_close (quitting) int quitting; { /* nothing to do */ } int sim_load (prog, from_tty) char *prog; int from_tty; { /* Return nonzero so gdb will handle it. */ return 1; } void sim_create_inferior (abfd, argv, env) struct _bfd *abfd; char **argv; char **env; { SIM_ADDR start_address; int pc; if (abfd != NULL) start_address = bfd_get_start_address (abfd); else start_address = 0; /*??*/ /* ??? We assume this is a 4 byte quantity. */ pc = start_address; sim_store_register (16, (unsigned char *) &pc); } void sim_set_callbacks (ptr) struct host_callback_struct *ptr; { }