Пример #1
0
/* WARNING: If this is called during a simulated instruction (ie. from a read/
 * write mem callback), the interrupt will be delivered after the instruction
 * has finished executeing */
void
report_interrupt (int line)
{
  uint32_t lmask = 1 << line;

  /* Disable doze and sleep mode */
  cpu_state.sprs[SPR_PMR] &= ~(SPR_PMR_DME | SPR_PMR_SME);

  /* If PIC is disabled, don't set any register, just raise EXCEPT_INT */
  if (!config.pic.enabled)
    {
      if (cpu_state.sprs[SPR_SR] & SPR_SR_IEE)
	except_handle (EXCEPT_INT, cpu_state.sprs[SPR_EEAR_BASE]);
      return;
    }

  if (cpu_state.pic_lines & lmask)
    {
      /* No edge occured, warn about performance penalty and exit */
      fprintf (stderr, "Warning: Int line %d did not change state\n", line);
      return;
    }

  cpu_state.pic_lines |= lmask;
  cpu_state.sprs[SPR_PICSR] |= lmask;

  if ((cpu_state.sprs[SPR_PICMR] & lmask) || line < 2)
    if (cpu_state.sprs[SPR_SR] & SPR_SR_IEE)
      SCHED_ADD (pic_rep_int, NULL, 0);
}
Пример #2
0
/*! Restarts the tick timer */
static void
tick_restart (void *dat)
{
  cpu_state.sprs[SPR_TTCR] = 0;
  cycle_count_at_tick_start = runtime.sim.cycles;
  SCHED_ADD (tick_restart, NULL, cpu_state.sprs[SPR_TTMR] & SPR_TTMR_TP);
}
Пример #3
0
/* Called whenever interrupts get enabled */
void
pic_ints_en (void)
{
  if ((cpu_state.sprs[SPR_PICMR] & cpu_state.sprs[SPR_PICSR]))
    SCHED_ADD (pic_rep_int, NULL, 0);
}
Пример #4
0
/*! Schedules the timer jobs */
static void
sched_timer_job (uorreg_t prev_ttmr)
{
  uorreg_t ttmr = cpu_state.sprs[SPR_TTMR];
  uint32_t match_ttmr = ttmr & SPR_TTMR_TP;
  /* TTCR register, only concerned with part of TTCR which will trigger int */
  uint32_t match_ttcr = spr_read_ttcr () & SPR_TTMR_TP;
  uint32_t cycles_until_except;

  /* On clearing TTMR interrupt signal bit remove previous jobs if they 
     exist */
  if ((prev_ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
    {
      SCHED_FIND_REMOVE (tick_raise_except, NULL);
    }

  switch (prev_ttmr & SPR_TTMR_M)
    {
    case SPR_TTMR_RT:
      SCHED_FIND_REMOVE (tick_restart, NULL);
      break;

    case SPR_TTMR_SR:
      SCHED_FIND_REMOVE (tick_one_shot, NULL);
      break;
    }

  /* Calculate cycles until next tick exception, based on current TTCR value */
  if (match_ttmr >= match_ttcr)
    {
      cycles_until_except = match_ttmr - match_ttcr;
    }
  else
    {
      /* Cycles after "wrap" of section of TTCR which will cause a match and, 
	 potentially, an exception */
      cycles_until_except = match_ttmr + (0x0fffffffu - match_ttcr) + 1;
    }

  switch (ttmr & SPR_TTMR_M)
    {
    case 0:			/* Disabled timer */
      if (!cycles_until_except && (ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
	SCHED_ADD (tick_raise_except, NULL, 0);
      break;

    case SPR_TTMR_RT:		/* Auto-restart timer */
      SCHED_ADD (tick_restart, NULL, cycles_until_except);
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
	SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
      break;

    case SPR_TTMR_SR:		/* One-shot timer */
      if (tick_counting)
	{
	  SCHED_ADD (tick_one_shot, NULL, cycles_until_except);
	  if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
	    SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
	}
      break;

    case SPR_TTMR_CR:		/* Continuos timer */
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
	SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
    }
}