Beispiel #1
0
void
sim_core_signal (SIM_DESC sd,
		 sim_cpu *cpu,
		 sim_cia cia,
		 unsigned map,
		 int nr_bytes,
		 address_word addr,
		 transfer_type transfer,
		 sim_core_signals sig)
{
  const char *copy = (transfer == read_transfer ? "read" : "write");
  address_word ip = CIA_ADDR (cia);
  switch (sig)
    {
    case sim_core_unmapped_signal:
      sim_io_eprintf (sd, "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
      sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGSEGV);
      break;
    case sim_core_unaligned_signal:
      sim_io_eprintf (sd, "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
      sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGBUS);
      break;
    default:
      sim_engine_abort (sd, cpu, cia,
			"sim_core_signal - internal error - bad switch");
    }
}
/* emul_exit () is used by the default startup code of GCC to implement
   the exit ().  For a real target, this will create an ILLEGAL fault.
   But doing an exit () on a real target is really a non-sense.
   exit () is important for the validation of GCC.  The exit status
   is passed in 'D' register.  */
void
emul_exit (sim_cpu *cpu)
{
  sim_engine_halt (CPU_STATE (cpu), cpu,
		   NULL, NULL_CIA, sim_exited,
		   cpu_get_d (cpu));
}
static void
has_stepped (SIM_DESC sd,
	     void *data)
{
  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
}
Beispiel #4
0
SEM_PC
sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC pc)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

#if 0
  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
    {
      h_bsm_set (current_cpu, h_sm_get (current_cpu));
      h_bie_set (current_cpu, h_ie_get (current_cpu));
      h_bcond_set (current_cpu, h_cond_get (current_cpu));
      /* sm not changed */
      h_ie_set (current_cpu, 0);
      h_cond_set (current_cpu, 0);

      h_bpc_set (current_cpu, cia);

      sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL,
			  EIT_RSVD_INSN_ADDR);
    }
  else
#endif
    sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);

  return pc;
}
Beispiel #5
0
static void
control_c_simulation (SIM_DESC sd,
		      void *data)
{
  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
}
Beispiel #6
0
/* Handle the BREAK insn.  */
void
frv_break (SIM_CPU *current_cpu)
{
  IADDR pc;
  SIM_DESC sd = CPU_STATE (current_cpu);

#ifdef SIM_HAVE_BREAKPOINTS
  /* First try sim-break.c.  If it's a breakpoint the simulator "owns"
     it doesn't return.  Otherwise it returns and let's us try.  */
  pc = GET_H_PC ();
  sim_handle_breakpoint (sd, current_cpu, pc);
  /* Fall through.  */
#endif

  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
    {
      /* Invalidate the insn cache because the debugger will presumably
	 replace the breakpoint insn with the real one.  */
#ifndef SIM_HAVE_BREAKPOINTS
      pc = GET_H_PC ();
#endif
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
    }

  frv_queue_break_interrupt (current_cpu);
}
Beispiel #7
0
do_syscall ()
{

    /* We use this for simulated system calls; we may need to change
       it to a reserved instruction if we conflict with uses at
       Matsushita.  */
    int save_errno = errno;
    errno = 0;

    /* Registers passed to trap 0 */

    /* Function number.  */
#define FUNC   (State.regs[0])

    /* Parameters.  */
#define PARM1   (State.regs[1])
#define PARM2   (load_word (State.regs[REG_SP] + 12))
#define PARM3   (load_word (State.regs[REG_SP] + 16))

    /* Registers set by trap 0 */

#define RETVAL State.regs[0]	/* return value */
#define RETERR State.regs[1]	/* return error code */

    /* Turn a pointer in a register into a pointer into real memory. */
#define MEMPTR(x) (State.mem + x)

    if ( FUNC == TARGET_SYS_exit )
    {
        /* EXIT - caller can look in PARM1 to work out the reason */
        if (PARM1 == 0xdead)
            State.exception = SIGABRT;
        else
        {
            sim_engine_halt (simulator, STATE_CPU (simulator, 0), NULL, PC,
                             sim_exited, PARM1);
            State.exception = SIGQUIT;
        }
        State.exited = 1;
    }
    else
    {
        CB_SYSCALL syscall;

        CB_SYSCALL_INIT (&syscall);
        syscall.arg1 = PARM1;
        syscall.arg2 = PARM2;
        syscall.arg3 = PARM3;
        syscall.func = FUNC;
        syscall.p1 = (PTR) simulator;
        syscall.read_mem = syscall_read_mem;
        syscall.write_mem = syscall_write_mem;
        cb_syscall (STATE_CALLBACK (simulator), &syscall);
        RETERR = syscall.errcode;
        RETVAL = syscall.result;
    }


    errno = save_errno;
}
Beispiel #8
0
void
sim_engine_vabort (SIM_DESC sd,
		   sim_cpu *cpu,
		   sim_cia cia,
		   const char *fmt,
		   va_list ap)
{
  ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  if (sd == NULL)
    {
      vfprintf (stderr, fmt, ap);
      fprintf (stderr, "\nQuit\n");
      abort ();
    }
  else if (STATE_ENGINE (sd)->jmpbuf == NULL)
    {
      sim_io_evprintf (sd, fmt, ap);
      sim_io_eprintf (sd, "\n");
      sim_io_error (sd, "Quit Simulator");
      abort ();
    }
  else
    {
      sim_io_evprintf (sd, fmt, ap);
      sim_io_eprintf (sd, "\n");
      sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT);
    }
}
Beispiel #9
0
void
hw_halt (struct hw *me,
         int reason,
         int status)
{
    struct sim_state *sd = hw_system (me);
    struct sim_hw *sim = STATE_HW (sd);
    sim_engine_halt (sd, sim->cpu, NULL, sim->cia, reason, status);
}
/* Check for interrupts caused by illegal insn access.  These conditions are
   checked in the order specified by the fr400 and fr500 LSI specs.  */
