Exemple #1
0
static void
bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
{
  memset (&cpu->state, 0, sizeof (cpu->state));

  PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;

  bfin_model_cpu_init (sd, cpu);

  /* Set default stack to top of scratch pad.  */
  SET_SPREG (BFIN_DEFAULT_MEM_SIZE);
  SET_KSPREG (BFIN_DEFAULT_MEM_SIZE);
  SET_USPREG (BFIN_DEFAULT_MEM_SIZE);

  /* This is what the hardware likes.  */
  SET_SYSCFGREG (0x30);
}
Exemple #2
0
void
cec_return (SIM_CPU *cpu, int ivg)
{
  SIM_DESC sd = CPU_STATE (cpu);
  struct bfin_cec *cec;
  bool snen;
  int curr_ivg;
  bu32 oldpc, newpc;

  oldpc = PCREG;

  BFIN_CPU_STATE.did_jump = true;
  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
    {
      SET_PCREG (cec_read_ret_reg (cpu, ivg));
      TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC");
      return;
    }

  cec = CEC_STATE (cpu);

  /* XXX: This isn't entirely correct ...  */
  cec->ipend &= ~IVG_EMU_B;

  curr_ivg = _cec_get_ivg (cec);
  if (curr_ivg == -1)
    curr_ivg = IVG_USER;
  if (ivg == -1)
    ivg = curr_ivg;

  TRACE_EVENTS (cpu, "returning from EVT%i (should be EVT%i)", curr_ivg, ivg);

  /* Not allowed to return from usermode.  */
  if (curr_ivg == IVG_USER)
    cec_exception (cpu, VEC_ILL_RES);

  if (ivg > IVG15 || ivg < 0)
    sim_io_error (sd, "%s: ivg %i out of range !", __func__, ivg);

  _cec_require_supervisor (cpu, cec);

  switch (ivg)
    {
    case IVG_EMU:
      /* RTE -- only valid in emulation mode.  */
      /* XXX: What does the hardware do ?  */
      if (curr_ivg != IVG_EMU)
	cec_exception (cpu, VEC_ILL_RES);
      break;
    case IVG_NMI:
      /* RTN -- only valid in NMI.  */
      /* XXX: What does the hardware do ?  */
      if (curr_ivg != IVG_NMI)
	cec_exception (cpu, VEC_ILL_RES);
      break;
    case IVG_EVX:
      /* RTX -- only valid in exception.  */
      /* XXX: What does the hardware do ?  */
      if (curr_ivg != IVG_EVX)
	cec_exception (cpu, VEC_ILL_RES);
      break;
    default:
      /* RTI -- not valid in emulation, nmi, exception, or user.  */
      /* XXX: What does the hardware do ?  */
      if (curr_ivg == IVG_EMU || curr_ivg == IVG_NMI
	  || curr_ivg == IVG_EVX || curr_ivg == IVG_USER)
	cec_exception (cpu, VEC_ILL_RES);
      break;
    case IVG_IRPTEN:
      /* XXX: Is this even possible ?  */
      excp_to_sim_halt (sim_stopped, SIM_SIGABRT);
      break;
    }
  newpc = cec_read_ret_reg (cpu, ivg);

  /* XXX: Does this nested trick work on EMU/NMI/EVX ?  */
  snen = (newpc & 1);
  /* XXX: Delayed clear shows bad PCREG register trace above ?  */
  SET_PCREG (newpc & ~1);

  TRACE_BRANCH (cpu, oldpc, PCREG, -1, "CEC changed PC (from EVT%i)", ivg);

  /* Update ipend after the TRACE_BRANCH so dv-bfin_trace
     knows current CEC state wrt overflow.  */
  if (!snen)
    cec->ipend &= ~(1 << ivg);

  /* Disable global interrupt mask to let any interrupt take over, but
     only when we were already in a RTI level.  Only way we could have
     raised at that point is if it was cleared in the first place.  */
  if (ivg >= IVG_IVHW || ivg == IVG_RST)
    cec_irpten_disable (cpu, cec);

  /* When going from super to user, we clear LSB in LB regs in case
     it was set on the transition up.
     Also need to load SP alias with USP.  */
  if (_cec_get_ivg (cec) == -1)
    {
      int i;
      for (i = 0; i < 2; ++i)
	if (LBREG (i) & 1)
	  SET_LBREG (i, LBREG (i) & ~1);
      SET_KSPREG (SPREG);
      SET_SPREG (USPREG);
    }

  /* Check for pending interrupts before we return to usermode.  */
  _cec_check_pending (cpu, cec);
}