Add ABFD argument to sim_open call. Pass through to sim_config so
[deliverable/binutils-gdb.git] / sim / v850 / interp.c
index 1cd990e8ecee94f173304c5ba2148295e1b3e740..bbc29f199334d9d2a5bbd36174b5813fc9f47764 100644 (file)
 #include <signal.h>
 #include "sysdep.h"
 #include "bfd.h"
-#include "remote-sim.h"
-#include "callback.h"
 
 #include "v850_sim.h"
 
-#define IMEM_SIZE 18   /* V850 instruction memory size is 18 bits */
-#define DMEM_SIZE 16   /* Data memory */
+enum interrupt_type
+{
+  int_none,
+  int_reset,
+  int_nmi,
+  int_intov1,
+  int_intp10,
+  int_intp11,
+  int_intp12,
+  int_intp13,
+  int_intcm4,
+  num_int_types
+};
+
+enum interrupt_cond_type
+{
+  int_cond_none,
+  int_cond_pc,
+  int_cond_time
+};
+
+struct interrupt_generator
+{
+  enum interrupt_type type;
+  enum interrupt_cond_type cond_type;
+  int number;
+  int address;
+  int time;
+  int enabled;
+  struct interrupt_generator *next;
+};
+
+char *interrupt_names[] = {
+  "",
+  "reset",
+  "nmi",
+  "intov1",
+  "intp10",
+  "intp11",
+  "intp12",
+  "intp13",
+  "intcm4",
+  NULL
+};
+
+struct interrupt_generator *intgen_list;
+
+/* True if a non-maskable (such as NMI or reset) interrupt generator
+   is present.  */
+
+static int have_nm_generator;
+
+#ifndef INLINE
+#ifdef __GNUC__
+#define INLINE inline
+#else
+#define INLINE
+#endif
+#endif
+
+/* These default values correspond to expected usage for the chip.  */
+
+SIM_ADDR rom_size = 0x8000;
+SIM_ADDR low_end = 0x200000;
+SIM_ADDR high_start = 0xffe000;
 
-uint16 OP[4];
+SIM_ADDR high_base;
+
+host_callback *v850_callback;
+
+int v850_debug;
+
+/* non-zero if we opened prog_bfd */
+static int prog_bfd_was_opened_p;
+bfd *prog_bfd;
+
+static SIM_OPEN_KIND sim_kind;
+static char *myname;
+
+uint32 OP[4];
 
 static struct hash_entry *lookup_hash PARAMS ((uint32 ins));
+static long hash PARAMS ((long));
+static void do_format_1_2 PARAMS ((uint32));
+static void do_format_3 PARAMS ((uint32));
+static void do_format_4 PARAMS ((uint32));
+static void do_format_5 PARAMS ((uint32));
+static void do_format_6 PARAMS ((uint32));
+static void do_format_7 PARAMS ((uint32));
+static void do_format_8 PARAMS ((uint32));
+static void do_format_9_10 PARAMS ((uint32));
+static void init_system PARAMS ((void));
 
 #define MAX_HASH  63