void
frv_detect_insn_access_interrupts (SIM_CPU *current_cpu, SCACHE *sc)
{

  const CGEN_INSN *insn = sc->argbuf.idesc->idata;
  SIM_DESC sd = CPU_STATE (current_cpu);
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);

  /* Check for vliw constraints.  */
  if (vliw->constraint_violation)
    frv_queue_illegal_instruction_interrupt (current_cpu, insn);
  /* Check for non-excepting insns.  */
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_NON_EXCEPTING)
      && ! GET_H_PSR_NEM ())
    frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
  /* Check for conditional insns.  */
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONDITIONAL)
      && ! GET_H_PSR_CM ())
    frv_queue_non_implemented_instruction_interrupt (current_cpu, insn);
  /* Make sure floating point support is enabled.  */
  else if (! GET_H_PSR_EF ())
    {
      /* Generate fp_disabled if it is a floating point insn or if PSR.EM is
	 off and the insns accesses a fp register.  */
      if (frv_is_float_insn (insn)
	  || (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)
	      && ! GET_H_PSR_EM ()))
	frv_queue_float_disabled_interrupt (current_cpu);
    }
  /* Make sure media support is enabled.  */
  else if (! GET_H_PSR_EM ())
    {
      /* Generate mp_disabled if it is a media insn.  */
      if (frv_is_media_insn (insn) || CGEN_INSN_NUM (insn) == FRV_INSN_MTRAP)
	frv_queue_media_disabled_interrupt (current_cpu);
    }
  /* Check for privileged insns.  */
  else if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_PRIVILEGED) &&
	   ! GET_H_PSR_S ())
    frv_queue_privileged_instruction_interrupt (current_cpu, insn);
#if 0 /* disable for now until we find out how FSR0.QNE gets reset.  */
  else
    {
      /* Enter the halt state if FSR0.QNE is set and we are executing a
	 floating point insn, a media insn or an insn which access a FR
	 register.  */
      SI fsr0 = GET_FSR (0);
      if (GET_FSR_QNE (fsr0)
	  && (frv_is_float_insn (insn) || frv_is_media_insn (insn)
	      || CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR_ACCESS)))
	{
	  sim_engine_halt (sd, current_cpu, NULL, GET_H_PC (), sim_stopped,
			   SIM_SIGINT);
	}
    }
#endif
}
Beispiel #11
0
const char *
aarch64_get_mem_ptr (sim_cpu *cpu, uint64_t address)
{
  char *addr = sim_core_trans_addr (CPU_STATE (cpu), cpu, read_map, address);

  if (addr == NULL)
    {
      mem_error (cpu, "request for non-existant mem addr of", address);
      sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
		       sim_stopped, SIM_SIGBUS);
    }

  return addr;
}
Beispiel #12
0
static void
handle_watchpoint (SIM_DESC sd, void *data)
{
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
  sim_watch_point *point = (sim_watch_point *) data;
  int interrupt_nr = point->interrupt_nr;

  if (point->is_periodic)
    /* reschedule this event before processing it */
    schedule_watchpoint (sd, point);
  else
    do_watchpoint_delete (sd, point->ident, invalid_watchpoint);

  if (point->interrupt_nr == watch->nr_interrupts)
    sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
  else
    watch->interrupt_handler (sd, &watch->interrupt_names[interrupt_nr]);
}
/* Handle a program interrupt or a software interrupt.  */
void
frv_program_or_software_interrupt (
  SIM_CPU *current_cpu, struct frv_interrupt *interrupt, IADDR current_pc
)
{
  USI new_pc;
  int original_psr_et;

  /* PCSR=PC
     PSR.PS=PSR.S
     PSR.ET=0
     PSR.S=1
     if PSR.ESR==1
       SR0 through SR3=GR4 through GR7
       TBR.TT=interrupt handler offset
       PC=TBR
  */
  original_psr_et = GET_H_PSR_ET ();

  SET_H_PSR_PS (GET_H_PSR_S ());
  SET_H_PSR_ET (0);
  SET_H_PSR_S (1);

  /* Must set PSR.S first to allow access to supervisor-only spr registers.  */
  /* The PCSR depends on the precision of the interrupt.  */
  if (interrupt->precise)
    SET_H_SPR (H_SPR_PCSR, previous_vliw_pc);
  else
    SET_H_SPR (H_SPR_PCSR, current_pc);

  /* Set the new PC in the TBR.  */
  SET_H_TBR_TT (interrupt->handler_offset);
  new_pc = GET_H_SPR (H_SPR_TBR);
  SET_H_PC (new_pc);

  /* If PSR.ET was not originally set, then enter the stopped state.  */
  if (! original_psr_et)
    {
      SIM_DESC sd = CPU_STATE (current_cpu);
      frv_non_operating_interrupt (current_cpu, interrupt->kind, current_pc);
      sim_engine_halt (sd, current_cpu, NULL, new_pc, sim_stopped, SIM_SIGINT);
    }
}
Beispiel #14
0
void
program_interrupt (SIM_DESC sd,
		   sim_cpu *cpu,
		   sim_cia cia,
		   SIM_SIGNAL sig)
{
  int status;
  struct hw *device;
  static int in_interrupt = 0;

#ifdef SIM_CPU_EXCEPTION_TRIGGER
  SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
#endif

  /* avoid infinite recursion */
  if (in_interrupt)
    {
      (*mn10300_callback->printf_filtered) (mn10300_callback, 
					    "ERROR: recursion in program_interrupt during software exception dispatch.");
    }
  else
    {
      in_interrupt = 1;
      /* copy NMI handler code from dv-mn103cpu.c */
      store_word (SP - 4, CPU_PC_GET (cpu));
      store_half (SP - 8, PSW);

      /* Set the SYSEF flag in NMICR by backdoor method.  See
	 dv-mn103int.c:write_icr().  This is necessary because
         software exceptions are not modelled by actually talking to
         the interrupt controller, so it cannot set its own SYSEF
         flag. */
     if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
       store_byte (0x34000103, 0x04);
    }

  PSW &= ~PSW_IE;
  SP = SP - 8;
  CPU_PC_SET (cpu, 0x40000008);

  in_interrupt = 0;
  sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
}
Beispiel #15
0
void
aarch64_get_mem_blk (sim_cpu *  cpu,
		     uint64_t   address,
		     char *     buffer,
		     unsigned   length)
{
  unsigned len;

  len = sim_core_read_buffer (CPU_STATE (cpu), cpu, read_map,
			      buffer, address, length);
  if (len == length)
    return;

  memset (buffer, 0, length);
  if (cpu)
    mem_error (cpu, "read of non-existant mem block at", address);

  sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
		   sim_stopped, SIM_SIGBUS);
}
Beispiel #16
0
USI
m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

