コード例 #1
0
ファイル: dv-bfin_cec.c プロジェクト: Drakey83/steamlink-sdk
void
cec_require_supervisor (SIM_CPU *cpu)
{
  /* Do not call _cec_require_supervisor() to avoid CEC_STATE()
     as that macro requires OS operating mode.  */
  if (cec_is_user_mode (cpu))
    cec_exception (cpu, VEC_ILL_RES);
}
コード例 #2
0
ファイル: interp.c プロジェクト: ChrisG0x20/gdb
static sim_cia
step_once (SIM_CPU *cpu)
{
  SIM_DESC sd = CPU_STATE (cpu);
  bu32 insn_len, oldpc = PCREG;
  int i;
  bool ssstep;

  if (TRACE_ANY_P (cpu))
    trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu),
		  NULL, 0, " "); /* Use a space for gcc warnings.  */

  /* Handle hardware single stepping when lower than EVT3, and when SYSCFG
     has already had the SSSTEP bit enabled.  */
  ssstep = false;
  if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT
      && (SYSCFGREG & SYSCFG_SSSTEP))
    {
      int ivg = cec_get_ivg (cpu);
      if (ivg == -1 || ivg > 3)
	ssstep = true;
    }

#if 0
  /* XXX: Is this what happens on the hardware ?  */
  if (cec_get_ivg (cpu) == EVT_EMU)
    cec_return (cpu, EVT_EMU);
#endif

  BFIN_CPU_STATE.did_jump = false;

  insn_len = interp_insn_bfin (cpu, oldpc);

  /* If we executed this insn successfully, then we always decrement
     the loop counter.  We don't want to update the PC though if the
     last insn happened to be a change in code flow (jump/etc...).  */
  if (!BFIN_CPU_STATE.did_jump)
    SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len));
  for (i = 1; i >= 0; --i)
    if (LCREG (i) && oldpc == LBREG (i))
      {
	SET_LCREG (i, LCREG (i) - 1);
	if (LCREG (i))
	  break;
      }

  ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));

  /* Handle hardware single stepping only if we're still lower than EVT3.
     XXX: May not be entirely correct wrt EXCPT insns.  */
  if (ssstep)
    {
      int ivg = cec_get_ivg (cpu);
      if (ivg == -1 || ivg > 3)
	{
	  INSN_LEN = 0;
	  cec_exception (cpu, VEC_STEP);
	}
    }

  return oldpc;
}
コード例 #3
0
ファイル: dv-bfin_cec.c プロジェクト: Drakey83/steamlink-sdk
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);
}
コード例 #4
0
ファイル: dv-bfin_cec.c プロジェクト: Drakey83/steamlink-sdk
static void
_cec_require_supervisor (SIM_CPU *cpu, struct bfin_cec *cec)
{
  if (_cec_is_user_mode (cec))
    cec_exception (cpu, VEC_ILL_RES);
}