From: eager Date: Tue, 6 Oct 2009 15:19:52 +0000 (+0000) Subject: * microblaze/interp.c: Add include microblaze-dis.h. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=83a29744c468ec47712c1096a70731e52f0e0d58;p=pf3gnuchains%2Fpf3gnuchains3x.git * microblaze/interp.c: Add include microblaze-dis.h. --- diff --git a/sim/ChangeLog b/sim/ChangeLog index edd6d2afe0..d04336da30 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,21 @@ +2009-10-06 Michael Eager + + * microblaze/interp.c: Add include microblaze-dis.h. + +2009-09-23 Michael Eager + + * configure: Add microblaze-*.* (not regenerated). + * configure.ac: Likewise. + * microblaze/config.in: New. + * microblaze/configure: Generate. + * microblaze/configure.ac: New. + * microblaze/interp.c: New. + * microblaze/Makefile.in: New. + * microblaze/microblaze.h: New. + * microblaze/microblaze.isa: New. + * microblaze/sim-main.h: New. + * microblaze/sysdep.h: New. + 2009-08-22 Ralf Wildenhues * avr/config.in: Regenerate. diff --git a/sim/microblaze/interp.c b/sim/microblaze/interp.c new file mode 100644 index 0000000000..8394c36bc2 --- /dev/null +++ b/sim/microblaze/interp.c @@ -0,0 +1,1091 @@ +/* Simulator for Xilinx MicroBlaze processor + Copyright 2009 Free Software Foundation, Inc. + + This file is part of GDB, the GNU debugger. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "sysdep.h" +#include +#include +#include /* for byte ordering macros */ +#include "bfd.h" +#include "gdb/callback.h" +#include "libiberty.h" +#include "gdb/remote-sim.h" +#include "sim-main.h" +#include "sim-utils.h" +#include "microblaze-dis.h" + + +#ifndef NUM_ELEM +#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0]) +#endif + +static int target_big_endian = 1; +static unsigned long heap_ptr = 0; +static unsigned long stack_ptr = 0; +host_callback *callback; + +unsigned long +microblaze_extract_unsigned_integer (unsigned char *addr, int len) +{ + unsigned long retval; + unsigned char *p; + unsigned char *startaddr = (unsigned char *)addr; + unsigned char *endaddr = startaddr + len; + + if (len > (int) sizeof (unsigned long)) + printf ("That operation is not available on integers of more than " + "%d bytes.", sizeof (unsigned long)); + + /* Start at the most significant end of the integer, and work towards + the least significant. */ + retval = 0; + + if (!target_big_endian) + { + for (p = endaddr; p > startaddr;) + retval = (retval << 8) | * -- p; + } + else + { + for (p = startaddr; p < endaddr;) + retval = (retval << 8) | * p ++; + } + + return retval; +} + +void +microblaze_store_unsigned_integer (unsigned char *addr, int len, + unsigned long val) +{ + unsigned char *p; + unsigned char *startaddr = (unsigned char *)addr; + unsigned char *endaddr = startaddr + len; + + if (!target_big_endian) + { + for (p = startaddr; p < endaddr;) + { + *p++ = val & 0xff; + val >>= 8; + } + } + else + { + for (p = endaddr; p > startaddr;) + { + *--p = val & 0xff; + val >>= 8; + } + } +} + +struct sim_state microblaze_state; + +int memcycles = 1; + +static SIM_OPEN_KIND sim_kind; +static char *myname; + +static int issue_messages = 0; + +long +int_sbrk (int inc_bytes) +{ + long addr; + + addr = heap_ptr; + + heap_ptr += inc_bytes; + + if (issue_messages && heap_ptr > SP) + fprintf (stderr, "Warning: heap_ptr overlaps stack!\n"); + + return addr; +} + +static void /* INLINE */ +wbat (word x, word v) +{ + if (((uword)x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "byte write to 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + } + else + { + unsigned char *p = CPU.memory + x; + p[0] = v; + } +} + +static void /* INLINE */ +wlat (word x, word v) +{ + if (((uword)x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "word write to 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + } + else + { + if ((x & 3) != 0) + { + if (issue_messages) + fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x); + + CPU.exception = SIGBUS; + } + else if (!target_big_endian) + { + unsigned char *p = CPU.memory + x; + p[3] = v >> 24; + p[2] = v >> 16; + p[1] = v >> 8; + p[0] = v; + } + else + { + unsigned char *p = CPU.memory + x; + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v; + } + } +} + +static void /* INLINE */ +what (word x, word v) +{ + if (((uword)x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "short write to 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + } + else + { + if ((x & 1) != 0) + { + if (issue_messages) + fprintf (stderr, "short write to unaligned memory address: 0x%x\n", + x); + + CPU.exception = SIGBUS; + } + else if (!target_big_endian) + { + unsigned char *p = CPU.memory + x; + p[1] = v >> 8; + p[0] = v; + } + else + { + unsigned char *p = CPU.memory + x; + p[0] = v >> 8; + p[1] = v; + } + } +} + +/* Read functions. */ +static int /* INLINE */ +rbat (word x) +{ + if (((uword)x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "byte read from 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + return 0; + } + else + { + unsigned char *p = CPU.memory + x; + return p[0]; + } +} + +static int /* INLINE */ +rlat (word x) +{ + if (((uword) x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "word read from 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + return 0; + } + else + { + if ((x & 3) != 0) + { + if (issue_messages) + fprintf (stderr, "word read from unaligned address: 0x%x\n", x); + + CPU.exception = SIGBUS; + return 0; + } + else if (! target_big_endian) + { + unsigned char *p = CPU.memory + x; + return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; + } + else + { + unsigned char *p = CPU.memory + x; + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + } + } +} + +static int /* INLINE */ +rhat (word x) +{ + if (((uword)x) >= CPU.msize) + { + if (issue_messages) + fprintf (stderr, "short read from 0x%x outside memory range\n", x); + + CPU.exception = SIGSEGV; + return 0; + } + else + { + if ((x & 1) != 0) + { + if (issue_messages) + fprintf (stderr, "short read from unaligned address: 0x%x\n", x); + + CPU.exception = SIGBUS; + return 0; + } + else if (!target_big_endian) + { + unsigned char *p = CPU.memory + x; + return (p[1] << 8) | p[0]; + } + else + { + unsigned char *p = CPU.memory + x; + return (p[0] << 8) | p[1]; + } + } +} + + +#define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80) +#define SEXTW(y) ((int)((short)y)) + +static int +IOMEM (int addr, int write, int value) +{ +} + +/* Default to a 8 Mbyte (== 2^23) memory space. */ +static int sim_memory_size = 1 << 23; + +#define MEM_SIZE_FLOOR 64 +void +sim_size (int size) +{ + sim_memory_size = size; + CPU.msize = sim_memory_size; + + if (CPU.memory) + free (CPU.memory); + + CPU.memory = (unsigned char *) calloc (1, CPU.msize); + + if (!CPU.memory) + { + if (issue_messages) + fprintf (stderr, + "Not enough VM for simulation of %d bytes of RAM\n", + CPU.msize); + + CPU.msize = 1; + CPU.memory = (unsigned char *) calloc (1, 1); + } +} + +static void +init_pointers () +{ + if (CPU.msize != (sim_memory_size)) + sim_size (sim_memory_size); +} + +static void +set_initial_gprs () +{ + int i; + long space; + unsigned long memsize; + + init_pointers (); + + /* Set up machine just out of reset. */ + PC = 0; + MSR = 0; + + memsize = CPU.msize / (1024 * 1024); + + if (issue_messages > 1) + fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n", + memsize, CPU.msize - 1); + + /* Clean out the GPRs */ + for (i = 0; i < 32; i++) + CPU.regs[i] = 0; + CPU.insts = 0; + CPU.cycles = 0; + CPU.imm_enable = 0; + +} + +static void +interrupt () +{ + CPU.exception = SIGINT; +} + +/* Functions so that trapped open/close don't interfere with the + parent's functions. We say that we can't close the descriptors + that we didn't open. exit() and cleanup() get in trouble here, + to some extent. That's the price of emulation. */ + +unsigned char opened[100]; + +static void +log_open (int fd) +{ + if (fd < 0 || fd > NUM_ELEM (opened)) + return; + + opened[fd] = 1; +} + +static void +log_close (int fd) +{ + if (fd < 0 || fd > NUM_ELEM (opened)) + return; + + opened[fd] = 0; +} + +static int +is_opened (int fd) +{ + if (fd < 0 || fd > NUM_ELEM (opened)) + return 0; + + return opened[fd]; +} + +static void +handle_trap1 () +{ +} + +static void +process_stub (int what) +{ + /* These values should match those in libgloss/microblaze/syscalls.s. */ + switch (what) + { + case 3: /* _read */ + case 4: /* _write */ + case 5: /* _open */ + case 6: /* _close */ + case 10: /* _unlink */ + case 19: /* _lseek */ + case 43: /* _times */ + handle_trap1 (); + break; + + default: + if (issue_messages) + fprintf (stderr, "Unhandled stub opcode: %d\n", what); + break; + } +} + +static void +util (unsigned what) +{ + switch (what) + { + case 0: /* exit */ + CPU.exception = SIGQUIT; + break; + + case 1: /* printf */ + { + unsigned long a[6]; + unsigned char *s; + int i; + + for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++) + if (*s == '%') + i++; + } + break; + + case 2: /* scanf */ + if (issue_messages) + fprintf (stderr, "WARNING: scanf unimplemented\n"); + break; + + case 3: /* utime */ + break; + + case 0xFF: + process_stub (CPU.regs[1]); + break; + + default: + if (issue_messages) + fprintf (stderr, "Unhandled util code: %x\n", what); + break; + } +} + +/* For figuring out whether we carried; addc/subc use this. */ +static int +iu_carry (unsigned long a, unsigned long b, int cin) +{ + unsigned long x; + + x = (a & 0xffff) + (b & 0xffff) + cin; + x = (x >> 16) + (a >> 16) + (b >> 16); + x >>= 16; + + return (x != 0); +} + +#define WATCHFUNCTIONS 1 +#ifdef WATCHFUNCTIONS + +#define MAXWL 80 +word WL[MAXWL]; +char *WLstr[MAXWL]; + +int ENDWL=0; +int WLincyc; +int WLcyc[MAXWL]; +int WLcnts[MAXWL]; +int WLmax[MAXWL]; +int WLmin[MAXWL]; +word WLendpc; +int WLbcyc; +int WLW; +#endif + +static int tracing = 0; + +void +sim_resume (SIM_DESC sd, int step, int siggnal) +{ + int needfetch; + word inst; + enum microblaze_instr op; + void (*sigsave)(); + int memops; + int bonus_cycles; + int insts; + int w; + int cycs; + word WLhash; + ubyte carry; + int imm_unsigned; + short ra, rb, rd; + long immword; + uword oldpc, newpc; + short delay_slot_enable; + short branch_taken; + short num_delay_slot; /* UNUSED except as reqd parameter */ + enum microblaze_instr_type insn_type; + + sigsave = signal (SIGINT, interrupt); + CPU.exception = step ? SIGTRAP : 0; + + memops = 0; + bonus_cycles = 0; + insts = 0; + + do + { + /* Fetch the initial instructions that we'll decode. */ + inst = rlat (PC & 0xFFFFFFFC); + + op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, + &num_delay_slot); + + if (op == invalid_inst) + fprintf (stderr, "Unknown instruction 0x%04x", inst); + + if (tracing) + fprintf (stderr, "%.4x: inst = %.4x ", PC, inst); + + rd = GET_RD; + rb = GET_RB; + ra = GET_RA; + /* immword = IMM_W; */ + + oldpc = PC; + delay_slot_enable = 0; + branch_taken = 0; + if (op == microblaze_brk) + CPU.exception = SIGTRAP; + else if (inst == MICROBLAZE_HALT_INST) + { + CPU.exception = SIGQUIT; + insts += 1; + bonus_cycles++; + } + else + { + switch(op) + { +#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \ + case NAME: \ + ACTION; \ + break; +#include "microblaze.isa" +#undef INSTRUCTION + + default: + CPU.exception = SIGILL; + fprintf (stderr, "ERROR: Unknown opcode\n"); + } + /* Make R0 consistent */ + CPU.regs[0] = 0; + + /* Check for imm instr */ + if (op == imm) + IMM_ENABLE = 1; + else + IMM_ENABLE = 0; + + /* Update cycle counts */ + insts ++; + if (insn_type == memory_store_inst || insn_type == memory_load_inst) + memops++; + if (insn_type == mult_inst) + bonus_cycles++; + if (insn_type == barrel_shift_inst) + bonus_cycles++; + if (insn_type == anyware_inst) + bonus_cycles++; + if (insn_type == div_inst) + bonus_cycles += 33; + + if ((insn_type == branch_inst || insn_type == return_inst) + && branch_taken) + { + /* Add an extra cycle for taken branches */ + bonus_cycles++; + /* For branch instructions handle the instruction in the delay slot */ + if (delay_slot_enable) + { + newpc = PC; + PC = oldpc + INST_SIZE; + inst = rlat (PC & 0xFFFFFFFC); + op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, + &num_delay_slot); + if (op == invalid_inst) + fprintf (stderr, "Unknown instruction 0x%04x", inst); + if (tracing) + fprintf (stderr, "%.4x: inst = %.4x ", PC, inst); + rd = GET_RD; + rb = GET_RB; + ra = GET_RA; + /* immword = IMM_W; */ + if (op == microblaze_brk) + { + if (issue_messages) + fprintf (stderr, "Breakpoint set in delay slot " + "(at address 0x%x) will not be honored\n", PC); + /* ignore the breakpoint */ + } + else if (insn_type == branch_inst || insn_type == return_inst) + { + if (issue_messages) + fprintf (stderr, "Cannot have branch or return instructions " + "in delay slot (at address 0x%x)\n", PC); + CPU.exception = SIGILL; + } + else + { + switch(op) + { +#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \ + case NAME: \ + ACTION; \ + break; +#include "microblaze.isa" +#undef INSTRUCTION + + default: + CPU.exception = SIGILL; + fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC); + } + /* Update cycle counts */ + insts++; + if (insn_type == memory_store_inst + || insn_type == memory_load_inst) + memops++; + if (insn_type == mult_inst) + bonus_cycles++; + if (insn_type == barrel_shift_inst) + bonus_cycles++; + if (insn_type == anyware_inst) + bonus_cycles++; + if (insn_type == div_inst) + bonus_cycles += 33; + } + /* Restore the PC */ + PC = newpc; + /* Make R0 consistent */ + CPU.regs[0] = 0; + /* Check for imm instr */ + if (op == imm) + IMM_ENABLE = 1; + else + IMM_ENABLE = 0; + } + else + /* no delay slot: increment cycle count */ + bonus_cycles++; + } + } + + if (tracing) + fprintf (stderr, "\n"); + } + while (!CPU.exception); + + /* Hide away the things we've cached while executing. */ + /* CPU.pc = pc; */ + CPU.insts += insts; /* instructions done ... */ + CPU.cycles += insts; /* and each takes a cycle */ + CPU.cycles += bonus_cycles; /* and extra cycles for branches */ + CPU.cycles += memops; /* and memop cycle delays */ + + signal (SIGINT, sigsave); +} + + +int +sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size) +{ + int i; + init_pointers (); + + memcpy (&CPU.memory[addr], buffer, size); + + return size; +} + +int +sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size) +{ + int i; + init_pointers (); + + memcpy (buffer, &CPU.memory[addr], size); + + return size; +} + + +int +sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +{ + init_pointers (); + + if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) + { + if (length == 4) + { + /* misalignment safe */ + long ival = microblaze_extract_unsigned_integer (memory, 4); + if (rn < NUM_REGS) + CPU.regs[rn] = ival; + else + CPU.spregs[rn-NUM_REGS] = ival; + return 4; + } + else + return 0; + } + else + return 0; +} + +int +sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +{ + long ival; + init_pointers (); + + if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) + { + if (length == 4) + { + if (rn < NUM_REGS) + ival = CPU.regs[rn]; + else + ival = CPU.spregs[rn-NUM_REGS]; + + /* misalignment-safe */ + microblaze_store_unsigned_integer (memory, 4, ival); + return 4; + } + else + return 0; + } + else + return 0; +} + + +int +sim_trace (SIM_DESC sd) +{ + tracing = 1; + + sim_resume (sd, 0, 0); + + tracing = 0; + + return 1; +} + +void +sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) +{ + if (CPU.exception == SIGQUIT) + { + *reason = sim_exited; + *sigrc = RETREG; + } + else + { + *reason = sim_stopped; + *sigrc = CPU.exception; + } +} + + +int +sim_stop (SIM_DESC sd) +{ + CPU.exception = SIGINT; + return 1; +} + + +void +sim_info (SIM_DESC sd, int verbose) +{ +#ifdef WATCHFUNCTIONS + int w, wcyc; +#endif + + callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", + CPU.insts); + callback->printf_filtered (callback, "# cycles %10d\n", + (CPU.cycles) ? CPU.cycles+2 : 0); + +#ifdef WATCHFUNCTIONS + callback->printf_filtered (callback, "\nNumber of watched functions: %d\n", + ENDWL); + + wcyc = 0; + + for (w = 1; w <= ENDWL; w++) + { + callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]); + callback->printf_filtered (callback, " calls = %d, cycles = %d\n", + WLcnts[w],WLcyc[w]); + + if (WLcnts[w] != 0) + callback->printf_filtered (callback, + " maxcpc = %d, mincpc = %d, avecpc = %d\n", + WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]); + wcyc += WLcyc[w]; + } + + callback->printf_filtered (callback, + "Total cycles for watched functions: %d\n",wcyc); +#endif +} + +struct aout +{ + unsigned char sa_machtype[2]; + unsigned char sa_magic[2]; + unsigned char sa_tsize[4]; + unsigned char sa_dsize[4]; + unsigned char sa_bsize[4]; + unsigned char sa_syms[4]; + unsigned char sa_entry[4]; + unsigned char sa_trelo[4]; + unsigned char sa_drelo[4]; +} aout; + +#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) +#define SHORT(x) (((x)[0]<<8)|(x)[1]) + +SIM_DESC +sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv) +{ + /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/ + + int osize = sim_memory_size; + myname = argv[0]; + callback = cb; + + if (kind == SIM_OPEN_STANDALONE) + issue_messages = 1; + + /* Discard and reacquire memory -- start with a clean slate. */ + sim_size (1); /* small */ + sim_size (osize); /* and back again */ + + set_initial_gprs (); /* Reset the GPR registers. */ + + return ((SIM_DESC) 1); +} + +void +sim_close (SIM_DESC sd, int quitting) +{ + if (CPU.memory) + { + free(CPU.memory); + CPU.memory = NULL; + CPU.msize = 0; + } +} + +SIM_RC +sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty) +{ + /* Do the right thing for ELF executables; this turns out to be + just about the right thing for any object format that: + - we crack using BFD routines + - follows the traditional UNIX text/data/bss layout + - calls the bss section ".bss". */ + + extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ + bfd *prog_bfd; + + { + bfd *handle; + asection *s; + int found_loadable_section = 0; + bfd_vma max_addr = 0; + handle = bfd_openr (prog, 0); + + if (!handle) + { + printf("``%s'' could not be opened.\n", prog); + return SIM_RC_FAIL; + } + + /* Makes sure that we have an object file, also cleans gets the + section headers in place. */ + if (!bfd_check_format (handle, bfd_object)) + { + /* wasn't an object file */ + bfd_close (handle); + printf ("``%s'' is not appropriate object file.\n", prog); + return SIM_RC_FAIL; + } + + for (s = handle->sections; s; s = s->next) + { + if (s->flags & SEC_ALLOC) + { + bfd_vma vma = 0; + int size = bfd_get_section_size (s); + if (size > 0) + { + vma = bfd_section_vma (handle, s); + if (vma >= max_addr) + { + max_addr = vma + size; + } + } + if (s->flags & SEC_LOAD) + found_loadable_section = 1; + } + } + + if (!found_loadable_section) + { + /* No loadable sections */ + bfd_close(handle); + printf("No loadable sections in file %s\n", prog); + return SIM_RC_FAIL; + } + + sim_memory_size = (unsigned long) max_addr; + + /* Clean up after ourselves. */ + bfd_close (handle); + + } + + /* from sh -- dac */ + prog_bfd = sim_load_file (sd, myname, callback, prog, abfd, + /* sim_kind == SIM_OPEN_DEBUG, */ + 1, + 0, sim_write); + if (prog_bfd == NULL) + return SIM_RC_FAIL; + + target_big_endian = bfd_big_endian (prog_bfd); + PC = bfd_get_start_address (prog_bfd); + + if (abfd == NULL) + bfd_close (prog_bfd); + + return SIM_RC_OK; +} + +SIM_RC +sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env) +{ + char **avp; + int nargs = 0; + int nenv = 0; + int s_length; + int l; + unsigned long strings; + unsigned long pointers; + unsigned long hi_stack; + + + /* Set the initial register set. */ + l = issue_messages; + issue_messages = 0; + set_initial_gprs (); + issue_messages = l; + + hi_stack = CPU.msize - 4; + PC = bfd_get_start_address (prog_bfd); + + /* For now ignore all parameters to the program */ + + return SIM_RC_OK; +} + +void +sim_kill (SIM_DESC sd) +{ + /* nothing to do */ +} + +void +sim_do_command (SIM_DESC sd, char * cmd) +{ + /* Nothing there yet; it's all an error. */ + + if (cmd != NULL) + { + char ** simargv = buildargv (cmd); + + if (strcmp (simargv[0], "watch") == 0) + { + if ((simargv[1] == NULL) || (simargv[2] == NULL)) + { + fprintf (stderr, "Error: missing argument to watch cmd.\n"); + return; + } + + ENDWL++; + + WL[ENDWL] = strtol (simargv[2], NULL, 0); + WLstr[ENDWL] = strdup (simargv[1]); + fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL], + WL[ENDWL], ENDWL); + + } + else if (strcmp (simargv[0], "dumpmem") == 0) + { + unsigned char * p; + FILE * dumpfile; + + if (simargv[1] == NULL) + fprintf (stderr, "Error: missing argument to dumpmem cmd.\n"); + + fprintf (stderr, "Writing dumpfile %s...",simargv[1]); + + dumpfile = fopen (simargv[1], "w"); + p = CPU.memory; + fwrite (p, CPU.msize-1, 1, dumpfile); + fclose (dumpfile); + + fprintf (stderr, "done.\n"); + } + else if (strcmp (simargv[0], "clearstats") == 0) + { + CPU.cycles = 0; + CPU.insts = 0; + ENDWL = 0; + } + else if (strcmp (simargv[0], "verbose") == 0) + { + issue_messages = 2; + } + else + { + fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n", + cmd); + } + } + else + { + fprintf (stderr, "M.CORE sim commands: \n"); + fprintf (stderr, " watch \n"); + fprintf (stderr, " dumpmem \n"); + fprintf (stderr, " clearstats\n"); + fprintf (stderr, " verbose\n"); + } +} + +void +sim_set_callbacks (host_callback *ptr) +{ + callback = ptr; +}