#ifdef SIM_HAVE_BREAKPOINTS
  /* Check for breakpoints "owned" by the simulator first, regardless
     of --environment.  */
  if (num == TRAP_BREAKPOINT)
    {
      /* First try sim-break.c.  If it's a breakpoint the simulator "owns"
	 it doesn't return.  Otherwise it returns and let's us try.  */
      sim_handle_breakpoint (sd, current_cpu, pc);
      /* Fall through.  */
    }
#endif

  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
    {
      /* The new pc is the trap vector entry.
	 We assume there's a branch there to some handler.
         Use cr5 as EVB (EIT Vector Base) register.  */
      /* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */
      USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4;
      return new_pc;
    }

  switch (num)
    {
    case TRAP_SYSCALL :
      {
	CB_SYSCALL s;

	CB_SYSCALL_INIT (&s);
	s.func = m32rbf_h_gr_get (current_cpu, 0);
	s.arg1 = m32rbf_h_gr_get (current_cpu, 1);
	s.arg2 = m32rbf_h_gr_get (current_cpu, 2);
	s.arg3 = m32rbf_h_gr_get (current_cpu, 3);

	if (s.func == TARGET_SYS_exit)
	  {
	    sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
	  }

	s.p1 = (PTR) sd;
	s.p2 = (PTR) current_cpu;
	s.read_mem = syscall_read_mem;
	s.write_mem = syscall_write_mem;
	cb_syscall (cb, &s);
	m32rbf_h_gr_set (current_cpu, 2, s.errcode);
	m32rbf_h_gr_set (current_cpu, 0, s.result);
	m32rbf_h_gr_set (current_cpu, 1, s.result2);
	break;
      }

    case TRAP_BREAKPOINT:
      sim_engine_halt (sd, current_cpu, NULL, pc,
		       sim_stopped, SIM_SIGTRAP);
      break;

    case TRAP_FLUSH_CACHE:
      /* Do nothing.  */
      break;

    default :
      {
	/* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */
        /* Use cr5 as EVB (EIT Vector Base) register.  */
        USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4;
	return new_pc;
      }
    }

  /* Fake an "rte" insn.  */
  /* FIXME: Should duplicate all of rte processing.  */
  return (pc & -4) + 4;
}
/* Process the current interrupt if there is one.  This operation must
   be called after each instruction to handle the interrupts.  If interrupts
   are masked, it does nothing.  */
int
interrupts_process (struct interrupts *interrupts)
{
  int id;
  uint8 ccr;

  /* See if interrupts are enabled/disabled and keep track of the
     number of cycles the interrupts are masked.  Such information is
     then reported by the info command.  */
  ccr = cpu_get_ccr (interrupts->cpu);
  if (ccr & M6811_I_BIT)
    {
      if (interrupts->start_mask_cycle < 0)
        interrupts->start_mask_cycle = cpu_current_cycle (interrupts->cpu);
    }
  else if (interrupts->start_mask_cycle >= 0
           && (ccr & M6811_I_BIT) == 0)
    {
      signed64 t = cpu_current_cycle (interrupts->cpu);

      t -= interrupts->start_mask_cycle;
      if (t < interrupts->min_mask_cycles)
        interrupts->min_mask_cycles = t;
      if (t > interrupts->max_mask_cycles)
        interrupts->max_mask_cycles = t;
      interrupts->start_mask_cycle = -1;
      interrupts->last_mask_cycles = t;
    }
  if (ccr & M6811_X_BIT)
    {
      if (interrupts->xirq_start_mask_cycle < 0)
        interrupts->xirq_start_mask_cycle
	  = cpu_current_cycle (interrupts->cpu);
    }
  else if (interrupts->xirq_start_mask_cycle >= 0
           && (ccr & M6811_X_BIT) == 0)
    {
      signed64 t = cpu_current_cycle (interrupts->cpu);

      t -= interrupts->xirq_start_mask_cycle;
      if (t < interrupts->xirq_min_mask_cycles)
        interrupts->xirq_min_mask_cycles = t;
      if (t > interrupts->xirq_max_mask_cycles)
        interrupts->xirq_max_mask_cycles = t;
      interrupts->xirq_start_mask_cycle = -1;
      interrupts->xirq_last_mask_cycles = t;
    }

  id = interrupts_get_current (interrupts);
  if (id >= 0)
    {
      uint16 addr;
      struct interrupt_history *h;

      /* Implement the breakpoint-on-interrupt.  */
      if (interrupts->interrupts[id].stop_mode & SIM_STOP_WHEN_TAKEN)
        {
          sim_io_printf (CPU_STATE (interrupts->cpu),
                         "Interrupt %s will be handled\n",
                         interrupt_names[id]);
          sim_engine_halt (CPU_STATE (interrupts->cpu),
                           interrupts->cpu,
                           0, cpu_get_pc (interrupts->cpu),
                           sim_stopped,
                           SIM_SIGTRAP);
        }

      cpu_push_all (interrupts->cpu);
      addr = memory_read16 (interrupts->cpu,
                            interrupts->vectors_addr + id * 2);
      cpu_call (interrupts->cpu, addr);

      /* Now, protect from nested interrupts.  */
      if (id == M6811_INT_XIRQ)
	{
	  cpu_set_ccr_X (interrupts->cpu, 1);
	}
      else
	{
	  cpu_set_ccr_I (interrupts->cpu, 1);
	}

      /* Update the interrupt history table.  */
      h = &interrupts->interrupts_history[interrupts->history_index];
      h->type = id;
      h->taken_cycle = cpu_current_cycle (interrupts->cpu);
      h->raised_cycle = interrupts->interrupts[id].cpu_cycle;
      
      if (interrupts->history_index >= MAX_INT_HISTORY-1)
        interrupts->history_index = 0;
      else
        interrupts->history_index++;

      interrupts->nb_interrupts_raised++;
      cpu_add_cycles (interrupts->cpu, 14);
      return 1;
    }
  return 0;
}
/* Update the mask of pending interrupts.  This operation must be called
   when the state of some 68HC11 IO register changes.  It looks the
   different registers that indicate a pending interrupt (timer, SCI, SPI,
   ...) and records the interrupt if it's there and enabled.  */