+
 struct hash_entry
 {
   struct hash_entry *next;
@@ -24,32 +109,26 @@ struct hash_entry
 
 struct hash_entry hash_table[MAX_HASH+1];
 
-static long 
+
+static INLINE long 
 hash(insn)
      long insn;
 {
-  if ((insn & 0x30) == 0
-      || (insn & 0x38) == 0x10)
+  if (   (insn & 0x0600) == 0
+      || (insn & 0x0700) == 0x0200
+      || (insn & 0x0700) == 0x0600
+      || (insn & 0x0780) == 0x0700)
     return (insn & 0x07e0) >> 5;
-  if ((insn & 0x3c) == 0x18
-      || (insn & 0x3c) == 0x1c
-      || (insn & 0x3c) == 0x20
-      || (insn & 0x3c) == 0x24
-      || (insn & 0x3c) == 0x28
-      || (insn & 0x3c) == 0x23)
-    return (insn & 0x07c0) >> 6;
-  if ((insn & 0x38) == 0x30)
-    return (insn & 0x07e0) >> 5;
-  /* What about sub-op field? XXX */
-  if ((insn & 0x38) == 0x38)
-    return (insn & 0x07e0) >> 5;
-  if ((insn & 0x3e) == 0x3c)
+
+  if ((insn & 0x0700) == 0x0300
+      || (insn & 0x0700) == 0x0400
+      || (insn & 0x0700) == 0x0500)
+    return (insn & 0x0780) >> 7;
+
+  if ((insn & 0x07c0) == 0x0780)
     return (insn & 0x07c0) >> 6;
-  if ((insn & 0x3f) == 0x3e)
-    return (insn & 0xc7e0) >> 5;
-  /* Not really correct.  XXX */
-  return insn & 0xffffffff;
-  
+
+  return (insn & 0x07e0) >> 5;
 }
 
 static struct hash_entry *
@@ -60,11 +139,11 @@ lookup_hash (ins)
 
   h = &hash_table[hash(ins)];
 
-  while ( (ins & h->mask) != h->opcode)
+  while ((ins & h->mask) != h->opcode)
     {
       if (h->next == NULL)
        {
-         printf ("ERROR looking up hash for %x\n",ins);
+         (*v850_callback->printf_filtered) (v850_callback, "ERROR looking up hash for 0x%x, PC=0x%x\n", ins, PC);
          exit(1);
        }
       h = h->next;
@@ -72,218 +151,283 @@ lookup_hash (ins)
   return (h);
 }
 
-uint32
-get_longword (x)
-      uint8 *x;
+/* FIXME These would more efficient to use than load_mem/store_mem,
+   but need to be changed to use the memory map.  */
+
+uint8
+get_byte (x)
+     uint8 *x;
 {
-  uint8 *a = x;
-  return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
+  return *x;
 }
 
-int64
-get_longlong (x)
-      uint8 *x;
+uint16
+get_half (x)
+     uint8 *x;
 {
   uint8 *a = x;
-  return ((int64)a[0]<<56) + ((int64)a[1]<<48) + ((int64)a[2]<<40) + ((int64)a[3]<<32) +
-    ((int64)a[4]<< 24) + ((int64)a[5]<<16) + ((int64)a[6]<<8) + (int64)a[7];
+  return (a[1] << 8) + (a[0]);
 }
 
-uint16
+uint32
 get_word (x)
       uint8 *x;
 {
   uint8 *a = x;
-  return ((uint16)a[0]<<8) + a[1];
+  return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
 }
 
-
 void
-write_word (addr, data)
+put_byte (addr, data)
      uint8 *addr;
-     uint16 data;
+     uint8 data;
 {
   uint8 *a = addr;
-  a[0] = data >> 8;
-  a[1] = data & 0xff;
+  a[0] = data;
 }
 
 void
-write_longword (addr, data)
+put_half (addr, data)
      uint8 *addr;
-     uint32 data;
+     uint16 data;
 {
-  addr[0] = (data >> 24) & 0xff;
-  addr[1] = (data >> 16) & 0xff;
-  addr[2] = (data >> 8) & 0xff;
-  addr[3] = data & 0xff;
+  uint8 *a = addr;
+  a[0] = data & 0xff;
+  a[1] = (data >> 8) & 0xff;
 }
 
 void
-write_longlong (addr, data)
+put_word (addr, data)
      uint8 *addr;
-     int64 data;
+     uint32 data;
 {
   uint8 *a = addr;
-  a[0] = data >> 56;
-  a[1] = (data >> 48) & 0xff;
-  a[2] = (data >> 40) & 0xff;
-  a[3] = (data >> 32) & 0xff;
-  a[4] = (data >> 24) & 0xff;
-  a[5] = (data >> 16) & 0xff;
-  a[6] = (data >> 8) & 0xff;
-  a[7] = data & 0xff;
+  a[0] = data & 0xff;
+  a[1] = (data >> 8) & 0xff;
+  a[2] = (data >> 16) & 0xff;
+  a[3] = (data >> 24) & 0xff;
 }
 
-static void
-get_operands (struct simops *s, uint32 ins)
+uint8 *
+map (addr)
+     SIM_ADDR addr;
 {
-  int i, shift, bits, flags;
-  uint32 mask;
-  for (i=0; i < s->numops; i++)
+  uint8 *p;
+
+  /* Mask down to 24 bits. */
+  addr &= 0xffffff;
+
+  if (addr < low_end)
+    {
+      /* "Mirror" the addresses below 1MB. */
+      if (addr < 0x100000)
+       addr &= (rom_size - 1);
+      else
+       addr += (rom_size - 0x100000);
+      return (uint8 *) (addr + State.mem);
+    }
+  else if (addr >= high_start)
     {
-      shift = s->operands[3*i];
-      bits = s->operands[3*i+1];
-      flags = s->operands[3*i+2];
-      mask = 0x7FFFFFFF >> (31 - bits);
-      OP[i] = (ins >> shift) & mask;
+      /* If in the peripheral I/O region, mirror 1K region across 4K,
+        and similarly if in the internal RAM region.  */
+      if (addr >= 0xfff000)
+       addr &= 0xfff3ff;
+      else if (addr >= 0xffe000)
+       addr &= 0xffe3ff;
+      return (uint8 *) (addr - high_start + high_base + State.mem);
+    }
+  else
+    {
+      fprintf (stderr, "segmentation fault: access address: %x not below %x or above %x [ep = %x]\n", addr, low_end, high_start, State.regs[30]);
+      
+      /* Signal a memory error. */
+      State.exception = SIGSEGV;
+      /* Point to a location not in main memory - renders invalid
+        addresses harmless until we get back to main insn loop. */
+      return (uint8 *) &(State.dummy_mem);
     }
 }
 
-static void
-do_format_1_2 (insn)
-     uint32 insn;
+uint32
+load_mem (addr, len)
+     SIM_ADDR addr;
+     int len;
 {
-  struct hash_entry *h;
-  printf("format 1 or 2 0x%x\n", insn);
+  uint8 *p = map (addr);
 
-  h = lookup_hash (insn);
-  OP[0] = insn & 0x1f;
-  OP[1] = (insn >> 11) & 0x1f;
-  (h->ops->func) ();
+  switch (len)
+    {
+    case 1:
+      return p[0];
+    case 2:
+      return p[1] << 8 | p[0];
+    case 4:
+      return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
+    default:
+      abort ();
+    }
 }
 
-static void
-do_format_3 (insn)
-     uint32 insn;
+void
+store_mem (addr, len, data)
+     SIM_ADDR addr;
+     int len;
+     uint32 data;
 {
-  struct hash_entry *h;
-  printf("format 3 0x%x\n", insn);
+  uint8 *p = map (addr);
 
-  h = lookup_hash (insn);
-  OP[0] = (((insn & 0x70) >> 4) | ((insn & 0xf800) >> 8)) << 1;
-  (h->ops->func) ();
-}
-
-static void
-do_format_4 (insn)
-     uint32 insn;
-{
-  printf("format 4 0x%x\n", insn);
+  switch (len)
+    {
+    case 1:
+      p[0] = data;
+      return;
+    case 2:
+      p[0] = data;
+      p[1] = data >> 8;
+      return;
+    case 4:
+      p[0] = data;
+      p[1] = data >> 8;
+      p[2] = data >> 16;
+      p[3] = data >> 24;
+      return;
+    default:
+      abort ();
+    }
 }
 
-static void
-do_format_5 (insn)
-     uint32 insn;
-{
-  printf("format 5 0x%x\n", insn);
-}
+void
+sim_size (power)
+     int power;
 
-static void
-do_format_6 (insn)
-     uint32 insn;
 {
-  struct hash_entry *h;
-  printf("format 6 0x%x\n", insn);
+  int totsize;
 
-  h = lookup_hash (insn);
-  OP[0] = (insn >> 16) & 0xffff;
-  OP[1] = insn & 0x1f;
-  OP[2] = (insn >> 11) & 0x1f;
-  (h->ops->func) ();
-}
+  if (State.mem)
+    free (State.mem);
 
-static void
-do_format_7 (insn)
-     uint32 insn;
-{
-  printf("format 7 0x%x\n", insn);
-}
+  totsize = rom_size + (low_end - 0x100000) + (0x1000000 - high_start);
 
-static void
-do_format_8 (insn)
-     uint32 insn;
-{
-  printf("format 8 0x%x\n", insn);
-}
+  high_base = rom_size + (low_end - 0x100000);
 
-static void
-do_formats_9_10 (insn)
-     uint32 insn;
-{
-  struct hash_entry *h;
-  printf("formats 9 and 10 0x%x\n", insn);
-
-  h = lookup_hash (insn);
-  OP[0] = insn & 0x1f;
-  OP[1] = (insn >> 11) & 0x1f;
-  (h->ops->func) ();
+  State.mem = (uint8 *) calloc (1, totsize);
+  if (!State.mem)
+    {
+      (*v850_callback->printf_filtered) (v850_callback, "Allocation of main memory failed.\n");
+      exit (1);
+    }
 }
 
 void
-sim_size (power)
-     int power;
-
+sim_set_memory_map (spec)
+     char *spec;
 {
-  if (State.imem)
+  char *reststr, *nreststr;
+  SIM_ADDR new_low_end, new_high_start;
+
+  new_low_end = low_end;
+  new_high_start = high_start;
+  if (! strncmp (spec, "hole=", 5))
+    {
+      new_low_end = sim_parse_number (spec + 5, &reststr);
+      if (new_low_end < 0x100000)
+       {
+         (*v850_callback->printf_filtered) (v850_callback,
+                                            "Low end must be at least 0x100000\n");
+         return;
+       }
+      if (*reststr == ',')
+       {
+         ++reststr;
+         new_high_start = sim_parse_number (reststr, &nreststr);
+         /* FIXME Check high_start also */
+       }
+      (*v850_callback->printf_filtered) (v850_callback,
+                                        "Hole goes from 0x%x to 0x%x\n",
+                                        new_low_end, new_high_start);
+    }
+  else
     {
-      free (State.imem);
-      free (State.dmem);
+      (*v850_callback->printf_filtered) (v850_callback, "Invalid specification for memory map, must be `hole=<m>[,<n>]'\n");
     }
 
-  State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE);
-  State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE);
-  if (!State.imem || !State.dmem )
+  if (new_low_end != low_end || new_high_start != high_start)
     {
-      fprintf (stderr,"Memory allocation failed.\n");
-      exit(1);
+      low_end = new_low_end;
+      high_start = new_high_start;
+      if (State.mem)
+       {
+         (*v850_callback->printf_filtered) (v850_callback, "Reconfiguring memory (old contents will be lost)\n");
+         sim_size (1);
+       }
     }
