⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interrupts.c

📁 gdb-6.0 linux 下的调试工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* interrupts.c -- 68HC11 Interrupts Emulation   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.   Written by Stephane Carrez (stcarrez@nerim.fr)This file is part of GDB, GAS, and the GNU binutils.GDB, GAS, and the GNU binutils are free software; you can redistributethem and/or modify them under the terms of the GNU General PublicLicense as published by the Free Software Foundation; either version1, or (at your option) any later version.GDB, GAS, and the GNU binutils are distributed in the hope that theywill be useful, but WITHOUT ANY WARRANTY; without even the impliedwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Seethe GNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this file; see the file COPYING.  If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#include "sim-main.h"#include "sim-options.h"static const char *interrupt_names[] = {  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",  "R8",  "R9",  "R10",  "R11",  "SCI",  "SPI",  "AINPUT",  "AOVERFLOW",  "TOVERFLOW",  "OUT5",  "OUT4",  "OUT3",  "OUT2",  "OUT1",  "INC3",  "INC2",  "INC1",  "RT",  "IRQ",  "XIRQ",  "SWI",  "ILL",  "COPRESET",  "COPFAIL",  "RESET"};struct interrupt_def idefs[] = {  /* Serial interrupts.  */  { M6811_INT_SCI,      M6811_SCSR,   M6811_TDRE,  M6811_SCCR2,  M6811_TIE },  { M6811_INT_SCI,      M6811_SCSR,   M6811_TC,    M6811_SCCR2,  M6811_TCIE },  { M6811_INT_SCI,      M6811_SCSR,   M6811_RDRF,  M6811_SCCR2,  M6811_RIE },  { M6811_INT_SCI,      M6811_SCSR,   M6811_IDLE,  M6811_SCCR2,  M6811_ILIE },  /* SPI interrupts.  */  { M6811_INT_SPI,      M6811_SPSR,   M6811_SPIF,  M6811_SPCR,   M6811_SPIE },  /* Realtime interrupts.  */  { M6811_INT_TCTN,     M6811_TFLG2,  M6811_TOF,   M6811_TMSK2,  M6811_TOI },  { M6811_INT_RT,       M6811_TFLG2,  M6811_RTIF,  M6811_TMSK2,  M6811_RTII },  /* Output compare interrupts.  */  { M6811_INT_OUTCMP1,  M6811_TFLG1,  M6811_OC1F,  M6811_TMSK1,  M6811_OC1I },  { M6811_INT_OUTCMP2,  M6811_TFLG1,  M6811_OC2F,  M6811_TMSK1,  M6811_OC2I },  { M6811_INT_OUTCMP3,  M6811_TFLG1,  M6811_OC3F,  M6811_TMSK1,  M6811_OC3I },  { M6811_INT_OUTCMP4,  M6811_TFLG1,  M6811_OC4F,  M6811_TMSK1,  M6811_OC4I },  { M6811_INT_OUTCMP5,  M6811_TFLG1,  M6811_OC5F,  M6811_TMSK1,  M6811_OC5I },  /* Input compare interrupts.  */  { M6811_INT_INCMP1,   M6811_TFLG1,  M6811_IC1F,  M6811_TMSK1,  M6811_IC1I },  { M6811_INT_INCMP2,   M6811_TFLG1,  M6811_IC2F,  M6811_TMSK1,  M6811_IC2I },  { M6811_INT_INCMP3,   M6811_TFLG1,  M6811_IC3F,  M6811_TMSK1,  M6811_IC3I },  /* Pulse accumulator.  */  { M6811_INT_AINPUT,   M6811_TFLG2,  M6811_PAIF,  M6811_TMSK2,  M6811_PAII },  { M6811_INT_AOVERFLOW,M6811_TFLG2,  M6811_PAOVF, M6811_TMSK2,  M6811_PAOVI},#if 0  { M6811_INT_COPRESET, M6811_CONFIG, M6811_NOCOP, 0,            0 },  { M6811_INT_COPFAIL,  M6811_CONFIG, M6811_NOCOP, 0,            0 }#endif};#define TableSize(X) (sizeof X / sizeof(X[0]))#define CYCLES_MAX ((((signed64) 1) << 62) - 1)enum{  OPTION_INTERRUPT_INFO = OPTION_START,  OPTION_INTERRUPT_CATCH,  OPTION_INTERRUPT_CLEAR};static DECLARE_OPTION_HANDLER (interrupt_option_handler);static const OPTION interrupt_options[] ={  { {"interrupt-info", no_argument, NULL, OPTION_INTERRUPT_INFO },      '\0', NULL, "Print information about interrupts",      interrupt_option_handler },  { {"interrupt-catch", required_argument, NULL, OPTION_INTERRUPT_CATCH },      '\0', "NAME[,MODE]",    "Catch interrupts when they are raised or taken\n"    "NAME   Name of the interrupt\n"    "MODE   Optional mode (`taken' or `raised')",      interrupt_option_handler },  { {"interrupt-clear", required_argument, NULL, OPTION_INTERRUPT_CLEAR },      '\0', "NAME", "No longer catch the interrupt",      interrupt_option_handler },    { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }};/* Initialize the interrupts module.  */voidinterrupts_initialize (SIM_DESC sd, struct _sim_cpu *proc){  struct interrupts *interrupts = &proc->cpu_interrupts;    interrupts->cpu          = proc;  sim_add_option_table (sd, 0, interrupt_options);}/* Initialize the interrupts of the processor.  */voidinterrupts_reset (struct interrupts *interrupts){  int i;    interrupts->pending_mask = 0;  if (interrupts->cpu->cpu_mode & M6811_SMOD)    interrupts->vectors_addr = 0xbfc0;  else    interrupts->vectors_addr = 0xffc0;  interrupts->nb_interrupts_raised = 0;  interrupts->min_mask_cycles = CYCLES_MAX;  interrupts->max_mask_cycles = 0;  interrupts->last_mask_cycles = 0;  interrupts->start_mask_cycle = -1;  interrupts->xirq_start_mask_cycle = -1;  interrupts->xirq_max_mask_cycles = 0;  interrupts->xirq_min_mask_cycles = CYCLES_MAX;  interrupts->xirq_last_mask_cycles = 0;    for (i = 0; i < M6811_INT_NUMBER; i++)    {      interrupts->interrupt_order[i] = i;    }  /* Clear the interrupt history table.  */  interrupts->history_index = 0;  memset (interrupts->interrupts_history, 0,          sizeof (interrupts->interrupts_history));  memset (interrupts->interrupts, 0,          sizeof (interrupts->interrupts));  /* In bootstrap mode, initialize the vector table to point     to the RAM location.  */  if (interrupts->cpu->cpu_mode == M6811_SMOD)    {      bfd_vma addr = interrupts->vectors_addr;      uint16 vector = 0x0100 - 3 * (M6811_INT_NUMBER - 1);      for (i = 0; i < M6811_INT_NUMBER; i++)        {          memory_write16 (interrupts->cpu, addr, vector);          addr += 2;          vector += 3;        }    }}static intfind_interrupt (const char *name){  int i;  if (name)    for (i = 0; i < M6811_INT_NUMBER; i++)      if (strcasecmp (name, interrupt_names[i]) == 0)        return i;  return -1;}static SIM_RCinterrupt_option_handler (SIM_DESC sd, sim_cpu *cpu,                          int opt, char *arg, int is_command){  char *p;  int mode;  int id;  struct interrupts *interrupts;  if (cpu == 0)    cpu = STATE_CPU (sd, 0);  interrupts = &cpu->cpu_interrupts;  switch (opt)    {    case OPTION_INTERRUPT_INFO:      for (id = 0; id < M6811_INT_NUMBER; id++)        {          sim_io_eprintf (sd, "%-10.10s ", interrupt_names[id]);          switch (interrupts->interrupts[id].stop_mode)            {            case SIM_STOP_WHEN_RAISED:              sim_io_eprintf (sd, "catch raised ");              break;            case SIM_STOP_WHEN_TAKEN:              sim_io_eprintf (sd, "catch taken  ");              break;            case SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN:              sim_io_eprintf (sd, "catch all    ");              break;            default:              sim_io_eprintf (sd, "             ");              break;            }          sim_io_eprintf (sd, "%ld\n",                          interrupts->interrupts[id].raised_count);        }      break;    case OPTION_INTERRUPT_CATCH:      p = strchr (arg, ',');      if (p)        *p++ = 0;      mode = SIM_STOP_WHEN_RAISED;      id = find_interrupt (arg);      if (id < 0)        sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);      if (p && strcasecmp (p, "raised") == 0)        mode = SIM_STOP_WHEN_RAISED;      else if (p && strcasecmp (p, "taken") == 0)        mode = SIM_STOP_WHEN_TAKEN;      else if (p && strcasecmp (p, "all") == 0)        mode = SIM_STOP_WHEN_RAISED | SIM_STOP_WHEN_TAKEN;      else if (p)        {          sim_io_eprintf (sd, "Invalid argument: %s\n", p);          break;        }      if (id >= 0)        interrupts->interrupts[id].stop_mode = mode;      break;    case OPTION_INTERRUPT_CLEAR:      mode = SIM_STOP_WHEN_RAISED;      id = find_interrupt (arg);      if (id < 0)        sim_io_eprintf (sd, "Interrupt name not recognized: %s\n", arg);      else        interrupts->interrupts[id].stop_mode = 0;            break;          }  return SIM_RC_OK;}/* 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.  */voidinterrupts_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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -