X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=sim%2Fmips%2Fdv-tx3904cpu.c;h=56c23d8dad43f785c3bd36e28862fb2bdcccb37f;hb=3a31051b3a5ded399dd54c5598608cea372675e1;hp=a040d4c8163ce8c115f4e505135ebe83ce13791b;hpb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;p=binutils-gdb.git diff --git a/sim/mips/dv-tx3904cpu.c b/sim/mips/dv-tx3904cpu.c index a040d4c8163..56c23d8dad4 100644 --- a/sim/mips/dv-tx3904cpu.c +++ b/sim/mips/dv-tx3904cpu.c @@ -1,44 +1,45 @@ /* This file is part of the program GDB, the GNU debugger. - - Copyright (C) 1998 Free Software Foundation, Inc. + + Copyright (C) 1998-2022 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 + the Free Software Foundation; either version 3 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. - + along with this program. If not, see . + */ +/* This must come before any other includes. */ +#include "defs.h" #include "sim-main.h" #include "hw-main.h" /* DEVICE - + tx3904cpu - tx3904 cpu virtual device - + DESCRIPTION - + Implements the external tx3904 functionality. This includes the delivery of of interrupts generated from other devices and the handling of device specific registers. PROPERTIES - + none @@ -82,11 +83,12 @@ struct tx3904cpu { /* Pending interrupts for delivery by event handler */ int pending_reset, pending_nmi, pending_level; + struct hw_event* event; }; -/* input port ID's */ +/* input port ID's */ enum { RESET_PORT, @@ -127,6 +129,7 @@ tx3904cpu_finish (struct hw *me) controller->pending_level = 0; controller->pending_reset = 0; controller->pending_nmi = 0; + controller->event = NULL; } @@ -140,54 +143,57 @@ deliver_tx3904cpu_interrupt (struct hw *me, struct tx3904cpu *controller = hw_data (me); SIM_DESC sd = hw_system (me); sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */ - address_word cia = CIA_GET (cpu); + address_word cia = CPU_PC_GET (cpu); #define CPU cpu -#define SD current_state +#define SD sd if (controller->pending_reset) { controller->pending_reset = 0; - HW_TRACE ((me, "reset pc=0x%08lx", (long) CIA_GET (cpu))); + HW_TRACE ((me, "reset pc=0x%08lx", (long) CPU_PC_GET (cpu))); SignalExceptionNMIReset(); } else if (controller->pending_nmi) { controller->pending_nmi = 0; - HW_TRACE ((me, "nmi pc=0x%08lx", (long) CIA_GET (cpu))); + HW_TRACE ((me, "nmi pc=0x%08lx", (long) CPU_PC_GET (cpu))); SignalExceptionNMIReset(); } else if (controller->pending_level) { HW_TRACE ((me, "interrupt level=%d pc=0x%08lx sr=0x%08lx", controller->pending_level, - (long) CIA_GET (cpu), (long) SR)); + (long) CPU_PC_GET (cpu), (long) SR)); /* Clear CAUSE register. It may stay this way if the interrupt was cleared with a negative pending_level. */ CAUSE &= ~ (cause_IP_mask << cause_IP_shift); - if(controller->pending_level > 0) /* interrupt set */ + if (controller->pending_level > 0) /* interrupt set */ { /* set hardware-interrupt subfields of CAUSE register */ CAUSE |= (controller->pending_level & cause_IP_mask) << cause_IP_shift; /* check for enabled / unmasked interrupts */ - if((SR & status_IEc) && + if ((SR & status_IEc) && (controller->pending_level & ((SR >> status_IM_shift) & status_IM_mask))) { controller->pending_level = 0; - SignalExceptionInterrupt(); + SignalExceptionInterrupt(0 /* dummy value */); } else { /* reschedule soon */ - hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL); + if (controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = + hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL); } } /* interrupt set */ } -#undef CPU cpu -#undef SD current_state +#undef CPU +#undef SD } @@ -201,26 +207,26 @@ tx3904cpu_port_event (struct hw *me, struct tx3904cpu *controller = hw_data (me); 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: /* level == 0 means that the interrupt was cleared */ - if(level == 0) + 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; - + default: hw_abort (me, "bad switch"); break; @@ -228,7 +234,10 @@ tx3904cpu_port_event (struct hw *me, /* Schedule an event to be delivered immediately after current instruction. */ - hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL); + if (controller->event != NULL) + hw_event_queue_deschedule(me, controller->event); + controller->event = + hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL); }