/* 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;
}
Ejemplo n.º 2
0
/* 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;
      
      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);
	}

      interrupts->nb_interrupts_raised++;
      cpu_add_cycles (interrupts->cpu, 14);
      return 1;
    }
  return 0;
}