Example #1
0
SIM_RC
sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
		     char **argv, char **env)
{
  SIM_CPU *cpu = STATE_CPU (sd, 0);
  SIM_ADDR addr;

  /* Set the PC.  */
  if (abfd != NULL)
    addr = bfd_get_start_address (abfd);
  else
    addr = 0;
  sim_pc_set (cpu, addr);

  /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv
     for us in sim_open() -> sim_parse_args().  But in debug mode (i.e.
     'target sim' with `bfin-...-gdb`), we need to handle it.  */
  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
    {
      freeargv (STATE_PROG_ARGV (sd));
      STATE_PROG_ARGV (sd) = dupargv (argv);
    }

  switch (STATE_ENVIRONMENT (sd))
    {
    case USER_ENVIRONMENT:
      bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env);
      break;
    case OPERATING_ENVIRONMENT:
      bfin_os_init (sd, cpu, (void *)argv);
      break;
    default:
      bfin_virtual_init (sd, cpu);
      break;
    }

  return SIM_RC_OK;
}
Example #2
0
static SIM_RC
standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
			 char *arg, int is_command)
{
  int i,n;

  switch ((STANDARD_OPTIONS) opt)
    {
    case OPTION_VERBOSE:
      STATE_VERBOSE_P (sd) = 1;
      break;

#ifdef SIM_HAVE_BIENDIAN
    case OPTION_ENDIAN:
      if (strcmp (arg, "big") == 0)
	{
	  if (WITH_TARGET_BYTE_ORDER == LITTLE_ENDIAN)
	    {
	      sim_io_eprintf (sd, "Simulator compiled for little endian only.\n");
	      return SIM_RC_FAIL;
	    }
	  /* FIXME:wip: Need to set something in STATE_CONFIG.  */
	  current_target_byte_order = BIG_ENDIAN;
	}
      else if (strcmp (arg, "little") == 0)
	{
	  if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN)
	    {
	      sim_io_eprintf (sd, "Simulator compiled for big endian only.\n");
	      return SIM_RC_FAIL;
	    }
	  /* FIXME:wip: Need to set something in STATE_CONFIG.  */
	  current_target_byte_order = LITTLE_ENDIAN;
	}
      else
	{
	  sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg);
	  return SIM_RC_FAIL;
	}
      break;
#endif

    case OPTION_ENVIRONMENT:
      if (strcmp (arg, "user") == 0)
	STATE_ENVIRONMENT (sd) = USER_ENVIRONMENT;
      else if (strcmp (arg, "virtual") == 0)
	STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
      else if (strcmp (arg, "operating") == 0)
	STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
      else
	{
	  sim_io_eprintf (sd, "Invalid environment specification `%s'\n", arg);
	  return SIM_RC_FAIL;
	}
      if (WITH_ENVIRONMENT != ALL_ENVIRONMENT
	  && WITH_ENVIRONMENT != STATE_ENVIRONMENT (sd))
	{
	  char *type;
	  switch (WITH_ENVIRONMENT)
	    {
	    case USER_ENVIRONMENT: type = "user"; break;
	    case VIRTUAL_ENVIRONMENT: type = "virtual"; break;
	    case OPERATING_ENVIRONMENT: type = "operating"; break;
	    }
	  sim_io_eprintf (sd, "Simulator compiled for the %s environment only.\n",
			  type);
	  return SIM_RC_FAIL;
	}
      break;

    case OPTION_ALIGNMENT:
      if (strcmp (arg, "strict") == 0)
	{
	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == STRICT_ALIGNMENT)
	    {
	      current_alignment = STRICT_ALIGNMENT;
	      break;
	    }
	}
      else if (strcmp (arg, "nonstrict") == 0)
	{
	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == NONSTRICT_ALIGNMENT)
	    {
	      current_alignment = NONSTRICT_ALIGNMENT;
	      break;
	    }
	}
      else if (strcmp (arg, "forced") == 0)
	{
	  if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == FORCED_ALIGNMENT)
	    {
	      current_alignment = FORCED_ALIGNMENT;
	      break;
	    }
	}
      else
	{
	  sim_io_eprintf (sd, "Invalid alignment specification `%s'\n", arg);
	  return SIM_RC_FAIL;
	}
      switch (WITH_ALIGNMENT)
	{
	case STRICT_ALIGNMENT:
	  sim_io_eprintf (sd, "Simulator compiled for strict alignment only.\n");
	  break;
	case NONSTRICT_ALIGNMENT:
	  sim_io_eprintf (sd, "Simulator compiled for nonstrict alignment only.\n");
	  break;
	case FORCED_ALIGNMENT:
	  sim_io_eprintf (sd, "Simulator compiled for forced alignment only.\n");
	  break;
	}
      return SIM_RC_FAIL;

    case OPTION_DEBUG:
      if (! WITH_DEBUG)
	sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n");
      else
	{
	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
	    for (i = 0; i < MAX_DEBUG_VALUES; ++i)
	      CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1;
	}
      break;

    case OPTION_DEBUG_INSN :
      if (! WITH_DEBUG)
	sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n");
      else
	{
	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
	    CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1;
	}
      break;

    case OPTION_DEBUG_FILE :
      if (! WITH_DEBUG)
	sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n");
      else
	{
	  FILE *f = fopen (arg, "w");

	  if (f == NULL)
	    {
	      sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg);
	      return SIM_RC_FAIL;
	    }
	  for (n = 0; n < MAX_NR_PROCESSORS; ++n)
	    CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f;
	}
      break;

#ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir.  */
    case OPTION_H8300:
      set_h8300h (1,0);
      break;
    case OPTION_H8300S:
      set_h8300h (1,1);
      break;
#endif

#ifdef SIM_HAVE_FLATMEM
    case OPTION_MEM_SIZE:
      {
	unsigned long ul = strtol (arg, NULL, 0);
	/* 16384: some minimal amount */
	if (! isdigit (arg[0]) || ul < 16384)
	  {
	    sim_io_eprintf (sd, "Invalid memory size `%s'", arg);
	    return SIM_RC_FAIL;
	  }
	STATE_MEM_SIZE (sd) = ul;
      }
      break;
#endif

    case OPTION_DO_COMMAND:
      sim_do_command (sd, arg);
      break;

    case OPTION_ARCHITECTURE:
      {
	const struct bfd_arch_info *ap = bfd_scan_arch (arg);
	if (ap == NULL)
	  {
	    sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg);
	    return SIM_RC_FAIL;
	  }
	STATE_ARCHITECTURE (sd) = ap;
	break;
      }

    case OPTION_ARCHITECTURE_INFO:
      {
	const char **list = bfd_arch_list();
	const char **lp;
	if (list == NULL)
	  abort ();
	sim_io_printf (sd, "Possible architectures:");
	for (lp = list; *lp != NULL; lp++)
	  sim_io_printf (sd, " %s", *lp);
	sim_io_printf (sd, "\n");
	free (list);
	break;
      }

    case OPTION_TARGET:
      {
	STATE_TARGET (sd) = xstrdup (arg);
	break;
      }

    case OPTION_LOAD_LMA:
      {
	STATE_LOAD_AT_LMA_P (sd) = 1;
	break;
      }

    case OPTION_LOAD_VMA:
      {
	STATE_LOAD_AT_LMA_P (sd) = 0;
	break;
      }

    case OPTION_HELP:
      sim_print_help (sd, is_command);
      if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
	exit (0);
      /* FIXME: 'twould be nice to do something similar if gdb.  */
      break;
    }

  return SIM_RC_OK;
}
Example #3
0
static bool
bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
		 bu32 *elf_addrs, char **ldso_path)
{
  bool ret;
  int i;

  Elf_Internal_Ehdr *iehdr;
  Elf32_External_Ehdr ehdr;
  Elf_Internal_Phdr *phdrs;
  unsigned char *data;
  long phdr_size;
  int phdrc;
  bu32 nsegs;

  bu32 max_load_addr;

  unsigned char null[4] = { 0, 0, 0, 0 };

  ret = false;
  *ldso_path = NULL;

  /* See if this an FDPIC ELF.  */
  phdrs = NULL;
  if (!abfd)
    goto skip_fdpic_init;
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
    goto skip_fdpic_init;
  if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
    goto skip_fdpic_init;
  iehdr = elf_elfheader (abfd);
  if (!(iehdr->e_flags & EF_BFIN_FDPIC))
    goto skip_fdpic_init;

  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
    sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
		   bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);

  /* Grab the Program Headers to set up the loadsegs on the stack.  */
  phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
  if (phdr_size == -1)
    goto skip_fdpic_init;
  phdrs = xmalloc (phdr_size);
  phdrc = bfd_get_elf_phdrs (abfd, phdrs);
  if (phdrc == -1)
    goto skip_fdpic_init;

  /* Push the Ehdr onto the stack.  */
  *sp -= sizeof (ehdr);
  elf_addrs[3] = *sp;
  sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
  if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
    sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);

  /* Since we're relocating things ourselves, we need to relocate
     the start address as well.  */
  elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;

  /* And the Exec's Phdrs onto the stack.  */
  if (STATE_PROG_BFD (sd) == abfd)
    {
      elf_addrs[4] = elf_addrs[0];

      phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
      if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
	goto skip_fdpic_init;
      data = xmalloc (phdr_size);
      if (bfd_bread (data, phdr_size, abfd) != phdr_size)
	goto skip_fdpic_init;
      *sp -= phdr_size;
      elf_addrs[1] = *sp;
      elf_addrs[2] = phdrc;
      sim_write (sd, *sp, data, phdr_size);
      free (data);
      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
    }

  /* Now push all the loadsegs.  */
  nsegs = 0;
  max_load_addr = 0;
  for (i = phdrc; i >= 0; --i)
    if (phdrs[i].p_type == PT_LOAD)
      {
	Elf_Internal_Phdr *p = &phdrs[i];
	bu32 paddr, vaddr, memsz, filesz;

	paddr = p->p_paddr + fdpic_load_offset;
	vaddr = p->p_vaddr;
	memsz = p->p_memsz;
	filesz = p->p_filesz;

	if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
			 i, vaddr, paddr, filesz, memsz);

	data = xmalloc (memsz);
	if (memsz != filesz)
	  memset (data + filesz, 0, memsz - filesz);

	if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
	    && bfd_bread (data, filesz, abfd) == filesz)
	  sim_write (sd, paddr, data, memsz);

	free (data);

	max_load_addr = MAX (paddr + memsz, max_load_addr);

	*sp -= 12;
	sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr  */
	sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr  */
	sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz  */
	++nsegs;
      }
    else if (phdrs[i].p_type == PT_DYNAMIC)
      {
	elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
	if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
      }
    else if (phdrs[i].p_type == PT_INTERP)
      {
	uint32_t off = phdrs[i].p_offset;
	uint32_t len = phdrs[i].p_filesz;

	*ldso_path = xmalloc (len);
	if (bfd_seek (abfd, off, SEEK_SET) != 0
	    || bfd_bread (*ldso_path, len, abfd) != len)
	  {
	    free (*ldso_path);
	    *ldso_path = NULL;
	  }
	else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	  sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
      }

  /* Update the load offset with a few extra pages.  */
  fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
  fdpic_load_offset += 0x10000;

  /* Push the summary loadmap info onto the stack last.  */
  *sp -= 4;
  sim_write (sd, *sp+0, null, 2); /* loadmap.version  */
  sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs  */

  ret = true;
 skip_fdpic_init:
  free (phdrs);

  return ret;
}
Example #4
0
void
sim_resume (SIM_DESC sd, int step, int siggnal)
{
  sim_engine *engine = STATE_ENGINE (sd);
  jmp_buf buf;
  int jmpval;

  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);

  /* we only want to be single stepping the simulator once */
  if (engine->stepper != NULL)
    {
      sim_events_deschedule (sd, engine->stepper);
      engine->stepper = NULL;
    }
  if (step)
    engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);

  sim_module_resume (sd);