-  printf ("Allocated %d bytes instruction memory and\n",1<<IMEM_SIZE);
-  printf ("          %d bytes data memory.\n",1<<DMEM_SIZE);
+}
+
+/* Parse a number in hex, octal, or decimal form.  */
+
+int
+sim_parse_number (str, rest)
+     char *str, **rest;
+{
+  if (str[0] == '0' && str[1] == 'x')
+    return strtol (str, rest, 16);
+  else if (str[0] == '0')
+    return strtol (str, rest, 16);
+  else
+    return strtol (str, rest, 10);
 }
 
 static void
 init_system ()
 {
-  if (!State.imem)
+  if (!State.mem)
     sim_size(1);
 }
 
 int
-sim_write (addr, buffer, size)
+sim_write (sd, addr, buffer, size)
+     SIM_DESC sd;
      SIM_ADDR addr;
      unsigned char *buffer;
      int size;
 {
   int i;
+
   init_system ();
 
-  /* printf ("sim_write %d bytes to 0x%x\n",size,addr); */
   for (i = 0; i < size; i++)
-    {
-      State.imem[i+addr] = buffer[i]; 
-    }
+    store_mem (addr + i, 1, buffer[i]);
+
   return size;
 }
 
-void
-sim_open (args)
-     char *args;
+SIM_DESC
+sim_open (kind, cb, abfd, argv)
+     SIM_OPEN_KIND kind;
+     host_callback *cb;
+     struct _bfd *abfd;
+     char **argv;
 {
   struct simops *s;
-  struct hash_entry *h, *prev;
-  if (args != NULL)
-      printf ("sim_open %s\n",args);
+  struct hash_entry *h;
+  char **p;
+
+  sim_kind = kind;
+  myname = argv[0];
+  v850_callback = cb;
+
+  if (argv != NULL)
+    {
+      for (p = argv + 1; *p; ++p)
+       {
+#ifdef DEBUG
+         if (strcmp (*p, "-t") == 0)
+           v850_debug = DEBUG;
+         else
+#endif
+           (*v850_callback->printf_filtered) (v850_callback, "ERROR: unsupported option(s): %s\n",*p);
+       }
+    }
 
   /* put all the opcodes in the hash table */
   for (s = Simops; s->func; s++)
@@ -296,207 +440,491 @@ sim_open (args)
 
       if (h->ops)
        {
-         h->next = calloc(1,sizeof(struct hash_entry));
+         h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
          h = h->next;
        }
       h->ops = s;
       h->mask = s->mask;
       h->opcode = s->opcode;
     }
