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

📄 dv-m68hc11.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.    Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.    Written by Stephane Carrez (stcarrez@nerim.fr)    (From a driver model Contributed by Cygnus Solutions.)        This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.        This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.        You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        */#include "sim-main.h"#include "sim-hw.h"#include "hw-main.h"#include "sim-options.h"#include "hw-base.h"#include <limits.h>/* DEVICE        m68hc11cpu - m68hc11 cpu virtual device        m68hc12cpu - m68hc12 cpu virtual device      DESCRIPTION        Implements the external m68hc11/68hc12 functionality.  This includes        the delivery of of interrupts generated from other devices and the        handling of device specific registers.   PROPERTIES   reg <base> <size>        Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).   clock <hz>        Frequency of the quartz used by the processor.   mode [single | expanded | bootstrap | test]        Cpu operating mode (the MODA and MODB external pins).   PORTS   reset (input)        Reset the cpu and generates a cpu-reset event (used to reset        other devices).   nmi (input)        Deliver a non-maskable interrupt to the processor.   set-port-a (input)   set-port-c (input)   set-pord-d (input)        Allow an external device to set the value of port A, C or D inputs.   cpu-reset (output)        Event generated after the CPU performs a reset.   port-a (output)   port-b (output)   port-c (output)   port-d (output)        Event generated when the value of the output port A, B, C or D	changes.   BUGS        When delivering an interrupt, this code assumes that there is only        one processor (number 0).   */enum{  OPTION_OSC_SET = OPTION_START,  OPTION_OSC_CLEAR,  OPTION_OSC_INFO};static DECLARE_OPTION_HANDLER (m68hc11_option_handler);static const OPTION m68hc11_options[] ={  { {"osc-set", required_argument, NULL, OPTION_OSC_SET },      '\0', "BIT,FREQ", "Set the oscillator on input port BIT",      m68hc11_option_handler },  { {"osc-clear", required_argument, NULL, OPTION_OSC_CLEAR },      '\0', "BIT", "Clear oscillator on input port BIT",      m68hc11_option_handler },  { {"osc-info", no_argument, NULL, OPTION_OSC_INFO },      '\0', NULL, "Print information about current input oscillators",      m68hc11_option_handler },    { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }};struct input_osc{  signed64         on_time;  signed64         off_time;  signed64         repeat;  struct hw_event *event;  const char      *name;  uint8            mask;  uint8            value;  uint16           addr;};#define NR_PORT_A_OSC (4)#define NR_PORT_B_OSC (0)#define NR_PORT_C_OSC (8)#define NR_PORT_D_OSC (6)#define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)struct m68hc11cpu {  /* Pending interrupts for delivery by event handler.  */  int              pending_reset;  int              pending_nmi;  int              pending_level;  struct hw_event  *event;  unsigned_word    attach_address;  int              attach_size;  int              attach_space;  int              last_oscillator;  struct input_osc oscillators[NR_OSC];};/* input port ID's */ enum {  RESET_PORT,  NMI_PORT,  IRQ_PORT,  CPU_RESET_PORT,  SET_PORT_A,  SET_PORT_C,  SET_PORT_D,  CPU_WRITE_PORT,  PORT_A,  PORT_B,  PORT_C,  PORT_D,  CAPTURE};static const struct hw_port_descriptor m68hc11cpu_ports[] = {  /* Interrupt inputs.  */  { "reset",     RESET_PORT,     0, input_port, },  { "nmi",       NMI_PORT,       0, input_port, },  { "irq",       IRQ_PORT,       0, input_port, },  { "set-port-a", SET_PORT_A,    0, input_port, },  { "set-port-c", SET_PORT_C,    0, input_port, },  { "set-port-d", SET_PORT_D,    0, input_port, },  { "cpu-write-port", CPU_WRITE_PORT,    0, input_port, },  /* Events generated for connection to other devices.  */  { "cpu-reset", CPU_RESET_PORT, 0, output_port, },  /* Events generated when the corresponding port is     changed by the program.  */  { "port-a",    PORT_A,         0, output_port, },  { "port-b",    PORT_B,         0, output_port, },  { "port-c",    PORT_C,         0, output_port, },  { "port-d",    PORT_D,         0, output_port, },  { "capture",   CAPTURE,        0, output_port, },  { NULL, },};static hw_io_read_buffer_method m68hc11cpu_io_read_buffer;static hw_io_write_buffer_method m68hc11cpu_io_write_buffer;static hw_ioctl_method m68hc11_ioctl;/* Finish off the partially created hw device.  Attach our local   callbacks.  Wire up our port names etc.  */static hw_port_event_method m68hc11cpu_port_event;static void make_oscillator (struct m68hc11cpu *controller,                             const char *id, uint16 addr, uint8 mask);static struct input_osc *find_oscillator (struct m68hc11cpu *controller,                                          const char *id);static void reset_oscillators (struct hw *me);static voiddv_m6811_attach_address_callback (struct hw *me,                                  int level,                                  int space,                                  address_word addr,                                  address_word nr_bytes,                                  struct hw *client){  HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",	     level, space, (unsigned long) addr, (unsigned long) nr_bytes,             hw_path (client)));  if (space != io_map)    {      sim_core_attach (hw_system (me),		       NULL, /*cpu*/		       level,		       access_read_write_exec,		       space, addr,		       nr_bytes,		       0, /* modulo */		       client,		       NULL);    }  else    {      /*printf("Attach from sub device: %d\n", (long) addr);*/      sim_core_attach (hw_system (me),		       NULL, /*cpu*/		       level,		       access_io,		       space, addr,		       nr_bytes,		       0, /* modulo */		       client,		       NULL);    }}static voiddv_m6811_detach_address_callback (struct hw *me,                                  int level,                                  int space,                                  address_word addr,                                  address_word nr_bytes,                                  struct hw *client){  sim_core_detach (hw_system (me), NULL, /*cpu*/                   level, space, addr);}static voidm68hc11_delete (struct hw* me){  struct m68hc11cpu *controller;    controller = hw_data (me);  reset_oscillators (me);  hw_detach_address (me, M6811_IO_LEVEL,		     controller->attach_space,		     controller->attach_address,		     controller->attach_size, me);}static voidattach_m68hc11_regs (struct hw *me,		     struct m68hc11cpu *controller){  SIM_DESC sd;  sim_cpu *cpu;  reg_property_spec reg;  const char *cpu_mode;    if (hw_find_property (me, "reg") == NULL)    hw_abort (me, "Missing \"reg\" property");  if (!hw_find_reg_array_property (me, "reg", 0, &reg))    hw_abort (me, "\"reg\" property must contain one addr/size entry");  hw_unit_address_to_attach_address (hw_parent (me),				     &reg.address,				     &controller->attach_space,				     &controller->attach_address,				     me);  hw_unit_size_to_attach_size (hw_parent (me),			       &reg.size,			       &controller->attach_size, me);  hw_attach_address (hw_parent (me), M6811_IO_LEVEL,		     controller->attach_space,                     controller->attach_address,                     controller->attach_size,		     me);  set_hw_delete (me, m68hc11_delete);  /* Get cpu frequency.  */  sd = hw_system (me);  cpu = STATE_CPU (sd, 0);  if (hw_find_property (me, "clock") != NULL)    {      cpu->cpu_frequency = hw_find_integer_property (me, "clock");    }  else    {      cpu->cpu_frequency = 8*1000*1000;    }  if (hw_find_property (me, "use_bank") != NULL)    hw_attach_address (hw_parent (me), 0,                       exec_map,                       cpu->bank_start,                       cpu->bank_end - cpu->bank_start,                       me);  cpu_mode = "expanded";  if (hw_find_property (me, "mode") != NULL)    cpu_mode = hw_find_string_property (me, "mode");  if (strcmp (cpu_mode, "test") == 0)    cpu->cpu_mode = M6811_MDA | M6811_SMOD;  else if (strcmp (cpu_mode, "bootstrap") == 0)    cpu->cpu_mode = M6811_SMOD;  else if (strcmp (cpu_mode, "single") == 0)    cpu->cpu_mode = 0;  else    cpu->cpu_mode = M6811_MDA;  controller->last_oscillator = 0;  /* Create oscillators for input port A.  */  make_oscillator (controller, "A7", M6811_PORTA, 0x80);  make_oscillator (controller, "A2", M6811_PORTA, 0x04);  make_oscillator (controller, "A1", M6811_PORTA, 0x02);  make_oscillator (controller, "A0", M6811_PORTA, 0x01);  /* port B is output only.  */  /* Create oscillators for input port C.  */  make_oscillator (controller, "C0", M6811_PORTC, 0x01);  make_oscillator (controller, "C1", M6811_PORTC, 0x02);  make_oscillator (controller, "C2", M6811_PORTC, 0x04);  make_oscillator (controller, "C3", M6811_PORTC, 0x08);  make_oscillator (controller, "C4", M6811_PORTC, 0x10);  make_oscillator (controller, "C5", M6811_PORTC, 0x20);  make_oscillator (controller, "C6", M6811_PORTC, 0x40);  make_oscillator (controller, "C7", M6811_PORTC, 0x80);  /* Create oscillators for input port D.  */  make_oscillator (controller, "D0", M6811_PORTD, 0x01);  make_oscillator (controller, "D1", M6811_PORTD, 0x02);  make_oscillator (controller, "D2", M6811_PORTD, 0x04);  make_oscillator (controller, "D3", M6811_PORTD, 0x08);  make_oscillator (controller, "D4", M6811_PORTD, 0x10);  make_oscillator (controller, "D5", M6811_PORTD, 0x20);  /* Add oscillator commands.  */  sim_add_option_table (sd, 0, m68hc11_options);}static voidm68hc11cpu_finish (struct hw *me){  struct m68hc11cpu *controller;  controller = HW_ZALLOC (me, struct m68hc11cpu);  set_hw_data (me, controller);  set_hw_io_read_buffer (me, m68hc11cpu_io_read_buffer);  set_hw_io_write_buffer (me, m68hc11cpu_io_write_buffer);  set_hw_ports (me, m68hc11cpu_ports);  set_hw_port_event (me, m68hc11cpu_port_event);  set_hw_attach_address (me, dv_m6811_attach_address_callback);  set_hw_detach_address (me, dv_m6811_detach_address_callback);#ifdef set_hw_ioctl  set_hw_ioctl (me, m68hc11_ioctl);#else  me->to_ioctl = m68hc11_ioctl;#endif  /* Initialize the pending interrupt flags.  */  controller->pending_level = 0;  controller->pending_reset = 0;  controller->pending_nmi = 0;  controller->event = NULL;  attach_m68hc11_regs (me, controller);}/* An event arrives on an interrupt port.  */static voiddeliver_m68hc11cpu_interrupt (struct hw *me, void *data){}static voidmake_oscillator (struct m68hc11cpu *controller, const char *name,                 uint16 addr, uint8 mask){  struct input_osc *osc;  if (controller->last_oscillator >= NR_OSC)    hw_abort (0, "Too many oscillators");  osc = &controller->oscillators[controller->last_oscillator];  osc->name = name;  osc->addr = addr;  osc->mask = mask;  controller->last_oscillator++;}/* Find the oscillator given the input port name.  */static struct input_osc *find_oscillator (struct m68hc11cpu *controller, const char *name){  int i;  for (i = 0; i < controller->last_oscillator; i++)    if (strcasecmp (controller->oscillators[i].name, name) == 0)      return &controller->oscillators[i];  return 0;}static voidoscillator_handler (struct hw *me, void *data){  struct input_osc *osc = (struct input_osc*) data;  SIM_DESC sd;  sim_cpu *cpu;  signed64 dt;  uint8 val;  sd = hw_system (me);  cpu = STATE_CPU (sd, 0);  /* Change the input bit.  */  osc->value ^= osc->mask;  val = cpu->ios[osc->addr] & ~osc->mask;  val |= osc->value;  m68hc11cpu_set_port (me, cpu, osc->addr, val);  /* Setup event to toggle the bit.  */  if (osc->value)    dt = osc->on_time;  else    dt = osc->off_time;  if (dt && --osc->repeat >= 0)    {      sim_events *events = STATE_EVENTS (sd);      dt += events->nr_ticks_to_process;      osc->event = hw_event_queue_schedule (me, dt, oscillator_handler, osc);    }  else    osc->event = 0;}static voidreset_oscillators (struct hw *me){  struct m68hc11cpu *controller = hw_data (me);  int i;  for (i = 0; i < controller->last_oscillator; i++)    {      if (controller->oscillators[i].event)        {          hw_event_queue_deschedule (me, controller->oscillators[i].event);          controller->oscillators[i].event = 0;        }    }}      static voidm68hc11cpu_port_event (struct hw *me,                       int my_port,                       struct hw *source,                       int source_port,                       int level){  struct m68hc11cpu *controller = hw_data (me);  SIM_DESC sd;  sim_cpu* cpu;    sd  = hw_system (me);  cpu = STATE_CPU (sd, 0);  switch (my_port)    {    case RESET_PORT:      HW_TRACE ((me, "port-in reset"));      /* The reset is made in 3 steps:         - First, cleanup the current sim_cpu struct.         - Reset the devices.         - Restart the cpu for the reset (get the CPU mode from the           CONFIG register that gets initialized by EEPROM device).  */      cpu_reset (cpu);      reset_oscillators (me);      hw_port_event (me, CPU_RESET_PORT, 1);      cpu_restart (cpu);      break;          case NMI_PORT:      controller->pending_nmi = 1;      HW_TRACE ((me, "port-in nmi"));      break;          case IRQ_PORT:      /* level == 0 means that the interrupt was cleared.  */      if(level == 0)	controller->pending_level = -1; /* signal end of interrupt */      else	controller->pending_level = level;      HW_TRACE ((me, "port-in level=%d", level));      break;    case SET_PORT_A:      m68hc11cpu_set_port (me, cpu, M6811_PORTA, level);      break;          case SET_PORT_C:      m68hc11cpu_set_port (me, cpu, M6811_PORTC, level);      break;    case SET_PORT_D:      m68hc11cpu_set_port (me, cpu, M6811_PORTD, level);      break;    case CPU_WRITE_PORT:      break;    default:      hw_abort (me, "bad switch");      break;    }  /* Schedule an event to be delivered immediately after current     instruction.  */  if(controller->event != NULL)    hw_event_queue_deschedule(me, controller->event);  controller->event =    hw_event_queue_schedule (me, 0, deliver_m68hc11cpu_interrupt, NULL);}io_reg_desc config_desc[] = {  { M6811_NOSEC, "NOSEC ", "Security Mode Disable" },  { M6811_NOCOP, "NOCOP ", "COP System Disable" },  { M6811_ROMON, "ROMON ", "Enable On-chip Rom" },

⌨️ 快捷键说明

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