void
interrupts_update_pending (struct interrupts *interrupts)
{
  int i;
  uint8 *ioregs;
  unsigned long clear_mask;
  unsigned long set_mask;

  clear_mask = 0;
  set_mask = 0;
  ioregs = &interrupts->cpu->ios[0];
  
  for (i = 0; i < TableSize(idefs); i++)
    {
      struct interrupt_def *idef = &idefs[i];
      uint8 data;
      
      /* Look if the interrupt is enabled.  */
      if (idef->enable_paddr)
	{
	  data = ioregs[idef->enable_paddr];
	  if (!(data & idef->enabled_mask))
            {
              /* Disable it.  */
              clear_mask |= (1 << idef->int_number);
              continue;
            }
	}

      /* Interrupt is enabled, see if it's there.  */
      data = ioregs[idef->int_paddr];
      if (!(data & idef->int_mask))
        {
          /* Disable it.  */
          clear_mask |= (1 << idef->int_number);
          continue;
        }

      /* Ok, raise it.  */
      set_mask |= (1 << idef->int_number);
    }

  /* Some interrupts are shared (M6811_INT_SCI) so clear
     the interrupts before setting the new ones.  */
  interrupts->pending_mask &= ~clear_mask;
  interrupts->pending_mask |= set_mask;

  /* Keep track of when the interrupt is raised by the device.
     Also implements the breakpoint-on-interrupt.  */
  if (set_mask)
    {
      signed64 cycle = cpu_current_cycle (interrupts->cpu);
      int must_stop = 0;
      
      for (i = 0; i < M6811_INT_NUMBER; i++)
        {
          if (!(set_mask & (1 << i)))
            continue;

          interrupts->interrupts[i].cpu_cycle = cycle;
          if (interrupts->interrupts[i].stop_mode & SIM_STOP_WHEN_RAISED)
            {
              must_stop = 1;
              sim_io_printf (CPU_STATE (interrupts->cpu),
                             "Interrupt %s raised\n",
                             interrupt_names[i]);
            }
        }
      if (must_stop)
        sim_engine_halt (CPU_STATE (interrupts->cpu),
                         interrupts->cpu,
                         0, cpu_get_pc (interrupts->cpu),
                         sim_stopped,
                         SIM_SIGTRAP);
    }
}
Beispiel #19
0
void
bfin_syscall (SIM_CPU *cpu)
{
  SIM_DESC sd = CPU_STATE (cpu);
  const char * const *argv = (void *)STATE_PROG_ARGV (sd);
  host_callback *cb = STATE_CALLBACK (sd);
  bu32 args[6];
  CB_SYSCALL sc;
  char *p;
  char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024];
  int fmt_ret_hex = 0;

  CB_SYSCALL_INIT (&sc);

  if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
    {
      /* Linux syscall.  */
      sc.func = PREG (0);
      sc.arg1 = args[0] = DREG (0);
      sc.arg2 = args[1] = DREG (1);
      sc.arg3 = args[2] = DREG (2);
      sc.arg4 = args[3] = DREG (3);
      /*sc.arg5 =*/ args[4] = DREG (4);
      /*sc.arg6 =*/ args[5] = DREG (5);
    }
  else
    {
      /* libgloss syscall.  */
      sc.func = PREG (0);
      sc.arg1 = args[0] = GET_LONG (DREG (0));
      sc.arg2 = args[1] = GET_LONG (DREG (0) + 4);
      sc.arg3 = args[2] = GET_LONG (DREG (0) + 8);
      sc.arg4 = args[3] = GET_LONG (DREG (0) + 12);
      /*sc.arg5 =*/ args[4] = GET_LONG (DREG (0) + 16);
      /*sc.arg6 =*/ args[5] = GET_LONG (DREG (0) + 20);
    }
  sc.p1 = (PTR) sd;
  sc.p2 = (PTR) cpu;
  sc.read_mem = sim_syscall_read_mem;
  sc.write_mem = sim_syscall_write_mem;

  /* Common cb_syscall() handles most functions.  */
  switch (cb_target_to_host_syscall (cb, sc.func))
    {
    case CB_SYS_exit:
      tbuf += sprintf (tbuf, "exit(%i)", args[0]);
      sim_engine_halt (sd, cpu, NULL, PCREG, sim_exited, sc.arg1);

#ifdef CB_SYS_argc
    case CB_SYS_argc:
      tbuf += sprintf (tbuf, "argc()");
      sc.result = count_argc (argv);
      break;
    case CB_SYS_argnlen:
      {
      tbuf += sprintf (tbuf, "argnlen(%u)", args[0]);
	if (sc.arg1 < count_argc (argv))
	  sc.result = strlen (argv[sc.arg1]);
	else
	  sc.result = -1;
      }
      break;
    case CB_SYS_argn:
      {
	tbuf += sprintf (tbuf, "argn(%u)", args[0]);
	if (sc.arg1 < count_argc (argv))
	  {
	    const char *argn = argv[sc.arg1];
	    int len = strlen (argn);
	    int written = sc.write_mem (cb, &sc, sc.arg2, argn, len + 1);
	    if (written == len + 1)
	      sc.result = sc.arg2;
	    else
	      sc.result = -1;
	  }
	else
	  sc.result = -1;
      }
      break;
#endif

    case CB_SYS_gettimeofday:
      {
	struct timeval _tv, *tv = &_tv;
	struct timezone _tz, *tz = &_tz;

	tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]);

	if (sc.arg1 == 0)
	  tv = NULL;
	if (sc.arg2 == 0)
	  tz = NULL;
	sc.result = gettimeofday (tv, tz);

	if (sc.result == 0)
	  {
	    bu32 t;

	    if (tv)
	      {
		t = tv->tv_sec;
		sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
		t = tv->tv_usec;
		sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
	      }

	    if (sc.arg2)
	      {
		t = tz->tz_minuteswest;
		sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
		t = tz->tz_dsttime;
		sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
	      }
	  }
	else
	  goto sys_finish;
      }
      break;

    case CB_SYS_ioctl:
      /* XXX: hack just enough to get basic stdio w/uClibc ...  */
      tbuf += sprintf (tbuf, "ioctl(%i, %#x, %u)", args[0], args[1], args[2]);
      if (sc.arg2 == 0x5401)
	{
	  sc.result = !isatty (sc.arg1);
	  sc.errcode = 0;
	}
      else
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EINVAL;
	}
      break;

    case CB_SYS_mmap2:
      {
	static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2;

	fmt_ret_hex = 1;
	tbuf += sprintf (tbuf, "mmap2(%#x, %u, %#x, %#x, %i, %u)",
			 args[0], args[1], args[2], args[3], args[4], args[5]);

	sc.errcode = 0;

	if (sc.arg4 & 0x20 /*MAP_ANONYMOUS*/)
	  /* XXX: We don't handle zeroing, but default is all zeros.  */;
	else if (args[4] >= MAX_CALLBACK_FDS)
	  sc.errcode = TARGET_ENOSYS;
	else
	  {
#ifdef HAVE_PREAD
	    char *data = xmalloc (sc.arg2);

	    /* XXX: Should add a cb->pread.  */
	    if (pread (cb->fdmap[args[4]], data, sc.arg2, args[5] << 12) == sc.arg2)
	      sc.write_mem (cb, &sc, heap, data, sc.arg2);
	    else
	      sc.errcode = TARGET_EINVAL;

	    free (data);
#else
	    sc.errcode = TARGET_ENOSYS;
#endif
	  }

	if (sc.errcode)
	  {
	    sc.result = -1;
	    break;
	  }

	sc.result = heap;
	heap += sc.arg2;
	/* Keep it page aligned.  */
	heap = ALIGN (heap, 4096);

	break;
      }

    case CB_SYS_munmap:
      /* XXX: meh, just lie for mmap().  */
      tbuf += sprintf (tbuf, "munmap(%#x, %u)", args[0], args[1]);
      sc.result = 0;
      break;

    case CB_SYS_dup2:
      tbuf += sprintf (tbuf, "dup2(%i, %i)", args[0], args[1]);
      if (sc.arg1 >= MAX_CALLBACK_FDS || sc.arg2 >= MAX_CALLBACK_FDS)
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EINVAL;
	}
      else
	{
	  sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]);
	  goto sys_finish;
	}
      break;

    case CB_SYS__llseek:
      tbuf += sprintf (tbuf, "llseek(%i, %u, %u, %#x, %u)",
		       args[0], args[1], args[2], args[3], args[4]);
      sc.func = TARGET_LINUX_SYS_lseek;
      if (sc.arg2)
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EINVAL;
	}
      else
	{
	  sc.arg2 = sc.arg3;
	  sc.arg3 = args[4];
	  cb_syscall (cb, &sc);
	  if (sc.result != -1)
	    {
	      bu32 z = 0;
	      sc.write_mem (cb, &sc, args[3], (void *)&sc.result, 4);
	      sc.write_mem (cb, &sc, args[3] + 4, (void *)&z, 4);
	    }
	}
      break;

    /* XXX: Should add a cb->pread.  */
    case CB_SYS_pread:
      tbuf += sprintf (tbuf, "pread(%i, %#x, %u, %i)",
		       args[0], args[1], args[2], args[3]);
      if (sc.arg1 >= MAX_CALLBACK_FDS)
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EINVAL;
	}
      else
	{
	  long old_pos, read_result, read_errcode;

	  /* Get current filepos.  */
	  sc.func = TARGET_LINUX_SYS_lseek;
	  sc.arg2 = 0;
	  sc.arg3 = SEEK_CUR;
	  cb_syscall (cb, &sc);
	  if (sc.result == -1)
	    break;
	  old_pos = sc.result;

	  /* Move to the new pos.  */
	  sc.func = TARGET_LINUX_SYS_lseek;
	  sc.arg2 = args[3];
	  sc.arg3 = SEEK_SET;
	  cb_syscall (cb, &sc);
	  if (sc.result == -1)
	    break;

	  /* Read the data.  */
	  sc.func = TARGET_LINUX_SYS_read;
	  sc.arg2 = args[1];
	  sc.arg3 = args[2];
	  cb_syscall (cb, &sc);
	  read_result = sc.result;
	  read_errcode = sc.errcode;

	  /* Move back to the old pos.  */
	  sc.func = TARGET_LINUX_SYS_lseek;
	  sc.arg2 = old_pos;
	  sc.arg3 = SEEK_SET;
	  cb_syscall (cb, &sc);

	  sc.result = read_result;
	  sc.errcode = read_errcode;
	}
      break;

    case CB_SYS_getcwd:
      tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]);

      p = alloca (sc.arg2);
      if (getcwd (p, sc.arg2) == NULL)
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EINVAL;
	}
      else
	{
	  sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2);
	  sc.result = sc.arg1;
	}
      break;

    case CB_SYS_stat64:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "stat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
      cb->stat_map = stat_map_64;
      sc.func = TARGET_LINUX_SYS_stat;
      cb_syscall (cb, &sc);
      cb->stat_map = stat_map_32;
      break;
    case CB_SYS_lstat64:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "lstat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
      cb->stat_map = stat_map_64;
      sc.func = TARGET_LINUX_SYS_lstat;
      cb_syscall (cb, &sc);
      cb->stat_map = stat_map_32;
      break;
    case CB_SYS_fstat64:
      tbuf += sprintf (tbuf, "fstat64(%#x, %u)", args[0], args[1]);
      cb->stat_map = stat_map_64;
      sc.func = TARGET_LINUX_SYS_fstat;
      cb_syscall (cb, &sc);
      cb->stat_map = stat_map_32;
      break;

    case CB_SYS_ftruncate64:
      tbuf += sprintf (tbuf, "ftruncate64(%u, %u)", args[0], args[1]);
      sc.func = TARGET_LINUX_SYS_ftruncate;
      cb_syscall (cb, &sc);
      break;

    case CB_SYS_getuid:
    case CB_SYS_getuid32:
      tbuf += sprintf (tbuf, "getuid()");
      sc.result = getuid ();
      goto sys_finish;
    case CB_SYS_getgid:
    case CB_SYS_getgid32:
      tbuf += sprintf (tbuf, "getgid()");
      sc.result = getgid ();
      goto sys_finish;
    case CB_SYS_setuid:
      sc.arg1 &= 0xffff;
    case CB_SYS_setuid32:
      tbuf += sprintf (tbuf, "setuid(%u)", args[0]);
      sc.result = setuid (sc.arg1);
      goto sys_finish;
    case CB_SYS_setgid:
      sc.arg1 &= 0xffff;
    case CB_SYS_setgid32:
      tbuf += sprintf (tbuf, "setgid(%u)", args[0]);
      sc.result = setgid (sc.arg1);
      goto sys_finish;

    case CB_SYS_getpid:
      tbuf += sprintf (tbuf, "getpid()");
      sc.result = getpid ();
      goto sys_finish;
    case CB_SYS_kill:
      tbuf += sprintf (tbuf, "kill(%u, %i)", args[0], args[1]);
      /* Only let the app kill itself.  */
      if (sc.arg1 != getpid ())
	{
	  sc.result = -1;
	  sc.errcode = TARGET_EPERM;
	}
      else
	{
#ifdef HAVE_KILL
	  sc.result = kill (sc.arg1, sc.arg2);
	  goto sys_finish;
#else
	  sc.result = -1;
	  sc.errcode = TARGET_ENOSYS;
#endif
	}
      break;

    case CB_SYS_open:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "open(%#x:\"%s\", %#x, %o)",
		       args[0], tstr, args[1], args[2]);
      goto case_default;
    case CB_SYS_close:
      tbuf += sprintf (tbuf, "close(%i)", args[0]);
      goto case_default;
    case CB_SYS_read:
      tbuf += sprintf (tbuf, "read(%i, %#x, %u)", args[0], args[1], args[2]);
      goto case_default;
    case CB_SYS_write:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "write(%i, %#x:\"%s\", %u)",
		       args[0], args[1], tstr, args[2]);
      goto case_default;
    case CB_SYS_lseek:
      tbuf += sprintf (tbuf, "lseek(%i, %i, %i)", args[0], args[1], args[2]);
      goto case_default;
    case CB_SYS_unlink:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "unlink(%#x:\"%s\")", args[0], tstr);
      goto case_default;
    case CB_SYS_truncate:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "truncate(%#x:\"%s\", %i)", args[0], tstr, args[1]);
      goto case_default;
    case CB_SYS_ftruncate:
      tbuf += sprintf (tbuf, "ftruncate(%i, %i)", args[0], args[1]);
      goto case_default;
    case CB_SYS_rename:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "rename(%#x:\"%s\", ", args[0], tstr);
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "%#x:\"%s\")", args[1], tstr);
      goto case_default;
    case CB_SYS_stat:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "stat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
      goto case_default;
    case CB_SYS_fstat:
      tbuf += sprintf (tbuf, "fstat(%i, %#x)", args[0], args[1]);
      goto case_default;
    case CB_SYS_lstat:
      if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
	strcpy (tstr, "???");
      tbuf += sprintf (tbuf, "lstat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
      goto case_default;
    case CB_SYS_pipe:
      tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]);
      goto case_default;

    default:
      tbuf += sprintf (tbuf, "???_%i(%#x, %#x, %#x, %#x, %#x, %#x)", sc.func,
		       args[0], args[1], args[2], args[3], args[4], args[5]);
    case_default:
      cb_syscall (cb, &sc);
      break;

    sys_finish:
      if (sc.result == -1)
	{
	  cb->last_errno = errno;
	  sc.errcode = cb->get_errno (cb);
	}
    }

  TRACE_EVENTS (cpu, "syscall_%i(%#x, %#x, %#x, %#x, %#x, %#x) = %li (error = %i)",
		sc.func, args[0], args[1], args[2], args[3], args[4], args[5],
		sc.result, sc.errcode);

  tbuf += sprintf (tbuf, " = ");
  if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
    {
      if (sc.result == -1)
	{
	  tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode);
	  if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS))
	    {
	      sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n",
			      PCREG, sc.func);
	    }
	  SET_DREG (0, -sc.errcode);
	}
      else
	{
	  if (fmt_ret_hex)
	    tbuf += sprintf (tbuf, "%#lx", sc.result);
	  else
	    tbuf += sprintf (tbuf, "%lu", sc.result);
	  SET_DREG (0, sc.result);
	}
    }
  else
    {
      tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode);
      SET_DREG (0, sc.result);
      SET_DREG (1, sc.result2);
      SET_DREG (2, sc.errcode);
    }

  TRACE_SYSCALL (cpu, "%s", _tbuf);
}
Beispiel #20
0
/* Return from trap.  */
USI
frv_rett (SIM_CPU *current_cpu, PCADDR pc, BI debug_field)
{
  USI new_pc;
  /* if (normal running mode and debug_field==0
       PC=PCSR
       PSR.ET=1
       PSR.S=PSR.PS
     else if (debug running mode and debug_field==1)
       PC=(BPCSR)
       PSR.ET=BPSR.BET
       PSR.S=BPSR.BS
       change to normal running mode
  */
  int psr_s = GET_H_PSR_S ();
  int psr_et = GET_H_PSR_ET ();

  /* Check for exceptions in the priority order listed in the FRV Architecture
     Volume 2.  */
  if (! psr_s)
    {
      /* Halt if PSR.ET is not set.  See chapter 6 of the LSI.  */
      if (! psr_et)
	{
	  SIM_DESC sd = CPU_STATE (current_cpu);
	  sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
	}

      /* privileged_instruction interrupt will have already been queued by
	 frv_detect_insn_access_interrupts.  */
      new_pc = pc + 4;
    }
  else if (psr_et)
    {
      /* Halt if PSR.S is set.  See chapter 6 of the LSI.  */
      if (psr_s)
	{
	  SIM_DESC sd = CPU_STATE (current_cpu);
	  sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
	}

      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
      new_pc = pc + 4;
    }
  else if (! CPU_DEBUG_STATE (current_cpu) && debug_field == 0)
    {
      USI psr = GET_PSR ();
      /* Return from normal running state.  */
      new_pc = GET_H_SPR (H_SPR_PCSR);
      SET_PSR_ET (psr, 1);
      SET_PSR_S (psr, GET_PSR_PS (psr));
      sim_queue_fn_si_write (current_cpu, frvbf_h_spr_set, H_SPR_PSR, psr);
    }
  else if (CPU_DEBUG_STATE (current_cpu) && debug_field == 1)
    {
      USI psr = GET_PSR ();
      /* Return from debug state.  */
      new_pc = GET_H_SPR (H_SPR_BPCSR);
      SET_PSR_ET (psr, GET_H_BPSR_BET ());
      SET_PSR_S (psr, GET_H_BPSR_BS ());
      sim_queue_fn_si_write (current_cpu, frvbf_h_spr_set, H_SPR_PSR, psr);
      CPU_DEBUG_STATE (current_cpu) = 0;
    }
  else
    new_pc = pc + 4;

  return new_pc;
}
Beispiel #21
0
/* Handle TRA and TIRA insns.  */
void
frv_itrap (SIM_CPU *current_cpu, PCADDR pc, USI base, SI offset)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  USI num = ((base + offset) & 0x7f) + 0x80;