+
+  /* fudge our descriptor for now */
+  return (SIM_DESC) 1;
 }
 
 
 void
-sim_close (quitting)
+sim_close (sd, quitting)
+     SIM_DESC sd;
      int quitting;
 {
-  /* nothing to do */
+  if (prog_bfd != NULL && prog_bfd_was_opened_p)
+    bfd_close (prog_bfd);
 }
 
 void
 sim_set_profile (n)
      int n;
 {
-  printf ("sim_set_profile %d\n",n);
+  (*v850_callback->printf_filtered) (v850_callback, "sim_set_profile %d\n", n);
 }
 
 void
 sim_set_profile_size (n)
      int n;
 {
-  printf ("sim_set_profile_size %d\n",n);
+  (*v850_callback->printf_filtered) (v850_callback, "sim_set_profile_size %d\n", n);
+}
+
+time_t start_time;
+
+static void do_interrupt PARAMS ((enum interrupt_type));
+
+int
+sim_stop (sd)
+     SIM_DESC sd;
+{
+  return 0;
 }
 
 void
-sim_resume (step, siggnal)
+sim_resume (sd, step, siggnal)
+     SIM_DESC sd;
      int step, siggnal;
 {
   uint32 inst, opcode;
-  int i;
   reg_t oldpc;
+  struct interrupt_generator *intgen;
+  time_t now;
 
-/*   printf ("sim_resume (%d,%d)  PC=0x%x\n",step,siggnal,PC); */
+  if (step)
+    State.exception = SIGTRAP;
+  else
+    State.exception = 0;
 
- if (step)
-   State.exception = SIGTRAP;
- else
-   State.exception = 0;
- do
-   {
-     inst = RLW (PC);
-     oldpc = PC;
-     opcode = (inst & 0x07e0) >> 5;
-     if ((opcode & 0x30) == 0
-        || (opcode & 0x38) == 0x10)
-       {
-        do_format_1_2 (inst & 0xffff);
-        PC += 2;
-       }
-     else if ((opcode & 0x3C) == 0x18
-             || (opcode & 0x3C) == 0x1C
-             || (opcode & 0x3C) == 0x20
-             || (opcode & 0x3C) == 0x24
-             || (opcode & 0x3C) == 0x28)
-       {
-        do_format_4 (inst & 0xffff);
-        PC += 2;
-       }
-     else if ((opcode & 0x3C) == 0x23)
-       {
-        do_format_3 (inst & 0xffff);
-        /* No PC update, it's done in the instruction.  */
-       }
-     else if ((opcode & 0x38) == 0x30)
-       {
-        do_format_6 (inst);
-        PC += 4;
-       }
-     else if ((opcode & 0x3C) == 0x38)
-       {
-        do_format_7 (inst);
-        PC += 4;
-       }
-     else if ((opcode & 0x3E) == 0x3C)
-       {
-        do_format_5 (inst);
-        PC += 4;
-       }
-     else if ((opcode & 0x3F) == 0x3E)
-       {
-        do_format_8 (inst);
-        PC += 4;
-       }
-     else
-       {
-        do_formats_9_10 (inst);
-        PC += 4;
-       }
-   } 
- while (!State.exception);
+  time (&start_time);
+
+  do
+    {
+      struct hash_entry * h;
+      /* Fetch the current instruction.  */
+      inst  = RLW (PC);
+      oldpc = PC;
+
+      h     = lookup_hash (inst);
+      OP[0] = inst & 0x1f;
+      OP[1] = (inst >> 11) & 0x1f;
+      OP[2] = (inst >> 16) & 0xffff;
+      OP[3] = inst;
+
+//      fprintf (stderr, "PC = %x, SP = %x\n", PC, SP );
+
+      if (inst == 0)
+       {
+         fprintf (stderr, "NOP encountered!\n");
+         break;
+       }
+      
+      PC += h->ops->func ();
+
+      if (oldpc == PC)
+       {
+         fprintf (stderr, "simulator loop at %x\n", PC );
+         break;
+       }
+      
+      /* Check for and handle pending interrupts.  */
+      if (intgen_list && (have_nm_generator || !(PSW & PSW_ID)))
+       {
+         intgen = NULL;
+         for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
+           {
+             if (intgen->cond_type == int_cond_pc
+                 && oldpc == intgen->address
+                 && intgen->enabled)
+               {
+                 break;
+               }
+             else if (intgen->cond_type == int_cond_time
+                      && intgen->enabled)
+               {
+                 time (&now);
+                 if (((long) now - (long) start_time) > intgen->time)
+                   {
+                     intgen->enabled = 0;
+                     break;
+                   }
+               }
+           }
+         if (intgen)
+           do_interrupt (intgen->type);
+       }
+      else if (State.pending_nmi)
+       {
+         State.pending_nmi = 0;
+         do_interrupt (int_nmi);
+       }
+    }
+  while (!State.exception);
+}
+
+static void
+do_interrupt (inttype)
+     enum interrupt_type inttype;
+{
+  /* Disable further interrupts.  */
+  PSW |= PSW_ID;
+  /* Indicate that we're doing interrupt not exception processing.  */
+  PSW &= ~PSW_EP;
+  if (inttype == int_reset)
+    {
+      PC = 0;
+      PSW = 0x20;
+      ECR = 0;
+      /* (Might be useful to init other regs with random values.) */
+    }
+  else if (inttype == int_nmi)
+    {
+      if (PSW & PSW_NP)
+       {
+         /* We're already working on an NMI, so this one must wait
+            around until the previous one is done.  The processor
+            ignores subsequent NMIs, so we don't need to count them.  */
+         State.pending_nmi = 1;
+       }
+      else
+       {
+         FEPC = PC;
+         FEPSW = PSW;
+         /* Set the FECC part of the ECR. */
+         ECR &= 0x0000ffff;
+         ECR |= 0x10;
+         PSW |= PSW_NP;
+         PC = 0x10;
+       }
+    }
+  else
+    {
+      EIPC = PC;
+      EIPSW = PSW;
+      /* Clear the EICC part of the ECR, will set below. */
+      ECR &= 0xffff0000;
+      switch (inttype)
+       {
+       case int_intov1:
+         PC = 0x80;
+         ECR |= 0x80;
+         break;
+       case int_intp10:
+         PC = 0x90;
+         ECR |= 0x90;
+         break;
+       case int_intp11:
+         PC = 0xa0;
+         ECR |= 0xa0;
+         break;
+       case int_intp12:
+         PC = 0xb0;
+         ECR |= 0xb0;
+         break;
+       case int_intp13:
+         PC = 0xc0;
+         ECR |= 0xc0;
+         break;
+       case int_intcm4:
+         PC = 0xd0;
+         ECR |= 0xd0;
+         break;
+       default:
+         /* Should never be possible.  */
+         abort ();
+         break;
+       }
+    }
 }
 
 int
