diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/mn10300/dv-mn103cpu.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'sim/mn10300/dv-mn103cpu.c')
-rw-r--r-- | sim/mn10300/dv-mn103cpu.c | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/sim/mn10300/dv-mn103cpu.c b/sim/mn10300/dv-mn103cpu.c deleted file mode 100644 index cce89f4..0000000 --- a/sim/mn10300/dv-mn103cpu.c +++ /dev/null @@ -1,431 +0,0 @@ -/* This file is part of the program GDB, the GU debugger. - - Copyright (C) 1998 Free Software Foundation, Inc. - 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 "hw-base.h" - -/* DEVICE - - - mn103cpu - mn10300 cpu virtual device - - - DESCRIPTION - - - Implements the external mn10300 functionality. This includes the - delivery of of interrupts generated from other devices and the - handling of device specific registers. - - - PROPERTIES - - - reg = <address> <size> - - Specify the address of the mn10300's control register block. This - block contains the Interrupt Vector Registers. - - The reg property value `0x20000000 0x42' locates the register block - at the address specified in the mn10300 user guide. - - - PORTS - - - reset (input) - - Currently ignored. - - - nmi (input) - - Deliver a non-maskable interrupt to the processor. - - - level (input) - - Maskable interrupt level port port. The interrupt controller - notifies the processor of any change in the level of pending - requested interrupts via this port. - - - ack (output) - - Output signal indicating that the processor is delivering a level - interrupt. The value passed with the event specfies the level of - the interrupt being delivered. - - - BUGS - - - When delivering an interrupt, this code assumes that there is only - one processor (number 0). - - This code does not attempt to be efficient at handling pending - interrupts. It simply schedules the interrupt delivery handler - every instruction cycle until all pending interrupts go away. An - alternative implementation might modify instructions that change - the PSW and have them check to see if the change makes an interrupt - delivery possible. - - */ - - -/* The interrupt vectors */ - -enum { NR_VECTORS = 7, }; - - -/* The interrupt controller register address blocks */ - -struct mn103cpu_block { - unsigned_word base; - unsigned_word bound; -}; - - -struct mn103cpu { - struct mn103cpu_block block; - struct hw_event *pending_handler; - int pending_level; - int pending_nmi; - int pending_reset; - /* the visible registers */ - unsigned16 interrupt_vector[NR_VECTORS]; - unsigned16 internal_memory_control; - unsigned16 cpu_mode; -}; - - - -/* input port ID's */ - -enum { - RESET_PORT, - NMI_PORT, - LEVEL_PORT, -}; - - -/* input port ID's */ - -enum { - ACK_PORT, -}; - -static const struct hw_port_descriptor mn103cpu_ports[] = { - - /* interrupt inputs */ - { "reset", RESET_PORT, 0, input_port, }, - { "nmi", NMI_PORT, 0, input_port, }, - { "level", LEVEL_PORT, 0, input_port, }, - - /* interrupt ack (latch) output from cpu */ - { "ack", ACK_PORT, 0, output_port, }, - - { NULL, }, -}; - - -/* Finish off the partially created hw device. Attach our local - callbacks. Wire up our port names etc */ - -static hw_io_read_buffer_callback mn103cpu_io_read_buffer; -static hw_io_write_buffer_callback mn103cpu_io_write_buffer; -static hw_port_event_callback mn103cpu_port_event; - -static void -attach_mn103cpu_regs (struct hw *me, - struct mn103cpu *controller) -{ - unsigned_word attach_address; - int attach_space; - unsigned attach_size; - reg_property_spec reg; - if (hw_find_property (me, "reg") == NULL) - hw_abort (me, "Missing \"reg\" property"); - if (!hw_find_reg_array_property (me, "reg", 0, ®)) - hw_abort (me, "\"reg\" property must contain three addr/size entries"); - hw_unit_address_to_attach_address (hw_parent (me), - ®.address, - &attach_space, - &attach_address, - me); - controller->block.base = attach_address; - hw_unit_size_to_attach_size (hw_parent (me), - ®.size, - &attach_size, me); - controller->block.bound = attach_address + (attach_size - 1); - if ((controller->block.base & 3) != 0) - hw_abort (me, "cpu register block must be 4 byte aligned"); - hw_attach_address (hw_parent (me), - 0, - attach_space, attach_address, attach_size, - me); -} - - -static void -mn103cpu_finish (struct hw *me) -{ - struct mn103cpu *controller; - - controller = HW_ZALLOC (me, struct mn103cpu); - set_hw_data (me, controller); - set_hw_io_read_buffer (me, mn103cpu_io_read_buffer); - set_hw_io_write_buffer (me, mn103cpu_io_write_buffer); - set_hw_ports (me, mn103cpu_ports); - set_hw_port_event (me, mn103cpu_port_event); - - /* Attach ourself to our parent bus */ - attach_mn103cpu_regs (me, controller); - - /* Initialize the read-only registers */ - controller->pending_level = 7; /* FIXME */ - /* ... */ -} - - - -/* An event arrives on an interrupt port */ - -static void -deliver_mn103cpu_interrupt (struct hw *me, - void *data) -{ - struct mn103cpu *controller = hw_data (me); - SIM_DESC simulator = hw_system (me); - sim_cpu *cpu = STATE_CPU (simulator, 0); - - if (controller->pending_reset) - { - controller->pending_reset = 0; - /* need to clear all registers et.al! */ - HW_TRACE ((me, "Reset!")); - hw_abort (me, "Reset!"); - } - else if (controller->pending_nmi) - { - controller->pending_nmi = 0; - store_word (SP - 4, CIA_GET (cpu)); - store_half (SP - 8, PSW); - PSW &= ~PSW_IE; - SP = SP - 8; - CIA_SET (cpu, 0x40000008); - HW_TRACE ((me, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx", - (long) CIA_GET (cpu), (unsigned) PSW, (long) SP)); - } - else if ((controller->pending_level < EXTRACT_PSW_LM) - && (PSW & PSW_IE)) - { - /* Don't clear pending level. Request continues to be pending - until the interrupt controller clears/changes it */ - store_word (SP - 4, CIA_GET (cpu)); - store_half (SP - 8, PSW); - PSW &= ~PSW_IE; - PSW &= ~PSW_LM; - PSW |= INSERT_PSW_LM (controller->pending_level); - SP = SP - 8; - CIA_SET (cpu, 0x40000000 + controller->interrupt_vector[controller->pending_level]); - HW_TRACE ((me, "port-out ack %d", controller->pending_level)); - hw_port_event (me, ACK_PORT, controller->pending_level); - HW_TRACE ((me, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx", - controller->pending_level, - (long) CIA_GET (cpu), (unsigned) PSW, (long) SP)); - } - - if (controller->pending_level < 7) /* FIXME */ - { - /* As long as there is the potential need to deliver an - interrupt we keep rescheduling this routine. */ - if (controller->pending_handler != NULL) - controller->pending_handler = - hw_event_queue_schedule (me, 1, deliver_mn103cpu_interrupt, NULL); - } - else - { - /* Don't bother re-scheduling the interrupt handler as there is - nothing to deliver */ - controller->pending_handler = NULL; - } - -} - - -static void -mn103cpu_port_event (struct hw *me, - int my_port, - struct hw *source, - int source_port, - int level) -{ - struct mn103cpu *controller = hw_data (me); - - /* Schedule our event handler *now* */ - if (controller->pending_handler == NULL) - controller->pending_handler = - hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL); - - switch (my_port) - { - - case RESET_PORT: - controller->pending_reset = 1; - HW_TRACE ((me, "port-in reset")); - break; - - case NMI_PORT: - controller->pending_nmi = 1; - HW_TRACE ((me, "port-in nmi")); - break; - - case LEVEL_PORT: - controller->pending_level = level; - HW_TRACE ((me, "port-in level=%d", level)); - break; - - default: - hw_abort (me, "bad switch"); - break; - - } -} - - -/* Read/write to a CPU register */ - -enum mn103cpu_regs { - INVALID_REG, - IVR0_REG, - IVR1_REG, - IVR2_REG, - IVR3_REG, - IVR4_REG, - IVR5_REG, - IVR6_REG, - IMCR_REG, - CPUM_REG, -}; - -static enum mn103cpu_regs -decode_mn103cpu_addr (struct hw *me, - struct mn103cpu *controller, - unsigned_word base) -{ - switch (base - controller->block.base) - { - case 0x000: return IVR0_REG; - case 0x004: return IVR1_REG; - case 0x008: return IVR2_REG; - case 0x00c: return IVR3_REG; - case 0x010: return IVR4_REG; - case 0x014: return IVR5_REG; - case 0x018: return IVR6_REG; - case 0x020: return IMCR_REG; - case 0x040: return CPUM_REG; - default: return INVALID_REG; - } -} - -static unsigned -mn103cpu_io_read_buffer (struct hw *me, - void *dest, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - struct mn103cpu *controller = hw_data (me); - unsigned16 val = 0; - enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base); - - switch (reg) - { - case IVR0_REG: - case IVR1_REG: - case IVR2_REG: - case IVR3_REG: - case IVR4_REG: - case IVR5_REG: - case IVR6_REG: - val = controller->interrupt_vector[reg - IVR0_REG]; - break; - case IMCR_REG: - val = controller->internal_memory_control; - break; - case CPUM_REG: - val = controller->cpu_mode; - break; - default: - /* just ignore the read */ - break; - } - - if (nr_bytes == 2) - *(unsigned16*) dest = H2LE_2 (val); - - return nr_bytes; -} - -static unsigned -mn103cpu_io_write_buffer (struct hw *me, - const void *source, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - struct mn103cpu *controller = hw_data (me); - unsigned16 val; - enum mn103cpu_regs reg; - - if (nr_bytes != 2) - hw_abort (me, "must be two byte write"); - - reg = decode_mn103cpu_addr (me, controller, base); - val = LE2H_2 (* (unsigned16 *) source); - - switch (reg) - { - case IVR0_REG: - case IVR1_REG: - case IVR2_REG: - case IVR3_REG: - case IVR4_REG: - case IVR5_REG: - case IVR6_REG: - controller->interrupt_vector[reg - IVR0_REG] = val; - HW_TRACE ((me, "ivr%d = 0x%04lx", reg - IVR0_REG, (long) val)); - break; - default: - /* just ignore the write */ - break; - } - - return nr_bytes; -} - - -const struct hw_device_descriptor dv_mn103cpu_descriptor[] = { - { "mn103cpu", mn103cpu_finish, }, - { NULL }, -}; |