#ifdef SIM_HAVE_BREAKPOINTS
  /* Check for breakpoints "owned" by the simulator first, regardless
     of --environment.  */
  if (num == TRAP_BREAKPOINT)
    {
      /* First try sim-break.c.  If it's a breakpoint the simulator "owns"
	 it doesn't return.  Otherwise it returns and let's us try.  */
      sim_handle_breakpoint (sd, current_cpu, pc);
      /* Fall through.  */
    }
#endif

  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
    {
      frv_queue_software_interrupt (current_cpu, num);
      return;
    }

  switch (num)
    {
    case TRAP_SYSCALL :
      {
	CB_SYSCALL s;
	CB_SYSCALL_INIT (&s);
	s.func = GET_H_GR (7);
	s.arg1 = GET_H_GR (8);
	s.arg2 = GET_H_GR (9);
	s.arg3 = GET_H_GR (10);

	if (s.func == TARGET_SYS_exit)
	  {
	    sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
	  }

	s.p1 = (PTR) sd;
	s.p2 = (PTR) current_cpu;
	s.read_mem = syscall_read_mem;
	s.write_mem = syscall_write_mem;
	cb_syscall (cb, &s);
	SET_H_GR (8, s.result);
	SET_H_GR (9, s.result2);
	SET_H_GR (10, s.errcode);
	break;
      }

    case TRAP_BREAKPOINT:
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
      break;

      /* Add support for dumping registers, either at fixed traps, or all
	 unknown traps if configured with --enable-sim-trapdump.  */
    default:
#if !TRAPDUMP
      frv_queue_software_interrupt (current_cpu, num);
      return;
#endif

#ifdef TRAP_REGDUMP1
    case TRAP_REGDUMP1:
#endif

#ifdef TRAP_REGDUMP2
    case TRAP_REGDUMP2:
#endif

#if TRAPDUMP || (defined (TRAP_REGDUMP1)) || (defined (TRAP_REGDUMP2))
      {
	char buf[256];
	int i, j;

	buf[0] = 0;
	if (STATE_TEXT_SECTION (sd)
	    && pc >= STATE_TEXT_START (sd)
	    && pc < STATE_TEXT_END (sd))
	  {
	    const char *pc_filename = (const char *)0;
	    const char *pc_function = (const char *)0;
	    unsigned int pc_linenum = 0;

	    if (bfd_find_nearest_line (STATE_PROG_BFD (sd),
				       STATE_TEXT_SECTION (sd),
				       (struct bfd_symbol **) 0,
				       pc - STATE_TEXT_START (sd),
				       &pc_filename, &pc_function, &pc_linenum)
		&& (pc_function || pc_filename))
	      {
		char *p = buf+2;
		buf[0] = ' ';
		buf[1] = '(';
		if (pc_function)
		  {
		    strcpy (p, pc_function);
		    p += strlen (p);
		  }
		else
		  {
		    char *q = (char *) strrchr (pc_filename, '/');
		    strcpy (p, (q) ? q+1 : pc_filename);
		    p += strlen (p);
		  }

		if (pc_linenum)
		  {
		    sprintf (p, " line %d", pc_linenum);
		    p += strlen (p);
		  }

		p[0] = ')';
		p[1] = '\0';
		if ((p+1) - buf > sizeof (buf))
		  abort ();
	      }
	  }

	sim_io_printf (sd,
		       "\nRegister dump,    pc = 0x%.8x%s, base = %u, offset = %d\n",
		       (unsigned)pc, buf, (unsigned)base, (int)offset);

	for (i = 0; i < 64; i += 8)
	  {
	    long g0 = (long)GET_H_GR (i);
	    long g1 = (long)GET_H_GR (i+1);
	    long g2 = (long)GET_H_GR (i+2);
	    long g3 = (long)GET_H_GR (i+3);
	    long g4 = (long)GET_H_GR (i+4);
	    long g5 = (long)GET_H_GR (i+5);
	    long g6 = (long)GET_H_GR (i+6);
	    long g7 = (long)GET_H_GR (i+7);

	    if ((g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7) != 0)
	      sim_io_printf (sd,
			     "\tgr%02d - gr%02d:   0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
			     i, i+7, g0, g1, g2, g3, g4, g5, g6, g7);
	  }

	for (i = 0; i < 64; i += 8)
	  {
	    long f0 = (long)GET_H_FR (i);
	    long f1 = (long)GET_H_FR (i+1);
	    long f2 = (long)GET_H_FR (i+2);
	    long f3 = (long)GET_H_FR (i+3);
	    long f4 = (long)GET_H_FR (i+4);
	    long f5 = (long)GET_H_FR (i+5);
	    long f6 = (long)GET_H_FR (i+6);
	    long f7 = (long)GET_H_FR (i+7);

	    if ((f0 | f1 | f2 | f3 | f4 | f5 | f6 | f7) != 0)
	      sim_io_printf (sd,
			     "\tfr%02d - fr%02d:   0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
			     i, i+7, f0, f1, f2, f3, f4, f5, f6, f7);
	  }

	sim_io_printf (sd,
		       "\tlr/lcr/cc/ccc: 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
		       (long)GET_H_SPR (272),
		       (long)GET_H_SPR (273),
		       (long)GET_H_SPR (256),
		       (long)GET_H_SPR (263));
      }
      break;
#endif
    }
}
Beispiel #22
0
USI
fr30_int (SIM_CPU *current_cpu, PCADDR pc, int num)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