-sim_trace ()
+sim_trace (sd)
+     SIM_DESC sd;
 {
-  printf ("sim_trace\n");
-  return 0;
+#ifdef DEBUG
+  v850_debug = DEBUG;
+#endif
+  sim_resume (sd, 0, 0);
+  return 1;
 }
 
 void
-sim_info (verbose)
+sim_info (sd, verbose)
+     SIM_DESC sd;
      int verbose;
 {
-  printf ("sim_info\n");
+  (*v850_callback->printf_filtered) (v850_callback, "sim_info\n");
 }
 
-void
-sim_create_inferior (start_address, argv, env)
-     SIM_ADDR start_address;
+SIM_RC
+sim_create_inferior (sd, argv, env)
+     SIM_DESC sd;
      char **argv;
      char **env;
 {
-  printf ("sim_create_inferior:  PC=0x%x\n",start_address);
-  PC = start_address;
+  return SIM_RC_OK;
 }
 
-
 void
-sim_kill ()
+sim_kill (sd)
+     SIM_DESC sd;
 {
   /* nothing to do */
 }
 
 void
-sim_set_callbacks(p)
+sim_set_callbacks (p)
      host_callback *p;
 {
-  printf ("sim_set_callbacks\n");
-  /* callback = p; */
+  v850_callback = p;
 }
 
