*/
-#include "config.h"
+/* This must come before any other includes. */
+#include "defs.h"
+
#include "bfd.h"
#include "sim-main.h"
#include "sim-utils.h"
#include "itable.h"
-
-#include "config.h"
-
#include <stdio.h>
#include <stdarg.h>
#include <ansidecl.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
#include "getopt.h"
#include "libiberty.h"
#include "bfd.h"
-#include "gdb/callback.h" /* GDB simulator callback interface */
-#include "gdb/remote-sim.h" /* GDB simulator interface */
+#include "elf-bfd.h"
+#include "sim/callback.h" /* GDB simulator callback interface */
+#include "sim/sim.h" /* GDB simulator interface */
+#include "sim-syscall.h" /* Simulator system call support */
char* pr_addr (SIM_ADDR addr);
char* pr_uword64 (uword64 addr);
trap is required. NOTE: Care must be taken, since this value may be
used in later revisions of the MIPS ISA. */
-#define RSVD_INSTRUCTION (0x00000005)
+#define RSVD_INSTRUCTION (0x00000039)
#define RSVD_INSTRUCTION_MASK (0xFC00003F)
#define RSVD_INSTRUCTION_ARG_SHIFT 6
static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
-
#define MEM_SIZE (8 << 20) /* 8 MBytes */
PC = pc;
}
+static int mips_reg_fetch (SIM_CPU *, int, unsigned char *, int);
+static int mips_reg_store (SIM_CPU *, int, unsigned char *, int);
+
SIM_DESC
-sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
+sim_open (SIM_OPEN_KIND kind, host_callback *cb,
+ struct bfd *abfd, char * const *argv)
{
int i;
- SIM_DESC sd = sim_state_alloc (kind, cb);
+ SIM_DESC sd = sim_state_alloc_extra (kind, cb,
+ sizeof (struct mips_sim_state));
sim_cpu *cpu;
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
/* The cpu data is kept in a separately allocated chunk of memory. */
- if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
+ if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
return 0;
cpu = STATE_CPU (sd, 0); /* FIXME */
/* FIXME: watchpoints code shouldn't need this */
- STATE_WATCHPOINTS (sd)->pc = &(PC);
- STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
/* Initialize the mechanism for doing insn profiling. */
sim_add_option_table (sd, NULL, mips_options);
- /* getopt will print the error message so we just have to exit if this fails.
- FIXME: Hmmm... in the case of gdb we need getopt to call
- print_filtered. */
+ /* The parser will print an error message for us, so we silently return. */
if (sim_parse_args (sd, argv) != SIM_RC_OK)
{
/* Uninstall the modules to avoid memory leaks,
/* Look for largest memory region defined on command-line at
phys address 0. */
-#ifdef SIM_HAVE_FLATMEM
- mem_size = STATE_MEM_SIZE (sd);
-#endif
for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next)
{
/* If we find an entry at address 0, then we will end up
mem_size = (match->modulo != 0
? match->modulo : match->nr_bytes);
/* Delete old region. */
- sim_do_commandf (sd, "memory delete %d:0x%lx@%d",
+ sim_do_commandf (sd, "memory delete %d:0x%" PRIxTW "@%d",
match->space, match->addr, match->level);
}
else if (mem_size == 0)
if (mem_size > K1SIZE)
mem_size = K1SIZE;
/* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x%%0x%lx,0x%0x",
K1BASE, K1SIZE, (long)mem_size, K0BASE);
+ if (WITH_TARGET_WORD_BITSIZE == 64)
+ sim_do_commandf (sd, "memory alias 0x%x,0x%" PRIxTW ",0x%" PRIxTA,
+ (K0BASE), mem_size, EXTENDED(K0BASE));
}
device_init(sd);
STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
/* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x9FC00000,
4 * 1024 * 1024, /* 4 MB */
0xBFC00000);
/* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x80000000,
4 * 1024 * 1024, /* 4 MB */
0xA0000000);
for (i=0; i<8; i++) /* 32 MB total */
{
unsigned size = 4 * 1024 * 1024; /* 4 MB */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x88000000 + (i * size),
size,
0xA8000000 + (i * size));
/* --- memory --- */
/* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x9FC00000,
4 * 1024 * 1024, /* 4 MB */
0xBFC00000);
/* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x80000000,
4 * 1024 * 1024, /* 4 MB */
0xA0000000);
for (i=0; i<8; i++) /* 32 MB total */
{
unsigned size = 4 * 1024 * 1024; /* 4 MB */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x",
0x88000000 + (i * size),
size,
0xA8000000 + (i * size));
/* Dummy memory regions for unsimulated devices - sorted by address */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400); /* ISA I/O */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004); /* ISA ctl */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004); /* LED/switch */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004); /* RTC */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004); /* RTC */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900); /* DRAMC */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c); /* EBIF */
- sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB1000000, 0x400); /* ISA I/O */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2100000, 0x004); /* ISA ctl */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2500000, 0x004); /* LED/switch */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2700000, 0x004); /* RTC */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB3C00000, 0x004); /* RTC */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFF8000, 0x900); /* DRAMC */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFF9000, 0x200); /* EBIF */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFFE000, 0x01c); /* EBIF */
+ sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFFF500, 0x300); /* PIO */
/* --- simulated devices --- */
{
/* FIXME: poking at dv-sockser internals, use tcp backend if
--sockser_addr option was given.*/
+#ifdef HAVE_DV_SOCKSER
extern char* sockser_addr;
- if(sockser_addr == NULL)
+#else
+# define sockser_addr NULL
+#endif
+ if (sockser_addr == NULL)
sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio");
else
sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp");
if (idt_monitor_base != 0)
{
unsigned loop;
- unsigned idt_monitor_size = 1 << 11;
+ address_word idt_monitor_size = 1 << 11;
/* the default monitor region */
- sim_do_commandf (sd, "memory region 0x%x,0x%x",
- idt_monitor_base, idt_monitor_size);
+ if (WITH_TARGET_WORD_BITSIZE == 64)
+ sim_do_commandf (sd, "memory alias 0x%x,0x%" PRIxTW ",0x%" PRIxTA,
+ idt_monitor_base, idt_monitor_size,
+ EXTENDED (idt_monitor_base));
+ else
+ sim_do_commandf (sd, "memory region 0x%x,0x%" PRIxTA,
+ idt_monitor_base, idt_monitor_size);
/* Entry into the IDT monitor is via fixed address vectors, and
not using machine instructions. To avoid clashing with use of
{
SIM_CPU *cpu = STATE_CPU (sd, i);
+ CPU_REG_FETCH (cpu) = mips_reg_fetch;
+ CPU_REG_STORE (cpu) = mips_reg_store;
CPU_PC_FETCH (cpu) = mips_pc_get;
CPU_PC_STORE (cpu) = mips_pc_set;
}
}
void
-sim_close (SIM_DESC sd, int quitting)
+mips_sim_close (SIM_DESC sd, int quitting)
{
-#ifdef DEBUG
- printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
-#endif
-
-
- /* "quitting" is non-zero if we cannot hang on errors */
-
- /* shut down modules */
- sim_module_uninstall (sd);
-
- /* Ensure that any resources allocated through the callback
- mechanism are released: */
- sim_io_shutdown (sd);
-
#if WITH_TRACE_ANY_P
if (tracefh != NULL && tracefh != stderr)
fclose(tracefh);
tracefh = NULL;
#endif
-
- /* FIXME - free SD */
-
- return;
}
-
-int
-sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
+static int
+mips_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
{
- int index;
- sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
-
- /* Return the number of bytes written, or zero if error. */
-#ifdef DEBUG
- sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
-#endif
-
- /* We use raw read and write routines, since we do not want to count
- the GDB memory accesses in our statistics gathering. */
-
- for (index = 0; index < size; index++)
- {
- address_word vaddr = (address_word)addr + index;
- address_word paddr;
- int cca;
- if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
- break;
- if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
- break;
- }
-
- return(index);
-}
-
-int
-sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
-{
- int index;
- sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
-
- /* Return the number of bytes read, or zero if error. */
-#ifdef DEBUG
- sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
-#endif /* DEBUG */
-
- for (index = 0; (index < size); index++)
- {
- address_word vaddr = (address_word)addr + index;
- address_word paddr;
- int cca;
- if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
- break;
- if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
- break;
- }
-
- return(index);
-}
-
-int
-sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
-{
- sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
while the simulator uses host byte order */
-#ifdef DEBUG
- sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
-#endif /* DEBUG */
/* Unfortunately this suffers from the same problem as the register
numbering one. We need to know what the width of each logical
if (cpu->register_widths[rn] == 0)
{
- sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
+ sim_io_eprintf (CPU_STATE (cpu), "Invalid register width for %d (register store ignored)\n", rn);
return 0;
}
-
-
if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR)
{
cpu->fpr_state[rn - FGR_BASE] = fmt_uninterpreted;
return 0;
}
-int
-sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
+static int
+mips_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
{
- sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
/* NOTE: gdb (the client) stores registers in target byte order
while the simulator uses host byte order */
-#ifdef DEBUG
-#if 0 /* FIXME: doesn't compile */
- sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
-#endif
-#endif /* DEBUG */
if (cpu->register_widths[rn] == 0)
{
- sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
+ sim_io_eprintf (CPU_STATE (cpu), "Invalid register width for %d (register fetch ignored)\n", rn);
return 0;
}
-
-
/* Any floating point register */
if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR)
{
}
SIM_RC
-sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
+sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
+ char * const *argv, char * const *env)
{
#ifdef DEBUG
for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
{
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
- CPU_PC_SET (cpu, (unsigned64) bfd_get_start_address (abfd));
+ sim_cia pc = bfd_get_start_address (abfd);
+
+ /* The 64-bit BFD sign-extends MIPS addresses to model
+ 32-bit compatibility segments with 64-bit addressing.
+ These addresses work as is on 64-bit targets but
+ can be truncated for 32-bit targets. */
+ if (WITH_TARGET_WORD_BITSIZE == 32)
+ pc = (unsigned32) pc;
+
+ CPU_PC_SET (cpu, pc);
}
}
return SIM_RC_OK;
}
+/* stat structures from MIPS32/64. */
+static const char stat32_map[] =
+"st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2"
+":st_rdev,2:st_size,4:st_atime,4:st_spare1,4:st_mtime,4:st_spare2,4"
+":st_ctime,4:st_spare3,4:st_blksize,4:st_blocks,4:st_spare4,8";
+
+static const char stat64_map[] =
+"st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2"
+":st_rdev,2:st_size,8:st_atime,8:st_spare1,8:st_mtime,8:st_spare2,8"
+":st_ctime,8:st_spare3,8:st_blksize,8:st_blocks,8:st_spare4,16";
+
+/* Map for calls using the host struct stat. */
+static const CB_TARGET_DEFS_MAP CB_stat_map[] =
+{
+ { "stat", CB_SYS_stat, 15 },
+ { 0, -1, -1 }
+};
/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
/* The following callback functions are available, however the
monitor we are simulating does not make use of them: get_errno,
- isatty, lseek, rename, system, time and unlink */
+ isatty, rename, system and time. */
switch (reason)
{
break;
}
+ case 13: /* int unlink(const char *path) */
+ {
+ char *path = fetch_str (sd, A0);
+ V0 = sim_io_unlink (sd, path);
+ free (path);
+ break;
+ }
+
+ case 14: /* int lseek(int fd, int offset, int whence) */
+ {
+ V0 = sim_io_lseek (sd, A0, A1, A2);
+ break;
+ }
+
+ case 15: /* int stat(const char *path, struct stat *buf); */
+ {
+ /* As long as the infrastructure doesn't cache anything
+ related to the stat mapping, this trick gets us a dual
+ "struct stat"-type mapping in the least error-prone way. */
+ host_callback *cb = STATE_CALLBACK (sd);
+ const char *saved_map = cb->stat_map;
+ CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map;
+ bfd *prog_bfd = STATE_PROG_BFD (sd);
+ int is_elf32bit = (elf_elfheader(prog_bfd)->e_ident[EI_CLASS] ==
+ ELFCLASS32);
+ static CB_SYSCALL s;
+ CB_SYSCALL_INIT (&s);
+ s.func = 15;
+ /* Mask out the sign extension part for 64-bit targets because the
+ MIPS simulator's memory model is still 32-bit. */
+ s.arg1 = A0 & 0xFFFFFFFF;
+ s.arg2 = A1 & 0xFFFFFFFF;
+ s.p1 = (PTR) sd;
+ s.p2 = (PTR) cpu;
+ s.read_mem = sim_syscall_read_mem;
+ s.write_mem = sim_syscall_write_mem;
+
+ cb->syscall_map = (CB_TARGET_DEFS_MAP *) CB_stat_map;
+ cb->stat_map = is_elf32bit ? stat32_map : stat64_map;
+
+ if (cb_syscall (cb, &s) != CB_RC_OK)
+ sim_engine_halt (sd, cpu, NULL, mips_pc_get (cpu),
+ sim_stopped, SIM_SIGILL);
+
+ V0 = s.result;
+ cb->stat_map = saved_map;
+ cb->syscall_map = saved_syscall_map;
+ break;
+ }
+
case 17: /* void _exit() */
{
sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n");
{
address_word s = A0;
unsigned char c;
- signed_word *ap = &A1; /* 1st argument */
+ address_word *ap = &A1; /* 1st argument */
/* This isn't the quickest way, since we call the host print
routine for every character almost. But it does avoid
having to allocate and manage a temporary string buffer. */
sim_io_printf(sd,"<binary not supported>");
else
{
- sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c);
- if (longlong)
- sim_io_printf(sd, tmp, lv);
- else
- sim_io_printf(sd, tmp, (int)lv);
+#define _P(c, fmt64, fmt32) \
+ case c: \
+ if (longlong) \
+ sim_io_printf (sd, "%" fmt64, lv); \
+ else \
+ sim_io_printf (sd, "%" fmt32, (int)lv); \
+ break;
+#define P(c, fmtc) _P(c, PRI##fmtc##64, PRI##fmtc##32)
+ switch (c)
+ {
+ P('d', d)
+ P('o', o)
+ P('x', x)
+ P('X', X)
+ P('u', u)
+ }
}
+#undef P
+#undef _P
}
else if (strchr ("eEfgG", c))
{
double dbl = *(double*)(ap++);
- sprintf (tmp, "%%%d.%d%c", width, trunc, c);
- sim_io_printf (sd, tmp, dbl);
+
+#define P(c, fmtc) \
+ case c: \
+ sim_io_printf (sd, "%*.*" #fmtc, width, trunc, dbl); \
+ break;
+ switch (c)
+ {
+ P('e', e)
+ P('E', E)
+ P('f', f)
+ P('g', g)
+ P('G', G)
+ }
+#undef P
trunc = 0;
}
}
uword64 vaddr,
signed_word val)
{
- address_word paddr;
- int uncached;
+ address_word paddr = vaddr;
if ((vaddr & 3) != 0)
SignalExceptionAddressStore ();
else
{
- if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
- isTARGET, isREAL))
- {
- const uword64 mask = 7;
- uword64 memval;
- unsigned int byte;
-
- paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
- byte = (vaddr & mask) ^ (BigEndianCPU << 2);
- memval = ((uword64) val) << (8 * byte);
- StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
- isREAL);
- }
+ const uword64 mask = 7;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
+ byte = (vaddr & mask) ^ (BigEndianCPU << 2);
+ memval = ((uword64) val) << (8 * byte);
+ StoreMemory (AccessLength_WORD, memval, 0, paddr, vaddr,
+ isREAL);
}
}
}
else
{
- address_word paddr;
- int uncached;
-
- if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
- isTARGET, isREAL))
- {
- const uword64 mask = 0x7;
- const unsigned int reverse = ReverseEndian ? 1 : 0;
- const unsigned int bigend = BigEndianCPU ? 1 : 0;
- uword64 memval;
- unsigned int byte;
-
- paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
- LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
- isDATA, isREAL);
- byte = (vaddr & mask) ^ (bigend << 2);
- return EXTEND32 (memval >> (8 * byte));
- }
+ address_word paddr = vaddr;
+ const uword64 mask = 0x7;
+ const unsigned int reverse = ReverseEndian ? 1 : 0;
+ const unsigned int bigend = BigEndianCPU ? 1 : 0;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
+ LoadMemory (&memval, NULL, AccessLength_WORD, paddr, vaddr, isDATA,
+ isREAL);
+ byte = (vaddr & mask) ^ (bigend << 2);
+ return EXTEND32 (memval >> (8 * byte));
}
return 0;
int type,
SIM_ADDR address,
int width,
- char *comment,...)
+ const char *comment, ...)
{
if (STATE & simTRACE) {
va_list ap;
decode_coproc (SIM_DESC sd,
sim_cpu *cpu,
address_word cia,
- unsigned int instruction)
+ unsigned int instruction,
+ int coprocnum,
+ CP0_operation op,
+ int rt,
+ int rd,
+ int sel)
{
- int coprocnum = ((instruction >> 26) & 3);
-
switch (coprocnum)
{
case 0: /* standard CPU control and cache registers */
{
- int code = ((instruction >> 21) & 0x1F);
- int rt = ((instruction >> 16) & 0x1F);
- int rd = ((instruction >> 11) & 0x1F);
- int tail = instruction & 0x3ff;
/* R4000 Users Manual (second edition) lists the following CP0
instructions:
CODE><-RT><RD-><--TAIL--->
CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
ERET Exception return (VR4100 = 01000010000000000000000000011000)
*/
- if (((code == 0x00) || (code == 0x04) /* MFC0 / MTC0 */
- || (code == 0x01) || (code == 0x05)) /* DMFC0 / DMTC0 */
- && tail == 0)
+ if (((op == cp0_mfc0) || (op == cp0_mtc0) /* MFC0 / MTC0 */
+ || (op == cp0_dmfc0) || (op == cp0_dmtc0)) /* DMFC0 / DMTC0 */
+ && sel == 0)
{
- /* Clear double/single coprocessor move bit. */
- code &= ~1;
-
- /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */
-
switch (rd) /* NOTEs: Standard CP0 registers */
{
/* 0 = Index R4000 VR4100 VR4300 */
case 8:
/* 8 = BadVAddr R4000 VR4100 VR4300 */
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = (signed_word) (signed_address) COP0_BADVADDR;
else
COP0_BADVADDR = GPR[rt];
#endif /* SUBTARGET_R3900 */
case 12:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = SR;
else
SR = GPR[rt];
break;
/* 13 = Cause R4000 VR4100 VR4300 */
case 13:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = CAUSE;
else
CAUSE = GPR[rt];
break;
/* 14 = EPC R4000 VR4100 VR4300 */
case 14:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = (signed_word) (signed_address) EPC;
else
EPC = GPR[rt];
#ifdef SUBTARGET_R3900
/* 16 = Debug */
case 16:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = Debug;
else
Debug = GPR[rt];
#else
/* 16 = Config R4000 VR4100 VR4300 */
case 16:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = C0_CONFIG;
else
/* only bottom three bits are writable */
#ifdef SUBTARGET_R3900
/* 17 = Debug */
case 17:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = DEPC;
else
DEPC = GPR[rt];
GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
/* CPR[0,rd] = GPR[rt]; */
default:
- if (code == 0x00)
+ if (op == cp0_mfc0 || op == cp0_dmfc0)
GPR[rt] = (signed_word) (signed32) COP0_GPR[rd];
else
COP0_GPR[rd] = GPR[rt];
#endif
}
}
- else if ((code == 0x00 || code == 0x01)
+ else if ((op == cp0_mfc0 || op == cp0_dmfc0)
&& rd == 16)
{
/* [D]MFC0 RT,C0_CONFIG,SEL */
signed32 cfg = 0;
- switch (tail & 0x07)
+ switch (sel)
{
case 0:
cfg = C0_CONFIG;
}
GPR[rt] = cfg;
}
- else if (code == 0x10 && (tail & 0x3f) == 0x18)
+ else if (op == cp0_eret && sel == 0x18)
{
/* ERET */
if (SR & status_ERL)
SR &= ~status_EXL;
}
}
- else if (code == 0x10 && (tail & 0x3f) == 0x10)
+ else if (op == cp0_rfe && sel == 0x10)
{
/* RFE */
#ifdef SUBTARGET_R3900
/* TODO: CACHE register */
#endif /* SUBTARGET_R3900 */
}
- else if (code == 0x10 && (tail & 0x3f) == 0x1F)
+ else if (op == cp0_deret && sel == 0x1F)
{
/* DERET */
Debug &= ~Debug_DM;