#ifdef SIM_HAVE_BREAKPOINTS
  /* Check for breakpoints "owned" by the simulator first, regardless
     of --environment.  */
  if (num == TRAP_BREAKPOINT)
    {
      /* First try sim-break.c.  If it's a breakpoint the simulator "owns"
	 it doesn't return.  Otherwise it returns and let's us try.  */
      sim_handle_breakpoint (sd, current_cpu, pc);
      /* Fall through.  */
    }
#endif

  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
    {
      /* The new pc is the trap vector entry.
	 We assume there's a branch there to some handler.  */
      USI new_pc;
      setup_int (current_cpu, pc);
      fr30bf_h_ibit_set (current_cpu, 0);
      new_pc = GETMEMSI (current_cpu, pc,
			 fr30bf_h_dr_get (current_cpu, H_DR_TBR)
			 + 1024 - ((num + 1) * 4));
      return new_pc;
    }

  switch (num)
    {
    case TRAP_SYSCALL :
      {
	/* TODO: find out what the ABI for this is */
	CB_SYSCALL s;

	CB_SYSCALL_INIT (&s);
	s.func = fr30bf_h_gr_get (current_cpu, 0);
	s.arg1 = fr30bf_h_gr_get (current_cpu, 4);
	s.arg2 = fr30bf_h_gr_get (current_cpu, 5);
	s.arg3 = fr30bf_h_gr_get (current_cpu, 6);

	if (s.func == TARGET_SYS_exit)
	  {
	    sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
	  }

	s.p1 = (PTR) sd;
	s.p2 = (PTR) current_cpu;
	s.read_mem = syscall_read_mem;
	s.write_mem = syscall_write_mem;
	cb_syscall (cb, &s);
	fr30bf_h_gr_set (current_cpu, 2, s.errcode); /* TODO: check this one */
	fr30bf_h_gr_set (current_cpu, 4, s.result);
	fr30bf_h_gr_set (current_cpu, 1, s.result2); /* TODO: check this one */
	break;
      }

    case TRAP_BREAKPOINT:
      sim_engine_halt (sd, current_cpu, NULL, pc,
		       sim_stopped, SIM_SIGTRAP);
      break;

    default :
      {
	USI new_pc;
	setup_int (current_cpu, pc);
	fr30bf_h_ibit_set (current_cpu, 0);
	new_pc = GETMEMSI (current_cpu, pc,
			   fr30bf_h_dr_get (current_cpu, H_DR_TBR)
			   + 1024 - ((num + 1) * 4));
	return new_pc;
      }
    }

  /* Fake an "reti" insn.
     Since we didn't push anything to stack, all we need to do is
     update pc.  */
  return pc + 2;
}