+/* All the code for exiting, signals, etc needs to be revamped.
+
+   This is enough to get c-torture limping though.  */
+
 void
-sim_stop_reason (reason, sigrc)
+sim_stop_reason (sd, reason, sigrc)
+     SIM_DESC sd;
      enum sim_stop *reason;
      int *sigrc;
 {
-/*   printf ("sim_stop_reason:  PC=0x%x\n",PC); */
-
-  if (State.exception == SIGQUIT)
+  if (State.exception == SIG_V850_EXIT)
     {
       *reason = sim_exited;
-      *sigrc = State.exception;
+      *sigrc = State.regs[7];
     }
   else
     {
       *reason = sim_stopped;
       *sigrc = State.exception;
-    } 
+    }
 }
 
 void
-sim_fetch_register (rn, memory)
+sim_fetch_register (sd, rn, memory)
+     SIM_DESC sd;
      int rn;
      unsigned char *memory;
 {
-  *(uint32 *)memory = State.regs[rn];
-  /* printf ("sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */
+  put_word (memory, State.regs[rn]);
 }
  
 void
-sim_store_register (rn, memory)
+sim_store_register (sd, rn, memory)
+     SIM_DESC sd;
      int rn;
      unsigned char *memory;
 {
-  State.regs[rn]= *(uint32 *)memory;
-  /* printf ("store: r%d=0x%x\n",rn,State.regs[rn]); */
+  State.regs[rn] = get_word (memory);
 }
 