#if WITH_SCACHE
  if (USING_SCACHE_P (sd))
    scache_flush (sd);
#endif

  /* run/resume the simulator */

  sim_engine_set_run_state (sd, sim_running, 0);

  engine->jmpbuf = &buf;
  jmpval = setjmp (buf);
  if (jmpval == sim_engine_start_jmpval
      || jmpval == sim_engine_restart_jmpval)
    {
      int last_cpu_nr = sim_engine_last_cpu_nr (sd);
      int next_cpu_nr = sim_engine_next_cpu_nr (sd);
      int nr_cpus = sim_engine_nr_cpus (sd);
      /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
	 useful if all one wants to do is run a benchmark.  Need some better
	 way to identify this case.  */
      int max_insns = (step
		       ? 1
		       : (nr_cpus == 1
			  /*&& wip:no-events*/
			  /* Don't do this if running under gdb, need to
			     poll ui for events.  */
			  && STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
		       ? 0
		       : 8); /*FIXME: magic number*/
      int fast_p = STATE_RUN_FAST_P (sd);

      sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
      if (next_cpu_nr >= nr_cpus)
	next_cpu_nr = 0;
      if (nr_cpus == 1)
	engine_run_1 (sd, max_insns, fast_p);
      else
	engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
    }
#if 1 /*wip*/
  else
    {
      /* Account for the last insn executed.  */
      SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
      ++ CPU_INSN_COUNT (cpu);
      CGEN_TRACE_INSN_FINI (cpu, NULL, 1);
    }
#endif

  engine->jmpbuf = NULL;

  {
    int i;
    int nr_cpus = sim_engine_nr_cpus (sd);

#if 0 /*wip,ignore*/
    /* If the loop exits, either we single-stepped or @cpu@_engine_stop
       was called.  */
    if (step)
      sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
    else
      sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
#endif

    for (i = 0; i < nr_cpus; ++i)
      {
	SIM_CPU *cpu = STATE_CPU (sd, i);

	PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
      }
  }

  sim_module_suspend (sd);
}
Example #5
0
void
cec_exception (SIM_CPU *cpu, int excp)
{
  SIM_DESC sd = CPU_STATE (cpu);
  int sigrc = -1;

  TRACE_EVENTS (cpu, "processing exception %#x in EVT%i", excp,
		cec_get_ivg (cpu));

  /* Ideally what would happen here for real hardware exceptions (not
     fake sim ones) is that:
      - For service exceptions (excp <= 0x11):
         RETX is the _next_ PC which can be tricky with jumps/hardware loops/...
      - For error exceptions (excp > 0x11):
         RETX is the _current_ PC (i.e. the one causing the exception)
      - PC is loaded with EVT3 MMR
      - ILAT/IPEND in CEC is updated depending on current IVG level
      - the fault address MMRs get updated with data/instruction info
      - Execution continues on in the EVT3 handler  */

  /* Handle simulator exceptions first.  */
  switch (excp)
    {
    case VEC_SIM_HLT:
      excp_to_sim_halt (sim_exited, 0);
      return;
    case VEC_SIM_ABORT:
      excp_to_sim_halt (sim_exited, 1);
      return;
    case VEC_SIM_TRAP:
      /* GDB expects us to step over EMUEXCPT.  */
      /* XXX: What about hwloops and EMUEXCPT at the end?
              Pretty sure gdb doesn't handle this already...  */
      SET_PCREG (PCREG + 2);
      /* Only trap when we are running in gdb.  */
      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	excp_to_sim_halt (sim_stopped, SIM_SIGTRAP);
      return;
    case VEC_SIM_DBGA:
      /* If running in gdb, simply trap.  */
      if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
	excp_to_sim_halt (sim_stopped, SIM_SIGTRAP);
      else
	excp_to_sim_halt (sim_exited, 2);
    }

  if (excp <= 0x3f)
    {
      SET_EXCAUSE (excp);
      if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
	{
	  /* ICPLB regs always get updated.  */
	  /* XXX: Should optimize this call path ...  */
	  if (excp != VEC_MISALI_I && excp != VEC_MISALI_D
	      && excp != VEC_CPLB_I_M && excp != VEC_CPLB_M
	      && excp != VEC_CPLB_I_VL && excp != VEC_CPLB_VL
	      && excp != VEC_CPLB_I_MHIT && excp != VEC_CPLB_MHIT)
	    mmu_log_ifault (cpu);
	  _cec_raise (cpu, CEC_STATE (cpu), IVG_EVX);
	  /* We need to restart the engine so that we don't return
	     and continue processing this bad insn.  */
	  if (EXCAUSE >= 0x20)
	    sim_engine_restart (sd, cpu, NULL, PCREG);
	  return;
	}
    }

  TRACE_EVENTS (cpu, "running virtual exception handler");

  switch (excp)
    {
    case VEC_SYS:
      bfin_syscall (cpu);
      break;

    case VEC_EXCPT01:	/* Userspace gdb breakpoint.  */
      sigrc = SIM_SIGTRAP;
      break;

    case VEC_UNDEF_I:	/* Undefined instruction.  */
      sigrc = SIM_SIGILL;
      break;

    case VEC_ILL_RES:	/* Illegal supervisor resource.  */
    case VEC_MISALI_I:	/* Misaligned instruction.  */
      sigrc = SIM_SIGBUS;
      break;

    case VEC_CPLB_M:
    case VEC_CPLB_I_M:
      sigrc = SIM_SIGSEGV;
      break;

    default:
      sim_io_eprintf (sd, "Unhandled exception %#x at 0x%08x (%s)\n",
		      excp, PCREG, excp_decoded[excp]);
      sigrc = SIM_SIGILL;
      break;
    }

  if (sigrc != -1)
    excp_to_sim_halt (sim_stopped, sigrc);
}