-sim_read (addr, buffer, size)
+int
+sim_read (sd, addr, buffer, size)
+     SIM_DESC sd;
      SIM_ADDR addr;
      unsigned char *buffer;
      int size;
 {
   int i;
   for (i = 0; i < size; i++)
-    {
-      buffer[i] = State.imem[addr + i];
-    }
+    buffer[i] = load_mem (addr + i, 1);
+
   return size;
 } 
 
+int current_intgen_number = 1;
+
 void
-sim_do_command (cmd)
+sim_set_interrupt (spec)
+     char *spec;
+{
+  int i, num;
+  char **argv;
+  struct interrupt_generator *intgen, *tmpgen;
+  extern char **buildargv ();
+
+  argv = buildargv (spec);
+
+  if (*argv && ! strcmp (*argv, "add"))
+    {
+      /* Create a new interrupt generator object.  */
+      intgen = (struct interrupt_generator *)
+       malloc (sizeof(struct interrupt_generator));
+      intgen->type = int_none;
+      intgen->cond_type = int_cond_none;
+      intgen->address = 0;
+      intgen->time = 0;
+      intgen->enabled = 0;
+      ++argv;
+      /* Match on interrupt type name.  */
+      for (i = 0; i < num_int_types; ++i)
+       {
+         if (*argv && ! strcmp (*argv, interrupt_names[i]))
+           {
+             intgen->type = i;
+             break;
+           }
+       }
+      if (intgen->type == int_none)
+       {
+         (*v850_callback->printf_filtered) (v850_callback, "Interrupt type unknown; known types are\n");
+         for (i = 0; i < num_int_types; ++i)
+           {
+             (*v850_callback->printf_filtered) (v850_callback, " %s", interrupt_names[i]);
+           }
+         (*v850_callback->printf_filtered) (v850_callback, "\n");
+         free (intgen);
+         return;
+       }
+      ++argv;
+      intgen->address = 0;
+      intgen->time = 0;
+      if (*argv && ! strcmp (*argv, "pc"))
+       {
+         intgen->cond_type = int_cond_pc;
+         ++argv;
+         intgen->address = sim_parse_number (*argv, NULL);
+       }
+      else if (*argv && ! strcmp (*argv, "time"))
+       {
+         intgen->cond_type = int_cond_time;
+         ++argv;
+         intgen->time = sim_parse_number (*argv, NULL);
+       }
+      else
+       {
+         (*v850_callback->printf_filtered) (v850_callback, "Condition type must be `pc' or `time'.\n");
+         free (intgen);
+         return;
+       }
+      /* We now have a valid interrupt generator.  Number it and add
+        to the list of generators.  */
+      intgen->number = current_intgen_number++;
+      intgen->enabled = 1;
+      intgen->next = intgen_list;
+      intgen_list = intgen;
+      (*v850_callback->printf_filtered) (v850_callback, "Interrupt generator %d (NMI) at pc=0x%x, time=%d.\n", intgen_list->number, intgen_list->address, intgen_list->time);
+    }
+  else if (*argv && !strcmp (*argv, "remove"))
+    {
+      ++argv;
+      num = sim_parse_number (*argv, NULL);
+      tmpgen = NULL;
+      if (intgen_list)
+       {
+         if (intgen_list->number == num)
+           {
+             tmpgen = intgen_list;
+             intgen_list = intgen_list->next;
+           }
+         else
+           {
+             for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
+               {
+                 if (intgen->next != NULL && intgen->next->number == num)
+                   {
+                     tmpgen = intgen->next;
+                     intgen->next = intgen->next->next;
+                     break;
+                   }
+               }
+           }
+         if (tmpgen)
+           free (tmpgen);
+         else
+           (*v850_callback->printf_filtered) (v850_callback,
+                                              "No interrupt generator numbered %d, ignoring.\n", num);
+       }
+    }
+  else if (*argv && !strcmp (*argv, "info"))
+    {
+      if (intgen_list)
+       {
+         for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
+           (*v850_callback->printf_filtered) (v850_callback,
+                                              "Interrupt generator %d (%s) at pc=0x%x/time=%d%s.\n",
+                                              intgen->number,
+                                              interrupt_names[intgen->type],
+                                              intgen->address,
+                                              intgen->time,
+                                              (intgen->enabled ? "" : " (disabled)"));
+       }
+      else
+       {
+         (*v850_callback->printf_filtered) (v850_callback, "No interrupt generators defined.\n"); 
+       }
+
+    }
+  else
+    {
+      (*v850_callback->printf_filtered) (v850_callback,
+                                        "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
+    }
+  /* Cache the presence of a non-maskable generator.  */
+  have_nm_generator = 0;
+  for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
+    {
+      if (intgen->type == int_nmi || intgen->type == int_reset)
+       {
+         have_nm_generator = 1;
+         break;
+       }
+    }
+}
+
+void
+sim_do_command (sd, cmd)
+     SIM_DESC sd;
      char *cmd;
-{ 
-  printf("sim_do_command: %s\n",cmd);
+{
+  char *mm_cmd = "memory-map";
+  char *int_cmd = "interrupt";
+
+  if (! strncmp (cmd, mm_cmd, strlen (mm_cmd))
+      && strchr ("     ", cmd[strlen(mm_cmd)]))
+    sim_set_memory_map (cmd + strlen(mm_cmd) + 1);
+
+  else if (! strncmp (cmd, int_cmd, strlen (int_cmd))
+      && strchr ("     ", cmd[strlen(int_cmd)]))
+    sim_set_interrupt (cmd + strlen(int_cmd) + 1);
+
+  else if (! strcmp (cmd, "help"))
+    {
+      (*v850_callback->printf_filtered) (v850_callback, "V850 simulator commands:\n\n");
+      (*v850_callback->printf_filtered) (v850_callback, "interrupt add <inttype> { pc | time } <value> -- Set up an interrupt generator\n");
+      (*v850_callback->printf_filtered) (v850_callback, "interrupt remove <n> -- Remove an existing interrupt generator\n");
+      (*v850_callback->printf_filtered) (v850_callback, "interrupt info -- List all the interrupt generators\n");
+      (*v850_callback->printf_filtered) (v850_callback, "memory-map hole=<m>,<n> -- Set the memory map to have a hole between <m> and <n>\n");
+      (*v850_callback->printf_filtered) (v850_callback, "\n");
+    }
+  else
+    (*v850_callback->printf_filtered) (v850_callback, "\"%s\" is not a valid V850 simulator command.\n",
+                                      cmd);
 }
 
-int
-sim_load (prog, from_tty)
+SIM_RC
+sim_load (sd, prog, abfd, from_tty)
+     SIM_DESC sd;
      char *prog;
+     bfd *abfd;
      int from_tty;
 {
-  /* Return nonzero so GDB will handle it.  */
-  return 1;
+  extern bfd *sim_load_file (); /* ??? Don't know where this should live.  */
+
+  if (prog_bfd != NULL && prog_bfd_was_opened_p)
+    bfd_close (prog_bfd);
+  prog_bfd = sim_load_file (sd, myname, v850_callback, prog, abfd,
+                           sim_kind == SIM_OPEN_DEBUG);
+  if (prog_bfd == NULL)
+    return SIM_RC_FAIL;
+  PC = bfd_get_start_address (prog_bfd);
+  prog_bfd_was_opened_p = abfd == NULL;
+  return SIM_RC_OK;
 } 
This page took 0.034398 seconds and 4 git commands to generate.