mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-11 02:38:51 +08:00
o Implement generic halt/restart/abort module.
Use in tic80 and d30v simulators. o Add signal hook to sim-core module
This commit is contained in:
@ -61,6 +61,8 @@ sim-events.c
|
|||||||
sim-events.h
|
sim-events.h
|
||||||
sim-fpu.c
|
sim-fpu.c
|
||||||
sim-fpu.h
|
sim-fpu.h
|
||||||
|
sim-halt.c
|
||||||
|
sim-halt.h
|
||||||
sim-inline.c
|
sim-inline.c
|
||||||
sim-inline.h
|
sim-inline.h
|
||||||
sim-io.c
|
sim-io.c
|
||||||
|
@ -1,3 +1,68 @@
|
|||||||
|
Mon May 19 12:07:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* sim-basics.h (transfer_type): New type.
|
||||||
|
|
||||||
|
* sim-core.c (sim_core_signal): New function. Print core signal
|
||||||
|
information.
|
||||||
|
(sim_core_find_mapping): Add transfer argument.
|
||||||
|
|
||||||
|
* sim-n-core.h (sim_core_{write,write}_unaligned_N): Call
|
||||||
|
SIM_CORE_SIGNAL if a recoverable abort.
|
||||||
|
* sim-core.c (sim_core_find_mapping): Ditto.
|
||||||
|
|
||||||
|
Fri May 16 15:13:21 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* sim-core.c (sim_core_find_mapping): Replace calls to
|
||||||
|
sim_io_error to more resiliant sim_engine_abort.
|
||||||
|
|
||||||
|
* sim-n-core.h (sim_core_read_unaligned_N): Ditto.
|
||||||
|
(sim_core_write_unaligned_N): Ditto.
|
||||||
|
|
||||||
|
Tue May 13 13:50:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* sim-module.c: Add sim_events_install to list.
|
||||||
|
|
||||||
|
* sim-events.c (sim_events_install, sim_events_uninstall): Clonse
|
||||||
|
from sim_core_*.
|
||||||
|
(sim_events_init): Now returns SIG_RC.
|
||||||
|
|
||||||
|
* sim-run.c: New file. Generic sim_engine_run.
|
||||||
|
* sim-reason.c: New file. Generic sim_stop_reason.
|
||||||
|
* sim-stop.c: New file. Generic sim_stop.
|
||||||
|
* sim-resume.c: New file. Generic sim_resume.
|
||||||
|
|
||||||
|
* Make-common.in (sim-engine.o): Add rule.
|
||||||
|
(sim-run.o, sim-reason.o, sim-stop.o, sim-resume.o): Ditto.
|
||||||
|
|
||||||
|
* sim-engine.h, sim-engine.c: New file. Provide generic
|
||||||
|
implementation of sim_engine_halt, sim_engine_error. et.al.
|
||||||
|
|
||||||
|
* sim-base.h (sim_state_base): Add member halt.
|
||||||
|
(sim-engine.h): Include.
|
||||||
|
|
||||||
|
* sim-events.h (sim_event_handler): Always pass SIM_DESC to event
|
||||||
|
handlers.
|
||||||
|
* sim-events.c (sim_events_poll): Update event handler.
|
||||||
|
|
||||||
|
Tue May 13 09:57:49 1997 Andrew Cagney <cagney@b2.cygnus.com>
|
||||||
|
|
||||||
|
* sim-events.h, sim-events.c (sim_events_watch_clock): New
|
||||||
|
function.
|
||||||
|
(sim_events_watch_sim): New function.
|
||||||
|
(sim_events_watch_core): New function.
|
||||||
|
(sim_watch_valid): New function.
|
||||||
|
(sim_events_preprocess): New function.
|
||||||
|
(sim_events_process): Process the watchpoints as well as the timer
|
||||||
|
queue.
|
||||||
|
(sim_events_tick): Check WORK_PENDING instead of the hold queue.
|
||||||
|
(sim_events_deschedule): Check all the queues when removing an
|
||||||
|
event.
|
||||||
|
(sim_events_init): Ditto for cleaning.
|
||||||
|
|
||||||
|
Mon May 19 12:07:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* sim-fpu.c (is_ufpu_number): Comment out - currently unused.
|
||||||
|
|
||||||
Mon May 19 11:23:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Mon May 19 11:23:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* callback.c (os_open): Type of arg flags is int.
|
* callback.c (os_open): Type of arg flags is int.
|
||||||
|
@ -180,6 +180,7 @@ sim_main_headers = \
|
|||||||
$(srcdir)/../common/sim-module.h \
|
$(srcdir)/../common/sim-module.h \
|
||||||
$(srcdir)/../common/sim-trace.h \
|
$(srcdir)/../common/sim-trace.h \
|
||||||
$(srcdir)/../common/sim-profile.h \
|
$(srcdir)/../common/sim-profile.h \
|
||||||
|
$(srcdir)/../common/sim-engine.h \
|
||||||
tconfig.h
|
tconfig.h
|
||||||
|
|
||||||
sim-assert_h = $(srcdir)/../common/sim-assert.h
|
sim-assert_h = $(srcdir)/../common/sim-assert.h
|
||||||
@ -190,6 +191,7 @@ sim-config_h = $(srcdir)/../common/sim-config.h
|
|||||||
sim-n-bits_h = $(srcdir)/../common/sim-n-bits.h
|
sim-n-bits_h = $(srcdir)/../common/sim-n-bits.h
|
||||||
sim-core_h = $(srcdir)/../common/sim-core.h
|
sim-core_h = $(srcdir)/../common/sim-core.h
|
||||||
sim-n-core_h = $(srcdir)/../common/sim-n-core.h
|
sim-n-core_h = $(srcdir)/../common/sim-n-core.h
|
||||||
|
sim-engine_h = $(srcdir)/../common/sim-engine.h
|
||||||
sim-events_h = $(srcdir)/../common/sim-events.h
|
sim-events_h = $(srcdir)/../common/sim-events.h
|
||||||
sim-fpu_h = $(srcdir)/../common/sim-fpu.h
|
sim-fpu_h = $(srcdir)/../common/sim-fpu.h
|
||||||
sim-io_h = $(srcdir)/../common/sim-io.h
|
sim-io_h = $(srcdir)/../common/sim-io.h
|
||||||
@ -207,6 +209,14 @@ BUILT_SRC_FROM_COMMON= \
|
|||||||
sim-config.c \
|
sim-config.c \
|
||||||
sim-io.c
|
sim-io.c
|
||||||
|
|
||||||
|
sim-abort.o: sim-abort.c \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-abort.c: $(srcdir)/../common/sim-abort.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
sim-bits.o: sim-bits.c $(sim-bits_h) $(sim-n-bits_h) $(sim-assert_h) \
|
sim-bits.o: sim-bits.c $(sim-bits_h) $(sim-n-bits_h) $(sim-assert_h) \
|
||||||
$(SIM_EXTRA_DEPS)
|
$(SIM_EXTRA_DEPS)
|
||||||
sim-bits.c: $(srcdir)/../common/sim-bits.c
|
sim-bits.c: $(srcdir)/../common/sim-bits.c
|
||||||
@ -239,6 +249,14 @@ sim-endian.c: $(srcdir)/../common/sim-endian.c
|
|||||||
cat $(srcdir)/../common/$@ >> tmp-$@
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
$(srcdir)/../../move-if-change tmp-$@ $@
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
|
sim-engine.o: sim-engine.c $(sim_main_headers) $(sim-engine_h) $(sim-assert_h) \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-engine.c: $(srcdir)/../common/sim-engine.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
sim-events.o: sim-events.c $(sim-events_h) $(sim-assert_h) \
|
sim-events.o: sim-events.c $(sim-events_h) $(sim-assert_h) \
|
||||||
$(SIM_EXTRA_DEPS)
|
$(SIM_EXTRA_DEPS)
|
||||||
sim-events.c: $(srcdir)/../common/sim-events.c
|
sim-events.c: $(srcdir)/../common/sim-events.c
|
||||||
@ -277,6 +295,38 @@ sim-options.o: $(srcdir)/../common/sim-options.c $(sim_main_headers) \
|
|||||||
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||||
$(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS)
|
$(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS)
|
||||||
|
|
||||||
|
sim-reason.o: sim-reason.c $(sim_main_headers) $(sim-assert_h) \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-reason.c: $(srcdir)/../common/sim-reason.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
|
sim-resume.o: sim-resume.c $(sim_main_headers) $(sim-assert_h) \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-resume.c: $(srcdir)/../common/sim-resume.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
|
sim-run.o: sim-run.c $(sim_main_headers) $(sim-assert_h) \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-run.c: $(srcdir)/../common/sim-run.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
|
sim-stop.o: sim-stop.c $(sim_main_headers) $(sim-assert_h) \
|
||||||
|
$(SIM_EXTRA_DEPS)
|
||||||
|
sim-stop.c: $(srcdir)/../common/sim-stop.c
|
||||||
|
rm -f $@ tmp-$@
|
||||||
|
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
|
||||||
|
cat $(srcdir)/../common/$@ >> tmp-$@
|
||||||
|
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||||
|
|
||||||
sim-trace.o: $(srcdir)/../common/sim-trace.c $(sim_main_headers) \
|
sim-trace.o: $(srcdir)/../common/sim-trace.c $(sim_main_headers) \
|
||||||
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||||
$(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS)
|
$(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS)
|
||||||
|
60
sim/common/sim-abort.c
Normal file
60
sim/common/sim-abort.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* Generic simulator abort.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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 <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* This is an implementation of sim_engine_abort that does not use
|
||||||
|
longjmp, instead it just calls sim_io_error. sim_io_error will
|
||||||
|
jump right out of the simulator.
|
||||||
|
|
||||||
|
It is intended as a holder for simulators that have started to use
|
||||||
|
sim-core et.al. but are not yet in a position to use sim-engine
|
||||||
|
(the setjmp/longjmp code). */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_engine_abort (SIM_DESC sd,
|
||||||
|
sim_cpu *cpu,
|
||||||
|
sim_cia cia,
|
||||||
|
const char *fmt,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
if (sd != NULL)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
sim_io_evprintf (sd, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
sim_io_error (sd, "\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf (stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
134
sim/common/sim-engine.c
Normal file
134
sim/common/sim-engine.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/* Generic simulator halt/restart.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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 <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic halt */
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_engine_halt (SIM_DESC sd,
|
||||||
|
sim_cpu *last_cpu,
|
||||||
|
sim_cpu *next_cpu, /* NULL - use default */
|
||||||
|
sim_cia cia,
|
||||||
|
enum sim_stop reason,
|
||||||
|
int sigrc)
|
||||||
|
{
|
||||||
|
sim_engine *engine = STATE_ENGINE (sd);
|
||||||
|
if (engine->jmpbuf != NULL)
|
||||||
|
{
|
||||||
|
jmp_buf *halt_buf = engine->jmpbuf;
|
||||||
|
engine->last_cpu = last_cpu;
|
||||||
|
engine->next_cpu = next_cpu;
|
||||||
|
engine->reason = reason;
|
||||||
|
engine->sigrc = sigrc;
|
||||||
|
SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia);
|
||||||
|
longjmp(*halt_buf, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sim_io_error (sd, "sim_halt - bad long jump");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic restart */
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_engine_restart (SIM_DESC sd,
|
||||||
|
sim_cpu *last_cpu,
|
||||||
|
sim_cpu *next_cpu,
|
||||||
|
sim_cia cia)
|
||||||
|
{
|
||||||
|
sim_engine *engine = STATE_ENGINE (sd);
|
||||||
|
if (engine->jmpbuf != NULL)
|
||||||
|
{
|
||||||
|
jmp_buf *halt_buf = engine->jmpbuf;
|
||||||
|
engine->last_cpu = last_cpu;
|
||||||
|
engine->next_cpu = next_cpu;
|
||||||
|
SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia);
|
||||||
|
longjmp(*halt_buf, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sim_io_error (sd, "sim_restart - bad long jump");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic error code */
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_engine_abort (SIM_DESC sd,
|
||||||
|
sim_cpu *cpu,
|
||||||
|
sim_cia cia,
|
||||||
|
const char *fmt,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
if (sd == NULL)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf (stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf (stderr, "\nQuit\n");
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
else if (STATE_ENGINE (sd)->jmpbuf == NULL)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
sim_io_evprintf (sd, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
sim_io_eprintf (sd, "\n");
|
||||||
|
sim_io_error (sd, "Quit Simulator");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
sim_io_evprintf (sd, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
sim_io_eprintf (sd, "\n");
|
||||||
|
sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIGABRT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic next/last cpu */
|
||||||
|
|
||||||
|
int
|
||||||
|
sim_engine_last_cpu_nr (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
sim_engine *engine = STATE_ENGINE (sd);
|
||||||
|
if (engine->last_cpu != NULL)
|
||||||
|
return engine->last_cpu - STATE_CPU (sd, 0);
|
||||||
|
else
|
||||||
|
return MAX_NR_PROCESSORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sim_engine_next_cpu_nr (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
sim_engine *engine = STATE_ENGINE (sd);
|
||||||
|
if (engine->next_cpu != NULL)
|
||||||
|
return engine->next_cpu - STATE_CPU (sd, 0);
|
||||||
|
else
|
||||||
|
return sim_engine_last_cpu_nr (sd) + 1;
|
||||||
|
}
|
122
sim/common/sim-engine.h
Normal file
122
sim/common/sim-engine.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/* Generic simulator halt/resume.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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. */
|
||||||
|
|
||||||
|
#ifndef SIM_ENGINE_H
|
||||||
|
#define SIM_ENGINE_H
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _sim_engine sim_engine;
|
||||||
|
struct _sim_engine
|
||||||
|
{
|
||||||
|
void *jmpbuf;
|
||||||
|
sim_cpu *last_cpu;
|
||||||
|
sim_cpu *next_cpu;
|
||||||
|
enum sim_stop reason;
|
||||||
|
sim_event *stepper;
|
||||||
|
int sigrc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Halt the simulator *now* */
|
||||||
|
|
||||||
|
extern void sim_engine_halt
|
||||||
|
(SIM_DESC sd,
|
||||||
|
sim_cpu *last_cpu,
|
||||||
|
sim_cpu *next_cpu, /* NULL -> succ (last_cpu) or event-mgr */
|
||||||
|
sim_cia cia,
|
||||||
|
enum sim_stop reason,
|
||||||
|
int sigrc);
|
||||||
|
|
||||||
|
/* Halt hook - allow target specific operation when halting a
|
||||||
|
simulator */
|
||||||
|
|
||||||
|
#if !defined (SIM_ENGINE_HALT_HOOK)
|
||||||
|
#define SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) if ((LAST_CPU) != NULL) (LAST_CPU)->cia = cia
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* restart the simulator *now* */
|
||||||
|
|
||||||
|
extern void sim_engine_restart
|
||||||
|
(SIM_DESC sd,
|
||||||
|
sim_cpu *last_cpu,
|
||||||
|
sim_cpu *next_cpu,
|
||||||
|
sim_cia cia);
|
||||||
|
|
||||||
|
/* Restart hook - allow target specific operation when restarting a
|
||||||
|
simulator */
|
||||||
|
|
||||||
|
#if !defined (SIM_ENGINE_RESTART_HOOK)
|
||||||
|
#define SIM_ENGINE_RESTART_HOOK(SD, LAST_CPU, CIA) SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Abort the simulator *now*.
|
||||||
|
|
||||||
|
This function is NULL safe. It can be called when either of SD or
|
||||||
|
CIA are NULL.
|
||||||
|
|
||||||
|
This function is setjmp/longjmp safe. It can be called when of
|
||||||
|
the sim_engine setjmp/longjmp buffer has not been established.
|
||||||
|
|
||||||
|
Simulators that are using components such as sim-core but are not
|
||||||
|
yet using this sim-engine module should link in file sim-abort.o
|
||||||
|
which implements a non setjmp/longjmp version of
|
||||||
|
sim_engine_abort. */
|
||||||
|
|
||||||
|
extern void sim_engine_abort
|
||||||
|
(SIM_DESC sd,
|
||||||
|
sim_cpu *cpu,
|
||||||
|
sim_cia cia,
|
||||||
|
const char *fmt,
|
||||||
|
...);
|
||||||
|
|
||||||
|
/* No abort hook - when possible this function exits using the
|
||||||
|
engine_halt function (and SIM_ENGINE_HALT_HOOK). */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Called by the generic sim_resume to run the simulation within the
|
||||||
|
above safty net.
|
||||||
|
|
||||||
|
An example implementation of sim_engine_run can be found in the
|
||||||
|
file sim-run.c */
|
||||||
|
|
||||||
|
extern void sim_engine_run
|
||||||
|
(SIM_DESC sd,
|
||||||
|
int next_cpu_nr,
|
||||||
|
int siggnal); /* most simulators ignore siggnal */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine the state of next/last cpu when the simulator was last
|
||||||
|
halted - a value >= nr-cpus indicates that the event-queue was
|
||||||
|
next/last. */
|
||||||
|
|
||||||
|
extern int sim_engine_next_cpu_nr (SIM_DESC sd);
|
||||||
|
extern int sim_engine_last_cpu_nr (SIM_DESC sd);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -27,6 +27,71 @@
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
watch_invalid,
|
||||||
|
|
||||||
|
/* core - target byte order */
|
||||||
|
watch_core_targ_1,
|
||||||
|
watch_core_targ_2,
|
||||||
|
watch_core_targ_4,
|
||||||
|
watch_core_targ_8,
|
||||||
|
/* core - big-endian */
|
||||||
|
watch_core_be_1,
|
||||||
|
watch_core_be_2,
|
||||||
|
watch_core_be_4,
|
||||||
|
watch_core_be_8,
|
||||||
|
/* core - little-endian */
|
||||||
|
watch_core_le_1,
|
||||||
|
watch_core_le_2,
|
||||||
|
watch_core_le_4,
|
||||||
|
watch_core_le_8,
|
||||||
|
|
||||||
|
/* sim - host byte order */
|
||||||
|
watch_sim_host_1,
|
||||||
|
watch_sim_host_2,
|
||||||
|
watch_sim_host_4,
|
||||||
|
watch_sim_host_8,
|
||||||
|
/* sim - big-endian */
|
||||||
|
watch_sim_be_1,
|
||||||
|
watch_sim_be_2,
|
||||||
|
watch_sim_be_4,
|
||||||
|
watch_sim_be_8,
|
||||||
|
/* sim - little-endian */
|
||||||
|
watch_sim_le_1,
|
||||||
|
watch_sim_le_2,
|
||||||
|
watch_sim_le_4,
|
||||||
|
watch_sim_le_8,
|
||||||
|
|
||||||
|
/* wallclock */
|
||||||
|
watch_clock,
|
||||||
|
|
||||||
|
/* timer */
|
||||||
|
watch_timer,
|
||||||
|
} sim_watchpoints;
|
||||||
|
|
||||||
|
|
||||||
|
struct _sim_event {
|
||||||
|
sim_watchpoints watching;
|
||||||
|
void *data;
|
||||||
|
sim_event_handler *handler;
|
||||||
|
/* timer event */
|
||||||
|
signed64 time_of_event;
|
||||||
|
/* watch wallclock event */
|
||||||
|
unsigned wallclock;
|
||||||
|
/* watch core address */
|
||||||
|
address_word core_addr;
|
||||||
|
sim_core_maps core_map;
|
||||||
|
/* watch sim addr */
|
||||||
|
void *host_addr;
|
||||||
|
/* watch core/sim range */
|
||||||
|
unsigned ub;
|
||||||
|
unsigned lb;
|
||||||
|
unsigned64 ub64;
|
||||||
|
unsigned64 lb64;
|
||||||
|
/* list */
|
||||||
|
sim_event *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The event queue maintains a single absolute time using two
|
/* The event queue maintains a single absolute time using two
|
||||||
variables.
|
variables.
|
||||||
@ -65,10 +130,10 @@ do \
|
|||||||
{ \
|
{ \
|
||||||
if (WITH_TRACE) \
|
if (WITH_TRACE) \
|
||||||
{ \
|
{ \
|
||||||
if (sd->events.trace) \
|
if (STATE_EVENTS (sd)->trace) \
|
||||||
{ \
|
{ \
|
||||||
const char *file; \
|
const char *file; \
|
||||||
SIM_FILTER_PATH(file, __FILE__); \
|
SIM_FILTER_PATH (file, __FILE__); \
|
||||||
sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
|
sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
|
||||||
sim_io_printf ARGS; \
|
sim_io_printf ARGS; \
|
||||||
} \
|
} \
|
||||||
@ -77,26 +142,72 @@ do \
|
|||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/* event queue iterator */
|
||||||
|
STATIC_INLINE_SIM_EVENTS\
|
||||||
|
(sim_event **)
|
||||||
|
next_event_queue (SIM_DESC sd,
|
||||||
|
sim_event **queue)
|
||||||
|
{
|
||||||
|
if (queue == NULL)
|
||||||
|
return &STATE_EVENTS (sd)->queue;
|
||||||
|
else if (queue == &STATE_EVENTS (sd)->queue)
|
||||||
|
return &STATE_EVENTS (sd)->watchpoints;
|
||||||
|
else if (queue == &STATE_EVENTS (sd)->watchpoints)
|
||||||
|
return &STATE_EVENTS (sd)->watchedpoints;
|
||||||
|
else if (queue == &STATE_EVENTS (sd)->watchedpoints)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
sim_io_error (sd, "next_event_queue - bad queue");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC_INLINE_SIM_EVENTS\
|
STATIC_INLINE_SIM_EVENTS\
|
||||||
(void)
|
(void)
|
||||||
sim_events_poll (void *data)
|
sim_events_poll (SIM_DESC sd,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
/* just re-schedule in 1000 million ticks time */
|
/* just re-schedule in 1000 million ticks time */
|
||||||
SIM_DESC sd = data;
|
sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
|
||||||
sim_events_schedule(sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
|
|
||||||
sim_io_poll_quit (sd);
|
sim_io_poll_quit (sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
/* "events" module install handler.
|
||||||
(void)
|
This is called via sim_module_install to install the "events" subsystem
|
||||||
sim_events_init(SIM_DESC sd)
|
into the simulator. */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(SIM_RC)
|
||||||
|
sim_events_install (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_module_add_uninstall_fn (sd, sim_events_uninstall);
|
||||||
sim_event *event;
|
sim_module_add_init_fn (sd, sim_events_init);
|
||||||
|
return SIM_RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Uninstall the "events" subsystem from the simulator. */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(void)
|
||||||
|
sim_events_uninstall (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
/* FIXME: free buffers, etc. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize the simulator event manager */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(SIM_RC)
|
||||||
|
sim_events_init (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
|
||||||
/* drain the interrupt queue */
|
/* drain the interrupt queue */
|
||||||
{
|
{
|
||||||
|
sim_event *event;
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
sigset_t new_mask;
|
sigset_t new_mask;
|
||||||
@ -111,86 +222,103 @@ sim_events_init(SIM_DESC sd)
|
|||||||
}
|
}
|
||||||
events->held = NULL;
|
events->held = NULL;
|
||||||
events->held_end = &events->held;
|
events->held_end = &events->held;
|
||||||
|
events->work_pending = 0;
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||||
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drain the normal queue */
|
/* drain the normal queues */
|
||||||
event = events->queue;
|
{
|
||||||
while (event != NULL) {
|
sim_event **queue = NULL;
|
||||||
sim_event *dead = event;
|
while ((queue = next_event_queue (sd, queue)) != NULL)
|
||||||
event = event->next;
|
{
|
||||||
zfree(dead);
|
if (queue == NULL) break;
|
||||||
|
while (*queue != NULL)
|
||||||
|
{
|
||||||
|
sim_event *dead = *queue;
|
||||||
|
*queue = dead->next;
|
||||||
|
zfree (dead);
|
||||||
|
}
|
||||||
|
*queue = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
events->queue = NULL;
|
|
||||||
|
|
||||||
/* wind time back to zero */
|
/* wind time back to zero */
|
||||||
events->processing = 0;
|
events->processing = 1; /* start by doing queue */
|
||||||
events->time_of_event = 0;
|
events->time_of_event = 0;
|
||||||
events->time_from_event = 0;
|
events->time_from_event = 0;
|
||||||
|
events->initial_wallclock = sim_elapsed_time_get ();
|
||||||
|
|
||||||
/* schedule our initial counter event */
|
/* schedule our initial counter event */
|
||||||
sim_events_schedule(sd, 0, sim_events_poll, sd);
|
sim_events_schedule (sd, 0, sim_events_poll, sd);
|
||||||
|
|
||||||
/* from now on, except when the large-int event is being processed
|
/* from now on, except when the large-int event is being processed
|
||||||
the event queue is non empty */
|
the event queue is non empty */
|
||||||
SIM_ASSERT(events->queue != NULL);
|
SIM_ASSERT (events->queue != NULL);
|
||||||
|
|
||||||
|
return SIM_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
INLINE_SIM_EVENTS\
|
||||||
(signed64)
|
(signed64)
|
||||||
sim_events_time(SIM_DESC sd)
|
sim_events_time (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
return events->time_of_event - events->time_from_event;
|
return events->time_of_event - events->time_from_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC_INLINE_SIM_EVENTS\
|
|
||||||
(void)
|
|
||||||
update_time_from_event(SIM_DESC sd)
|
|
||||||
{
|
|
||||||
sim_events *events = &sd->events;
|
|
||||||
signed64 current_time = sim_events_time(sd);
|
|
||||||
if (events->queue != NULL) {
|
|
||||||
events->time_from_event = (events->queue->time_of_event - current_time);
|
|
||||||
events->time_of_event = events->queue->time_of_event;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
events->time_of_event = current_time - 1;
|
|
||||||
events->time_from_event = -1;
|
|
||||||
}
|
|
||||||
SIM_ASSERT(current_time == sim_events_time (sd));
|
|
||||||
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC_INLINE_SIM_EVENTS\
|
STATIC_INLINE_SIM_EVENTS\
|
||||||
(void)
|
(void)
|
||||||
insert_sim_event(SIM_DESC sd,
|
update_time_from_event (SIM_DESC sd)
|
||||||
sim_event *new_event,
|
|
||||||
signed64 delta)
|
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
signed64 current_time = sim_events_time (sd);
|
||||||
|
if (events->queue != NULL)
|
||||||
|
{
|
||||||
|
events->time_from_event = (events->queue->time_of_event - current_time);
|
||||||
|
events->time_of_event = events->queue->time_of_event;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events->time_of_event = current_time - 1;
|
||||||
|
events->time_from_event = -1;
|
||||||
|
}
|
||||||
|
SIM_ASSERT (current_time == sim_events_time (sd));
|
||||||
|
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_INLINE_SIM_EVENTS\
|
||||||
|
(void)
|
||||||
|
insert_sim_event (SIM_DESC sd,
|
||||||
|
sim_event *new_event,
|
||||||
|
signed64 delta)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
sim_event *curr;
|
sim_event *curr;
|
||||||
sim_event **prev;
|
sim_event **prev;
|
||||||
signed64 time_of_event;
|
signed64 time_of_event;
|
||||||
|
|
||||||
if (delta < 0)
|
if (delta < 0)
|
||||||
engine_error (sd, "what is past is past!\n");
|
sim_io_error (sd, "what is past is past!\n");
|
||||||
|
|
||||||
/* compute when the event should occure */
|
/* compute when the event should occure */
|
||||||
time_of_event = sim_events_time(sd) + delta;
|
time_of_event = sim_events_time (sd) + delta;
|
||||||
|
|
||||||
/* find the queue insertion point - things are time ordered */
|
/* find the queue insertion point - things are time ordered */
|
||||||
prev = &events->queue;
|
prev = &events->queue;
|
||||||
curr = events->queue;
|
curr = events->queue;
|
||||||
while (curr != NULL && time_of_event >= curr->time_of_event) {
|
while (curr != NULL && time_of_event >= curr->time_of_event)
|
||||||
SIM_ASSERT(curr->next == NULL
|
{
|
||||||
|| curr->time_of_event <= curr->next->time_of_event);
|
SIM_ASSERT (curr->next == NULL
|
||||||
prev = &curr->next;
|
|| curr->time_of_event <= curr->next->time_of_event);
|
||||||
curr = curr->next;
|
prev = &curr->next;
|
||||||
}
|
curr = curr->next;
|
||||||
SIM_ASSERT(curr == NULL || time_of_event < curr->time_of_event);
|
}
|
||||||
|
SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
|
||||||
|
|
||||||
/* insert it */
|
/* insert it */
|
||||||
new_event->next = curr;
|
new_event->next = curr;
|
||||||
@ -198,19 +326,21 @@ insert_sim_event(SIM_DESC sd,
|
|||||||
new_event->time_of_event = time_of_event;
|
new_event->time_of_event = time_of_event;
|
||||||
|
|
||||||
/* adjust the time until the first event */
|
/* adjust the time until the first event */
|
||||||
update_time_from_event(sd);
|
update_time_from_event (sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
(sim_event *)
|
(sim_event *)
|
||||||
sim_events_schedule(SIM_DESC sd,
|
sim_events_schedule (SIM_DESC sd,
|
||||||
signed64 delta_time,
|
signed64 delta_time,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
sim_event *new_event = ZALLOC(sim_event);
|
sim_event *new_event = ZALLOC(sim_event);
|
||||||
new_event->data = data;
|
new_event->data = data;
|
||||||
new_event->handler = handler;
|
new_event->handler = handler;
|
||||||
|
new_event->watching = watch_timer;
|
||||||
insert_sim_event(sd, new_event, delta_time);
|
insert_sim_event(sd, new_event, delta_time);
|
||||||
ETRACE((_ETRACE,
|
ETRACE((_ETRACE,
|
||||||
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
||||||
@ -223,15 +353,15 @@ sim_events_schedule(SIM_DESC sd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(sim_event *)
|
(sim_event *)
|
||||||
sim_events_schedule_after_signal(SIM_DESC sd,
|
sim_events_schedule_after_signal(SIM_DESC sd,
|
||||||
signed64 delta_time,
|
signed64 delta_time,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
sim_event *new_event = ZALLOC(sim_event);
|
sim_event *new_event = ZALLOC (sim_event);
|
||||||
|
|
||||||
new_event->data = data;
|
new_event->data = data;
|
||||||
new_event->handler = handler;
|
new_event->handler = handler;
|
||||||
@ -239,11 +369,12 @@ sim_events_schedule_after_signal(SIM_DESC sd,
|
|||||||
new_event->next = NULL;
|
new_event->next = NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||||
|
/*-LOCK-*/
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
sigset_t new_mask;
|
sigset_t new_mask;
|
||||||
sigfillset(&new_mask);
|
sigfillset(&new_mask);
|
||||||
/*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
|
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
|
||||||
#endif
|
#endif
|
||||||
if (events->held == NULL) {
|
if (events->held == NULL) {
|
||||||
events->held = new_event;
|
events->held = new_event;
|
||||||
@ -252,77 +383,337 @@ sim_events_schedule_after_signal(SIM_DESC sd,
|
|||||||
*events->held_end = new_event;
|
*events->held_end = new_event;
|
||||||
}
|
}
|
||||||
events->held_end = &new_event->next;
|
events->held_end = &new_event->next;
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
events->work_pending = 1; /* notify main process */
|
||||||
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
|
||||||
|
/*-UNLOCK-*/
|
||||||
|
sigprocmask (SIG_SETMASK, &old_mask, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ETRACE((_ETRACE,
|
ETRACE ((_ETRACE,
|
||||||
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
||||||
(long)sim_events_time(sd),
|
(long)sim_events_time(sd),
|
||||||
(long)new_event,
|
(long)new_event,
|
||||||
(long)new_event->time_of_event,
|
(long)new_event->time_of_event,
|
||||||
(long)new_event->handler,
|
(long)new_event->handler,
|
||||||
(long)new_event->data));
|
(long)new_event->data));
|
||||||
|
|
||||||
return new_event;
|
return new_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void)
|
(sim_event *)
|
||||||
sim_events_deschedule(SIM_DESC sd,
|
sim_events_watch_clock (SIM_DESC sd,
|
||||||
sim_event *event_to_remove)
|
unsigned wallclock_ms_time,
|
||||||
|
sim_event_handler *handler,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
sim_event *to_remove = (sim_event*)event_to_remove;
|
sim_event *new_event = ZALLOC (sim_event);
|
||||||
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
|
/* type */
|
||||||
if (event_to_remove != NULL) {
|
new_event->watching = watch_clock;
|
||||||
sim_event *current;
|
/* handler */
|
||||||
sim_event **ptr_to_current;
|
new_event->data = data;
|
||||||
for (ptr_to_current = &events->queue, current = *ptr_to_current;
|
new_event->handler = handler;
|
||||||
current != NULL && current != to_remove;
|
/* data */
|
||||||
ptr_to_current = ¤t->next, current = *ptr_to_current);
|
new_event->wallclock = wallclock_ms_time;
|
||||||
if (current == to_remove) {
|
/* insert */
|
||||||
*ptr_to_current = current->next;
|
new_event->next = events->watchpoints;
|
||||||
ETRACE((_ETRACE,
|
events->watchpoints = new_event;
|
||||||
"event descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
events->work_pending = 1;
|
||||||
(long)sim_events_time(sd),
|
ETRACE ((_ETRACE,
|
||||||
(long)event_to_remove,
|
"event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
|
||||||
(long)current->time_of_event,
|
(long)sim_events_time (sd),
|
||||||
(long)current->handler,
|
(long)new_event,
|
||||||
(long)current->data));
|
(long)new_event->wallclock,
|
||||||
zfree(current);
|
(long)new_event->handler,
|
||||||
update_time_from_event(sd);
|
(long)new_event->data));
|
||||||
}
|
return new_event;
|
||||||
else {
|
|
||||||
ETRACE((_ETRACE,
|
|
||||||
"event descheduled at %ld - tag 0x%lx - not found\n",
|
|
||||||
(long)sim_events_time(sd),
|
|
||||||
(long)event_to_remove));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(sim_event *)
|
||||||
|
sim_events_watch_sim (SIM_DESC sd,
|
||||||
|
void *host_addr,
|
||||||
|
int nr_bytes,
|
||||||
|
int byte_order,
|
||||||
|
unsigned64 lb,
|
||||||
|
unsigned64 ub,
|
||||||
|
sim_event_handler *handler,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
sim_event *new_event = ZALLOC (sim_event);
|
||||||
|
/* type */
|
||||||
|
switch (byte_order)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_sim_host_1; break;
|
||||||
|
case 2: new_event->watching = watch_sim_host_2; break;
|
||||||
|
case 4: new_event->watching = watch_sim_host_4; break;
|
||||||
|
case 8: new_event->watching = watch_sim_host_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BIG_ENDIAN:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_sim_be_1; break;
|
||||||
|
case 2: new_event->watching = watch_sim_be_2; break;
|
||||||
|
case 4: new_event->watching = watch_sim_be_4; break;
|
||||||
|
case 8: new_event->watching = watch_sim_be_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LITTLE_ENDIAN:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_sim_le_1; break;
|
||||||
|
case 2: new_event->watching = watch_sim_le_2; break;
|
||||||
|
case 4: new_event->watching = watch_sim_le_4; break;
|
||||||
|
case 8: new_event->watching = watch_sim_le_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
|
||||||
|
}
|
||||||
|
/* handler */
|
||||||
|
new_event->data = data;
|
||||||
|
new_event->handler = handler;
|
||||||
|
/* data */
|
||||||
|
new_event->host_addr = host_addr;
|
||||||
|
new_event->lb = lb;
|
||||||
|
new_event->lb64 = lb;
|
||||||
|
new_event->ub = ub;
|
||||||
|
new_event->ub64 = ub;
|
||||||
|
/* insert */
|
||||||
|
new_event->next = events->watchpoints;
|
||||||
|
events->watchpoints = new_event;
|
||||||
|
events->work_pending = 1;
|
||||||
|
ETRACE ((_ETRACE,
|
||||||
|
"event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
|
||||||
|
(long)sim_events_time (sd),
|
||||||
|
(long)new_event,
|
||||||
|
(long)new_event->host_addr,
|
||||||
|
(long)new_event->lb,
|
||||||
|
(long)new_event->ub,
|
||||||
|
(long)new_event->handler,
|
||||||
|
(long)new_event->data));
|
||||||
|
return new_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(sim_event *)
|
||||||
|
sim_events_watch_core (SIM_DESC sd,
|
||||||
|
address_word core_addr,
|
||||||
|
sim_core_maps core_map,
|
||||||
|
int nr_bytes,
|
||||||
|
int byte_order,
|
||||||
|
unsigned64 lb,
|
||||||
|
unsigned64 ub,
|
||||||
|
sim_event_handler *handler,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
sim_event *new_event = ZALLOC (sim_event);
|
||||||
|
/* type */
|
||||||
|
switch (byte_order)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_core_targ_1; break;
|
||||||
|
case 2: new_event->watching = watch_core_targ_2; break;
|
||||||
|
case 4: new_event->watching = watch_core_targ_4; break;
|
||||||
|
case 8: new_event->watching = watch_core_targ_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BIG_ENDIAN:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_core_be_1; break;
|
||||||
|
case 2: new_event->watching = watch_core_be_2; break;
|
||||||
|
case 4: new_event->watching = watch_core_be_4; break;
|
||||||
|
case 8: new_event->watching = watch_core_be_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LITTLE_ENDIAN:
|
||||||
|
switch (nr_bytes)
|
||||||
|
{
|
||||||
|
case 1: new_event->watching = watch_core_le_1; break;
|
||||||
|
case 2: new_event->watching = watch_core_le_2; break;
|
||||||
|
case 4: new_event->watching = watch_core_le_4; break;
|
||||||
|
case 8: new_event->watching = watch_core_le_8; break;
|
||||||
|
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sim_io_error (sd, "sim_events_watch_core - invalid byte order");
|
||||||
|
}
|
||||||
|
/* handler */
|
||||||
|
new_event->data = data;
|
||||||
|
new_event->handler = handler;
|
||||||
|
/* data */
|
||||||
|
new_event->core_addr = core_addr;
|
||||||
|
new_event->core_map = core_map;
|
||||||
|
new_event->lb = lb;
|
||||||
|
new_event->lb64 = lb;
|
||||||
|
new_event->ub = ub;
|
||||||
|
new_event->ub64 = ub;
|
||||||
|
/* insert */
|
||||||
|
new_event->next = events->watchpoints;
|
||||||
|
events->watchpoints = new_event;
|
||||||
|
events->work_pending = 1;
|
||||||
|
ETRACE ((_ETRACE,
|
||||||
|
"event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
|
||||||
|
(long)sim_events_time (sd),
|
||||||
|
(long)new_event,
|
||||||
|
(long)new_event->host_addr,
|
||||||
|
(long)new_event->lb,
|
||||||
|
(long)new_event->ub,
|
||||||
|
(long)new_event->handler,
|
||||||
|
(long)new_event->data));
|
||||||
|
return new_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(void)
|
||||||
|
sim_events_deschedule (SIM_DESC sd,
|
||||||
|
sim_event *event_to_remove)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
sim_event *to_remove = (sim_event*)event_to_remove;
|
||||||
|
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
|
||||||
|
if (event_to_remove != NULL)
|
||||||
|
{
|
||||||
|
sim_event **queue = NULL;
|
||||||
|
while ((queue = next_event_queue (sd, queue)) != NULL)
|
||||||
|
{
|
||||||
|
sim_event **ptr_to_current;
|
||||||
|
for (ptr_to_current = queue;
|
||||||
|
*ptr_to_current != NULL && *ptr_to_current != to_remove;
|
||||||
|
ptr_to_current = &(*ptr_to_current)->next);
|
||||||
|
if (*ptr_to_current == to_remove)
|
||||||
|
{
|
||||||
|
sim_event *dead = *ptr_to_current;
|
||||||
|
*ptr_to_current = dead->next;
|
||||||
|
ETRACE ((_ETRACE,
|
||||||
|
"event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
|
||||||
|
(long) sim_events_time (sd),
|
||||||
|
(long) event_to_remove,
|
||||||
|
(long) dead->time_of_event,
|
||||||
|
(long) dead->handler,
|
||||||
|
(long) dead->data));
|
||||||
|
zfree (dead);
|
||||||
|
update_time_from_event (sd);
|
||||||
|
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ETRACE ((_ETRACE,
|
||||||
|
"event/watch descheduled at %ld - tag 0x%lx - not found\n",
|
||||||
|
(long) sim_events_time (sd),
|
||||||
|
(long) event_to_remove));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STATIC_INLINE_SIM_EVENTS\
|
||||||
|
(int)
|
||||||
|
sim_watch_valid (SIM_DESC sd,
|
||||||
|
sim_event *to_do)
|
||||||
|
{
|
||||||
|
switch (to_do->watching)
|
||||||
|
{
|
||||||
|
|
||||||
|
#define WATCH_CORE(N,OP) \
|
||||||
|
{ \
|
||||||
|
unsigned_##N word; \
|
||||||
|
sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
|
||||||
|
OP (word); \
|
||||||
|
return (word >= to_do->lb && word <= to_do->ub); \
|
||||||
|
}
|
||||||
|
|
||||||
|
case watch_core_targ_1: WATCH_CORE (1, T2H);
|
||||||
|
case watch_core_targ_2: WATCH_CORE (2, T2H);
|
||||||
|
case watch_core_targ_4: WATCH_CORE (4, T2H);
|
||||||
|
case watch_core_targ_8: WATCH_CORE (8, T2H);
|
||||||
|
|
||||||
|
case watch_core_be_1: WATCH_CORE (1, BE2H);
|
||||||
|
case watch_core_be_2: WATCH_CORE (2, BE2H);
|
||||||
|
case watch_core_be_4: WATCH_CORE (4, BE2H);
|
||||||
|
case watch_core_be_8: WATCH_CORE (8, BE2H);
|
||||||
|
|
||||||
|
case watch_core_le_1: WATCH_CORE (1, LE2H);
|
||||||
|
case watch_core_le_2: WATCH_CORE (2, LE2H);
|
||||||
|
case watch_core_le_4: WATCH_CORE (4, LE2H);
|
||||||
|
case watch_core_le_8: WATCH_CORE (8, LE2H);
|
||||||
|
|
||||||
|
#undef WATCH_CORE
|
||||||
|
|
||||||
|
#define WATCH_SIM(N,OP) \
|
||||||
|
{ \
|
||||||
|
unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
|
||||||
|
OP (word); \
|
||||||
|
return (word >= to_do->lb && word <= to_do->ub); \
|
||||||
|
}
|
||||||
|
|
||||||
|
case watch_sim_host_1: WATCH_SIM (1, word = );
|
||||||
|
case watch_sim_host_2: WATCH_SIM (2, word = );
|
||||||
|
case watch_sim_host_4: WATCH_SIM (4, word = );
|
||||||
|
case watch_sim_host_8: WATCH_SIM (8, word = );
|
||||||
|
|
||||||
|
case watch_sim_be_1: WATCH_SIM (1, BE2H);
|
||||||
|
case watch_sim_be_2: WATCH_SIM (2, BE2H);
|
||||||
|
case watch_sim_be_4: WATCH_SIM (4, BE2H);
|
||||||
|
case watch_sim_be_8: WATCH_SIM (8, BE2H);
|
||||||
|
|
||||||
|
case watch_sim_le_1: WATCH_SIM (1, LE2H);
|
||||||
|
case watch_sim_le_2: WATCH_SIM (1, LE2H);
|
||||||
|
case watch_sim_le_4: WATCH_SIM (1, LE2H);
|
||||||
|
case watch_sim_le_8: WATCH_SIM (1, LE2H);
|
||||||
|
#undef WATCH_SIM
|
||||||
|
|
||||||
|
case watch_clock: /* wallclock */
|
||||||
|
return (sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock)
|
||||||
|
< to_do->wallclock);
|
||||||
|
|
||||||
|
case watch_timer:
|
||||||
|
case watch_invalid:
|
||||||
|
sim_io_error (sd, "sim_watch_valid - bad switch");
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
INLINE_SIM_EVENTS\
|
||||||
(int)
|
(int)
|
||||||
sim_events_tick(SIM_DESC sd)
|
sim_events_tick (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS (sd);
|
||||||
|
|
||||||
/* we should only be here when the previous tick has been fully
|
/* this should only be called after the previous tick has been fully
|
||||||
processed */
|
processed */
|
||||||
SIM_ASSERT(!events->processing && events->queue != NULL);
|
SIM_ASSERT (!events->processing);
|
||||||
|
|
||||||
/* Advance the time but *only* if there is nothing to process */
|
/* Advance the time but *only* if there is nothing to process */
|
||||||
if (events->time_from_event == 0)
|
if (events->work_pending
|
||||||
return 1;
|
|| events->time_from_event == 0)
|
||||||
else if (events->held != NULL)
|
{
|
||||||
return 1;
|
events->processing = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
events->time_from_event -= 1;
|
events->time_from_event -= 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -330,65 +721,129 @@ sim_events_tick(SIM_DESC sd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INLINE_SIM_EVENTS\
|
||||||
|
(void)
|
||||||
|
sim_events_preprocess (SIM_DESC sd,
|
||||||
|
int events_were_last,
|
||||||
|
int events_were_next)
|
||||||
|
{
|
||||||
|
sim_events *events = STATE_EVENTS(sd);
|
||||||
|
if (events->processing)
|
||||||
|
{
|
||||||
|
/* Halted midway through event processing */
|
||||||
|
ASSERT (events_were_last && events_were_next);
|
||||||
|
sim_events_process (sd);
|
||||||
|
}
|
||||||
|
else if (events_were_next)
|
||||||
|
{
|
||||||
|
/* Halted by the last processor */
|
||||||
|
ASSERT (!events->processing && !events_were_last);
|
||||||
|
if (sim_events_tick (sd))
|
||||||
|
sim_events_process (sd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
INLINE_SIM_EVENTS\
|
||||||
(void)
|
(void)
|
||||||
sim_events_process(SIM_DESC sd)
|
sim_events_process (SIM_DESC sd)
|
||||||
{
|
{
|
||||||
sim_events *events = &sd->events;
|
sim_events *events = STATE_EVENTS(sd);
|
||||||
signed64 event_time = sim_events_time(sd);
|
signed64 event_time = sim_events_time(sd);
|
||||||
|
|
||||||
/* something to do */
|
ASSERT (events->processing);
|
||||||
SIM_ASSERT(events->time_from_event == 0 || events->held != NULL);
|
|
||||||
SIM_ASSERT(events->queue != NULL);
|
|
||||||
|
|
||||||
/* move any events that were queued by any signal handlers onto the
|
/* move any events that were queued by any signal handlers onto
|
||||||
real event queue. */
|
the real event queue. */
|
||||||
if (events->held != NULL) {
|
if (events->held != NULL)
|
||||||
sim_event *held_events;
|
{
|
||||||
sim_event *curr_event;
|
sim_event *held_events;
|
||||||
|
sim_event *curr_event;
|
||||||
|
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||||
/*-LOCK-*/
|
/*-LOCK-*/
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
sigset_t new_mask;
|
sigset_t new_mask;
|
||||||
sigfillset(&new_mask);
|
sigfillset(&new_mask);
|
||||||
sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
|
sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
held_events = events->held;
|
held_events = events->held;
|
||||||
events->held = NULL;
|
events->held = NULL;
|
||||||
events->held_end = &events->held;
|
events->held_end = &events->held;
|
||||||
|
events->work_pending = 0;
|
||||||
|
|
||||||
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
|
||||||
/*-UNLOCK-*/
|
/*-UNLOCK-*/
|
||||||
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do {
|
do
|
||||||
curr_event = held_events;
|
{
|
||||||
held_events = curr_event->next;
|
curr_event = held_events;
|
||||||
insert_sim_event(sd, curr_event, curr_event->time_of_event);
|
held_events = curr_event->next;
|
||||||
} while (held_events != NULL);
|
insert_sim_event (sd, curr_event,
|
||||||
}
|
curr_event->time_of_event);
|
||||||
|
}
|
||||||
|
while (held_events != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process any watchpoints. Be careful to allow a watchpoint to
|
||||||
|
appear/disappear under our feet.
|
||||||
|
To ensure that watchpoints are processed only once per cycle,
|
||||||
|
they are moved onto a watched queue, this returned to the
|
||||||
|
watchpoint queue when all queue processing has been
|
||||||
|
completed. */
|
||||||
|
while (events->watchpoints != NULL)
|
||||||
|
{
|
||||||
|
sim_event *to_do = events->watchpoints;
|
||||||
|
events->watchpoints = to_do->next;
|
||||||
|
if (sim_watch_valid (sd, to_do))
|
||||||
|
{
|
||||||
|
sim_event_handler *handler = to_do->handler;
|
||||||
|
void *data = to_do->data;
|
||||||
|
events->queue = to_do->next;
|
||||||
|
ETRACE((_ETRACE,
|
||||||
|
"event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
|
||||||
|
(long) event_time,
|
||||||
|
(long) to_do,
|
||||||
|
(long) handler,
|
||||||
|
(long) data));
|
||||||
|
zfree (to_do);
|
||||||
|
handler (sd, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
to_do->next = events->watchedpoints;
|
||||||
|
events->watchedpoints = to_do;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* consume all events for this or earlier times. Be careful to
|
/* consume all events for this or earlier times. Be careful to
|
||||||
allow a new event to appear under our feet */
|
allow an event to appear/disappear under our feet */
|
||||||
events->processing = 1;
|
while (events->queue->time_of_event <= event_time)
|
||||||
while (events->queue->time_of_event <= event_time) {
|
{
|
||||||
sim_event *to_do = events->queue;
|
sim_event *to_do = events->queue;
|
||||||
sim_event_handler *handler = to_do->handler;
|
sim_event_handler *handler = to_do->handler;
|
||||||
void *data = to_do->data;
|
void *data = to_do->data;
|
||||||
events->queue = to_do->next;
|
events->queue = to_do->next;
|
||||||
ETRACE((_ETRACE,
|
ETRACE((_ETRACE,
|
||||||
"event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
|
"event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
|
||||||
(long)event_time,
|
(long) event_time,
|
||||||
(long)to_do,
|
(long) to_do,
|
||||||
(long)handler,
|
(long) handler,
|
||||||
(long)data));
|
(long) data));
|
||||||
zfree (to_do);
|
zfree (to_do);
|
||||||
handler (data);
|
handler (sd, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* put things back where they belong ready for the next iteration */
|
||||||
|
events->watchpoints = events->watchedpoints;
|
||||||
|
events->watchedpoints = NULL;
|
||||||
|
if (events->watchpoints != NULL)
|
||||||
|
events->work_pending = 1;
|
||||||
|
|
||||||
|
/* this round of processing complete */
|
||||||
events->processing = 0;
|
events->processing = 0;
|
||||||
|
|
||||||
/* re-caculate time for new events - advance the time */
|
/* re-caculate time for new events - advance the time */
|
||||||
|
@ -38,49 +38,84 @@
|
|||||||
illustrated above, the event queue should be processed before the
|
illustrated above, the event queue should be processed before the
|
||||||
first instruction. That instruction being executed during tick 1.
|
first instruction. That instruction being executed during tick 1.
|
||||||
|
|
||||||
The event queue is processed using:
|
The simulator main loop may take a form similar to:
|
||||||
|
|
||||||
if (sim_events_tick (sd)) {
|
if (halt-/restart-setjmp)
|
||||||
sim_events_process (sd);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
.... // Determine who should go next
|
||||||
|
last-cpu-nr = get-last-cpu-nr (sd);
|
||||||
|
next-cpu-nr = get-next-cpu-nr (sd);
|
||||||
|
events-were-last? = (last-cpu-nr >= nr-cpus);
|
||||||
|
events-were-next? = (next-cpu-nr >= nr-cpus);
|
||||||
|
|
||||||
|
.... // process any outstanding events
|
||||||
|
sim_events_preprocess (sd, events-were-last?, events-were-next?);
|
||||||
|
if (events-were-next)
|
||||||
|
next-cpu-nr = 0;
|
||||||
|
|
||||||
|
.... // prime main loop
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
.... // model one insn of next-cpu-nr .. nr-cpus
|
||||||
|
if (sim_events_tick (sd))
|
||||||
|
sim_events_process (sd);
|
||||||
|
next-cpu-nr = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NB. In the above pseudo code it is assumed that any cpu-nr >=
|
||||||
|
nr-cpus is a marker for the event queue. */
|
||||||
|
|
||||||
|
|
||||||
typedef void sim_event_handler(void *data);
|
typedef void sim_event_handler(SIM_DESC sd, void *data);
|
||||||
|
|
||||||
typedef struct _sim_event sim_event;
|
typedef struct _sim_event sim_event;
|
||||||
struct _sim_event {
|
|
||||||
void *data;
|
|
||||||
sim_event_handler *handler;
|
|
||||||
signed64 time_of_event;
|
|
||||||
sim_event *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _sim_events sim_events;
|
typedef struct _sim_events sim_events;
|
||||||
struct _sim_events {
|
struct _sim_events {
|
||||||
int processing;
|
int processing;
|
||||||
sim_event *queue;
|
sim_event *queue;
|
||||||
|
sim_event *watchpoints;
|
||||||
|
sim_event *watchedpoints;
|
||||||
|
/* flag additional work needed */
|
||||||
|
volatile int work_pending;
|
||||||
|
/* the asynchronous event queue */
|
||||||
sim_event *volatile held;
|
sim_event *volatile held;
|
||||||
sim_event *volatile *volatile held_end;
|
sim_event *volatile *volatile held_end;
|
||||||
|
/* timekeeping */
|
||||||
|
SIM_ELAPSED_TIME initial_wallclock;
|
||||||
signed64 time_of_event;
|
signed64 time_of_event;
|
||||||
int time_from_event;
|
int time_from_event;
|
||||||
void *path_to_halt_or_restart;
|
|
||||||
int trace;
|
int trace;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Install the "events" module. */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(SIM_RC) sim_events_install (SIM_DESC sd);
|
||||||
|
|
||||||
|
|
||||||
|
/* Uninstall the "events" subsystem. */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(void)
|
||||||
|
sim_events_uninstall (SIM_DESC sd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialization */
|
/* Initialization */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void) sim_events_init
|
(SIM_RC) sim_events_init (SIM_DESC sd);
|
||||||
(SIM_DESC sd);
|
|
||||||
|
|
||||||
|
|
||||||
/* Set Tracing Level */
|
/* Set Tracing Level */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void) sim_events_set_trace
|
(void) sim_events_set_trace
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
int level);
|
int level);
|
||||||
@ -88,14 +123,14 @@ INLINE_SIM_EVENTS\
|
|||||||
|
|
||||||
/* Schedule an event DELTA_TIME ticks into the future */
|
/* Schedule an event DELTA_TIME ticks into the future */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(sim_event *) sim_events_schedule
|
(sim_event *) sim_events_schedule
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
signed64 delta_time,
|
signed64 delta_time,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(sim_event *) sim_events_schedule_after_signal
|
(sim_event *) sim_events_schedule_after_signal
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
signed64 delta_time,
|
signed64 delta_time,
|
||||||
@ -107,79 +142,77 @@ INLINE_SIM_EVENTS\
|
|||||||
simulation. The exact interpretation of wallclock is host
|
simulation. The exact interpretation of wallclock is host
|
||||||
dependant. */
|
dependant. */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void) sim_events_wallclock_schedule
|
(sim_event *) sim_events_watch_clock
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
signed64 wallclock_ms_time,
|
unsigned wallclock_ms_time,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
/* Schedule an event when the NR_BYTES value at HOST_ADDR with
|
||||||
/* Schedule an event when the value at ADDR lies between LB..UB */
|
BYTE_ORDER lies within LB..UB (unsigned).
|
||||||
|
|
||||||
typedef enum {
|
HOST_ADDR: pointer into the host address space.
|
||||||
/* value host byte ordered */
|
BYTE_ORDER: 0 - host endian; BIG_ENDIAN; LITTLE_ENDIAN */
|
||||||
watch_host_1,
|
|
||||||
watch_host_2,
|
|
||||||
watch_host_4,
|
|
||||||
watch_host_8,
|
|
||||||
/* value target byte ordered */
|
|
||||||
watch_targ_1,
|
|
||||||
watch_targ_2,
|
|
||||||
watch_targ_4,
|
|
||||||
watch_targ_8,
|
|
||||||
/* value big-endian */
|
|
||||||
watch_bend_1,
|
|
||||||
watch_bend_2,
|
|
||||||
watch_bend_4,
|
|
||||||
watch_bend_8,
|
|
||||||
/* value little-endian */
|
|
||||||
watch_lend_1,
|
|
||||||
watch_lend_2,
|
|
||||||
watch_lend_4,
|
|
||||||
watch_lend_8,
|
|
||||||
} sim_watchpoint;
|
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void) sim_events_watchpoint_schedule
|
(sim_event*) sim_events_watch_sim
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
sim_watchpoint type,
|
void *host_addr,
|
||||||
void *addr,
|
int nr_bytes,
|
||||||
|
int byte_order,
|
||||||
unsigned64 lb,
|
unsigned64 lb,
|
||||||
unsigned64 ub,
|
unsigned64 ub,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data);
|
void *data);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
/* Schedule an event when the NR_BYTES value at CORE_ADDR with BYTE_ORDER
|
||||||
/* Schedule an event when the value in CORE lies between LB..UB */
|
lies between LB..UB.
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
CORE_ADDR/MAP: pointer into the target address space.
|
||||||
(void) sim_events_watchcore_schedule
|
BYTE_ORDER: 0 - current target endian; BIG_ENDIAN; LITTLE_ENDIAN */
|
||||||
|
|
||||||
|
EXTERN_SIM_EVENTS\
|
||||||
|
(sim_event*) sim_events_watch_core
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
sim_watchpoint type,
|
address_word core_addr,
|
||||||
address_word addr,
|
sim_core_maps core_map,
|
||||||
sim_core_maps map,
|
int nr_bytes,
|
||||||
|
int byte_order,
|
||||||
unsigned64 lb,
|
unsigned64 lb,
|
||||||
unsigned64 ub,
|
unsigned64 ub,
|
||||||
sim_event_handler *handler,
|
sim_event_handler *handler,
|
||||||
void *data);
|
void *data);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Deschedule the specified event */
|
/* Deschedule the specified event */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
EXTERN_SIM_EVENTS\
|
||||||
(void) sim_events_deschedule
|
(void) sim_events_deschedule
|
||||||
(SIM_DESC sd,
|
(SIM_DESC sd,
|
||||||
sim_event *event_to_remove);
|
sim_event *event_to_remove);
|
||||||
|
|
||||||
|
|
||||||
|
/* Prepare for main simulator loop. Ensure that the next thing to do
|
||||||
|
is not event processing.
|
||||||
|
|
||||||
/* progress time. Broken into two parts so that if something is
|
If the simulator halted part way through event processing then both
|
||||||
pending, the caller has a chance to save any cached state */
|
EVENTS_WERE_LAST and EVENTS_WERE_FIRST shall be true.
|
||||||
|
|
||||||
|
If the simulator halted after processing the last cpu, then only
|
||||||
|
EVENTS_WERE_NEXT shall be true. */
|
||||||
|
|
||||||
|
INLINE_SIM_EVENTS\
|
||||||
|
(void) sim_events_preprocess
|
||||||
|
(SIM_DESC sd,
|
||||||
|
int events_were_last,
|
||||||
|
int events_were_next);
|
||||||
|
|
||||||
|
|
||||||
|
/* Progress time - separated into two parts so that the main loop can
|
||||||
|
save its context before the event queue is processed */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
INLINE_SIM_EVENTS\
|
||||||
(int) sim_events_tick
|
(int) sim_events_tick
|
||||||
@ -190,6 +223,7 @@ INLINE_SIM_EVENTS\
|
|||||||
(SIM_DESC sd);
|
(SIM_DESC sd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* local concept of time */
|
/* local concept of time */
|
||||||
|
|
||||||
INLINE_SIM_EVENTS\
|
INLINE_SIM_EVENTS\
|
||||||
|
67
sim/common/sim-resume.c
Normal file
67
sim/common/sim-resume.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Generic simulator resume.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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 <signal.h>
|
||||||
|
|
||||||
|
/* Halt the simulator after just one instruction */
|
||||||
|
|
||||||
|
static void
|
||||||
|
has_stepped (SIM_DESC sd,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGTRAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic resume - assumes the existance of sim_engine_run */
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_resume (SIM_DESC sd,
|
||||||
|
int step,
|
||||||
|
int siggnal)
|
||||||
|
{
|
||||||
|
sim_engine *engine = STATE_ENGINE (sd);
|
||||||
|
jmp_buf buf;
|
||||||
|
|
||||||
|
/* we only want to be single stepping the simulator once */
|
||||||
|
if (engine->stepper != NULL)
|
||||||
|
{
|
||||||
|
sim_events_deschedule (sd, engine->stepper);
|
||||||
|
engine->stepper = NULL;
|
||||||
|
}
|
||||||
|
if (step)
|
||||||
|
engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
|
||||||
|
|
||||||
|
/* run/resume the simulator */
|
||||||
|
engine->jmpbuf = &buf;
|
||||||
|
if (! setjmp (buf))
|
||||||
|
{
|
||||||
|
int last_cpu_nr = sim_engine_last_cpu_nr (sd);
|
||||||
|
int next_cpu_nr = sim_engine_next_cpu_nr (sd);
|
||||||
|
int nr_cpus = MAX_NR_PROCESSORS; /* FIXME */
|
||||||
|
sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
|
||||||
|
if (next_cpu_nr >= nr_cpus)
|
||||||
|
next_cpu_nr = 0;
|
||||||
|
sim_engine_run (sd, next_cpu_nr, siggnal);
|
||||||
|
}
|
||||||
|
engine->jmpbuf = NULL;
|
||||||
|
}
|
45
sim/common/sim-run.c
Normal file
45
sim/common/sim-run.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* Generic simulator run.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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"
|
||||||
|
|
||||||
|
/* Generic implementation of sim_engine_run that works within the
|
||||||
|
sim_engine setjmp/longjmp framework. */
|
||||||
|
|
||||||
|
void
|
||||||
|
sim_engine_run (SIM_DESC sd,
|
||||||
|
int next_cpu_nr, /* ignore */
|
||||||
|
int siggnal) /* ignore */
|
||||||
|
{
|
||||||
|
sim_cia cia;
|
||||||
|
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||||
|
cia = cpu->cia;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
instruction_word insn = IMEM (cia);
|
||||||
|
cia = idecode_issue (sd, insn, cia);
|
||||||
|
/* process any events */
|
||||||
|
if (sim_events_tick (sd))
|
||||||
|
{
|
||||||
|
cpu->cia = cia;
|
||||||
|
sim_events_process (sd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
sim/common/sim-stop.c
Normal file
43
sim/common/sim-stop.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* Generic simulator stop.
|
||||||
|
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||||
|
Contributed by Cygnus Support.
|
||||||
|
|
||||||
|
This file is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
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, 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 <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Generic implementation if sim_stop */
|
||||||
|
|
||||||
|
static void
|
||||||
|
control_c_simulation (SIM_DESC sd,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sim_stop (SIM_DESC sd)
|
||||||
|
{
|
||||||
|
sim_events_schedule_after_signal(sd,
|
||||||
|
0 /*NOW*/,
|
||||||
|
control_c_simulation,
|
||||||
|
sd /*data*/);
|
||||||
|
return 1;
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
Mon May 19 12:55:42 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* Makefile.in (SIM_OBJS): Link in sim-abort.o as a stub for
|
||||||
|
sim_engine_abort.
|
||||||
|
|
||||||
Mon May 5 12:45:28 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Mon May 5 12:45:28 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* sim-if.c (sim_open): Update to reflect changes to core in
|
* sim-if.c (sim_open): Update to reflect changes to core in
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
|
Fri May 16 14:35:30 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
|
* insns (illegal, fp_unavailable): Halt instead of abort the
|
||||||
|
simulator.
|
||||||
|
|
||||||
|
* insns: Replace calls to engine_error with sim_engine_abort.
|
||||||
|
Ditto for engine_halt V sim_engine_halt.
|
||||||
|
|
||||||
|
Tue May 13 15:24:12 1997 Andrew Cagney <cagney@b2.cygnus.com>
|
||||||
|
|
||||||
|
* interp.c (engine_run_until_stop): Delete. Moved to common.
|
||||||
|
(engine_step): Ditto.
|
||||||
|
(engine_step): Ditto.
|
||||||
|
(engine_halt): Ditto.
|
||||||
|
(engine_restart): Ditto.
|
||||||
|
(engine_halt): Ditto.
|
||||||
|
(engine_error): Ditto.
|
||||||
|
|
||||||
|
* sim-calls.c (sim_stop): Delete. Moved to common.
|
||||||
|
(sim_stop_reason): Ditto.
|
||||||
|
(sim_resume): Ditto.
|
||||||
|
|
||||||
|
* Makefile.in (SIM_OBJS): Link in generic sim-engine, sim-run,
|
||||||
|
sim-resume, sim-reason, sim-stop modules.
|
||||||
|
|
||||||
Fri May 16 11:57:49 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
Fri May 16 11:57:49 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* ic (compute): Drop check for REG == 0, now always forced to
|
* ic (compute): Drop check for REG == 0, now always forced to
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# Not all of these need to be mentioned, only the necessary ones.
|
# Not all of these need to be mentioned, only the necessary ones.
|
||||||
|
|
||||||
# List of object files, less common parts.
|
# List of object files, less common parts.
|
||||||
SIM_OBJS = sim-endian.o sim-bits.o sim-config.o interp.o \
|
SIM_OBJS = sim-endian.o sim-bits.o sim-config.o \
|
||||||
support.o idecode.o semantics.o itable.o misc.o \
|
support.o idecode.o semantics.o itable.o misc.o \
|
||||||
sim-calls.o \
|
sim-calls.o \
|
||||||
sim-events.o \
|
sim-events.o \
|
||||||
@ -22,7 +22,12 @@ SIM_OBJS = sim-endian.o sim-bits.o sim-config.o interp.o \
|
|||||||
sim-options.o \
|
sim-options.o \
|
||||||
sim-trace.o \
|
sim-trace.o \
|
||||||
sim-profile.o \
|
sim-profile.o \
|
||||||
sim-fpu.o
|
sim-fpu.o \
|
||||||
|
sim-engine.o \
|
||||||
|
sim-run.o \
|
||||||
|
sim-resume.o \
|
||||||
|
sim-stop.o \
|
||||||
|
sim-reason.o
|
||||||
|
|
||||||
# List of extra dependencies.
|
# List of extra dependencies.
|
||||||
# Generally this consists of simulator specific files included by sim-main.h.
|
# Generally this consists of simulator specific files included by sim-main.h.
|
||||||
@ -142,6 +147,7 @@ ENGINE_H = \
|
|||||||
$(srcdir)/../common/sim-core.h \
|
$(srcdir)/../common/sim-core.h \
|
||||||
$(srcdir)/../common/sim-events.h \
|
$(srcdir)/../common/sim-events.h \
|
||||||
$(srcdir)/../common/sim-fpu.h \
|
$(srcdir)/../common/sim-fpu.h \
|
||||||
|
$(srcdir)/../common/sim-engine.h \
|
||||||
|
|
||||||
idecode.o: $(ENGINE_H)
|
idecode.o: $(ENGINE_H)
|
||||||
semantics.o: $(ENGINE_H)
|
semantics.o: $(ENGINE_H)
|
||||||
|
109
sim/tic80/insns
109
sim/tic80/insns
@ -21,12 +21,13 @@
|
|||||||
|
|
||||||
// The following is called when ever an illegal instruction is encountered.
|
// The following is called when ever an illegal instruction is encountered.
|
||||||
::internal::illegal
|
::internal::illegal
|
||||||
engine_error (SD, CPU, cia,
|
sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) cia.ip);
|
||||||
"illegal instruction at 0x%lx", cia.ip);
|
sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGILL);
|
||||||
|
|
||||||
// The following is called when ever an FP op is attempted with FPU disabled.
|
// The following is called when ever an FP op is attempted with FPU disabled.
|
||||||
::internal::fp_unavailable
|
::internal::fp_unavailable
|
||||||
engine_error (SD, CPU, cia,
|
sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip);
|
||||||
"floating-point unavailable at 0x%lx", cia.ip);
|
sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGFPE);
|
||||||
|
|
||||||
// Handle a branch instruction
|
// Handle a branch instruction
|
||||||
instruction_address::function::do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink
|
instruction_address::function::do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink
|
||||||
@ -184,7 +185,7 @@ instruction_address::function::do_bcnd:instruction_address nia, int Cond, unsign
|
|||||||
case 0: val = SEXT32 (source, 7); break;
|
case 0: val = SEXT32 (source, 7); break;
|
||||||
case 1: val = SEXT32 (source, 15); break;
|
case 1: val = SEXT32 (source, 15); break;
|
||||||
case 2: val = source; break;
|
case 2: val = source; break;
|
||||||
default: engine_error (SD, CPU, cia, "bcnd - reserved size");
|
default: sim_engine_abort (SD, CPU, cia, "bcnd - reserved size");
|
||||||
}
|
}
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
@ -271,28 +272,28 @@ void::function::do_cmnd:signed32 source
|
|||||||
int PP = EXTRACTED32 (source, 3, 0);
|
int PP = EXTRACTED32 (source, 3, 0);
|
||||||
/* what is implemented? */
|
/* what is implemented? */
|
||||||
if (PP != 0)
|
if (PP != 0)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - PPs not supported",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - PPs not supported",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
if (VC != 0)
|
if (VC != 0)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - VC not supported",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - VC not supported",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
if (TC != 0)
|
if (TC != 0)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - TC not supported",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - TC not supported",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
if (MP)
|
if (MP)
|
||||||
{
|
{
|
||||||
if (Reset || Halt)
|
if (Reset || Halt)
|
||||||
engine_halt (SD, CPU, cia, sim_exited, 0);
|
sim_engine_halt (SD, CPU, NULL, cia, sim_exited, 0);
|
||||||
if (Unhalt)
|
if (Unhalt)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
/* if (ICR || DCR); */
|
/* if (ICR || DCR); */
|
||||||
if (Task)
|
if (Task)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
if (Msg)
|
if (Msg)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported",
|
||||||
(unsigned long) cia.ip);
|
(unsigned long) cia.ip);
|
||||||
}
|
}
|
||||||
TRACE_SINK1 (MY_INDEX, source);
|
TRACE_SINK1 (MY_INDEX, source);
|
||||||
31./,21.0b0000010,14.UI::::cmnd i
|
31./,21.0b0000010,14.UI::::cmnd i
|
||||||
@ -401,11 +402,11 @@ sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
|
|||||||
return sim_fpu_32to (val);
|
return sim_fpu_32to (val);
|
||||||
case 1: /* double */
|
case 1: /* double */
|
||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
engine_error (SD, CPU, cia, "DP immediate invalid");
|
sim_engine_abort (SD, CPU, cia, "DP immediate invalid");
|
||||||
if (reg & 1)
|
if (reg & 1)
|
||||||
engine_error (SD, CPU, cia, "DP FP register must be even");
|
sim_engine_abort (SD, CPU, cia, "DP FP register must be even");
|
||||||
if (reg <= 1)
|
if (reg <= 1)
|
||||||
engine_error (SD, CPU, cia, "DP FP register must be >= 2");
|
sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2");
|
||||||
return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32)
|
return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32)
|
||||||
| INSERTED64 (GPR (reg), 31, 0));
|
| INSERTED64 (GPR (reg), 31, 0));
|
||||||
case 2: /* 32 bit signed integer */
|
case 2: /* 32 bit signed integer */
|
||||||
@ -413,7 +414,7 @@ sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
|
|||||||
case 3: /* 32 bit unsigned integer */
|
case 3: /* 32 bit unsigned integer */
|
||||||
return sim_fpu_u32to (val);
|
return sim_fpu_u32to (val);
|
||||||
default:
|
default:
|
||||||
engine_error (SD, CPU, cia, "Unsupported FP precision");
|
sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
|
||||||
}
|
}
|
||||||
return sim_fpu_i32to (0);
|
return sim_fpu_i32to (0);
|
||||||
void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
||||||
@ -428,9 +429,9 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
|||||||
{
|
{
|
||||||
unsigned64 v = sim_fpu_to64 (val);
|
unsigned64 v = sim_fpu_to64 (val);
|
||||||
if (Dest & 1)
|
if (Dest & 1)
|
||||||
engine_error (SD, CPU, cia, "DP FP Dest register must be even");
|
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even");
|
||||||
if (Dest <= 1)
|
if (Dest <= 1)
|
||||||
engine_error (SD, CPU, cia, "DP FP Dest register must be >= 2");
|
sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2");
|
||||||
GPR (Dest + 0) = VL4_8 (v);
|
GPR (Dest + 0) = VL4_8 (v);
|
||||||
GPR (Dest + 1) = VH4_8 (v);
|
GPR (Dest + 1) = VH4_8 (v);
|
||||||
break;
|
break;
|
||||||
@ -446,7 +447,7 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
engine_error (SD, CPU, cia, "Unsupported FP precision");
|
sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
|
||||||
}
|
}
|
||||||
|
|
||||||
// fadd.{s|d}{s|d}{s|d}
|
// fadd.{s|d}{s|d}{s|d}
|
||||||
@ -634,10 +635,10 @@ instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink,
|
|||||||
TRACE_UCOND_BR (MY_INDEX, target);
|
TRACE_UCOND_BR (MY_INDEX, target);
|
||||||
nia = do_branch (_SD, annul, target, 1, rLink);
|
nia = do_branch (_SD, annul, target, 1, rLink);
|
||||||
if (nia.dp & 0x3)
|
if (nia.dp & 0x3)
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: destination address 0x%lx misaligned",
|
"0x%lx: destination address 0x%lx misaligned",
|
||||||
(unsigned long) cia.ip,
|
(unsigned long) cia.ip,
|
||||||
(unsigned long) nia.dp);
|
(unsigned long) nia.dp);
|
||||||
return nia;
|
return nia;
|
||||||
31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i
|
31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i
|
||||||
nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase);
|
nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase);
|
||||||
@ -675,8 +676,8 @@ void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int
|
|||||||
{
|
{
|
||||||
signed64 val;
|
signed64 val;
|
||||||
if (Dest & 0x1)
|
if (Dest & 0x1)
|
||||||
engine_error (SD, CPU, cia, "0x%lx: ld.d to odd register %d",
|
sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d",
|
||||||
cia.ip, Dest);
|
cia.ip, Dest);
|
||||||
addr = base + (S ? (offset << 3) : offset);
|
addr = base + (S ? (offset << 3) : offset);
|
||||||
if (m)
|
if (m)
|
||||||
*rBase = addr;
|
*rBase = addr;
|
||||||
@ -687,7 +688,7 @@ void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
addr = -1;
|
addr = -1;
|
||||||
engine_error (SD, CPU, cia, "ld - invalid sz %d", sz);
|
sim_engine_abort (SD, CPU, cia, "ld - invalid sz %d", sz);
|
||||||
}
|
}
|
||||||
TRACE_LD (MY_INDEX, GPR(Dest), m, S, base, offset);
|
TRACE_LD (MY_INDEX, GPR(Dest), m, S, base, offset);
|
||||||
31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i
|
31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i
|
||||||
@ -714,7 +715,7 @@ void::function::do_ld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, i
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
addr = -1;
|
addr = -1;
|
||||||
engine_error (SD, CPU, cia, "ld.u - invalid sz %d", sz);
|
sim_engine_abort (SD, CPU, cia, "ld.u - invalid sz %d", sz);
|
||||||
}
|
}
|
||||||
if (m)
|
if (m)
|
||||||
*rBase = addr;
|
*rBase = addr;
|
||||||
@ -867,9 +868,9 @@ void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, i
|
|||||||
shiftmask = ~((1 << nRotate) - 1); /* inverted */
|
shiftmask = ~((1 << nRotate) - 1); /* inverted */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: Invalid merge (%d) for shift",
|
"0x%lx: Invalid merge (%d) for shift",
|
||||||
cia.ip, source);
|
cia.ip, source);
|
||||||
shiftmask = 0;
|
shiftmask = 0;
|
||||||
}
|
}
|
||||||
/* and the composite mask */
|
/* and the composite mask */
|
||||||
@ -894,9 +895,9 @@ void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, i
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: Invalid merge (%d)",
|
"0x%lx: Invalid merge (%d)",
|
||||||
cia.ip, source);
|
cia.ip, source);
|
||||||
|
|
||||||
}
|
}
|
||||||
TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate);
|
TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate);
|
||||||
@ -942,9 +943,9 @@ void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , in
|
|||||||
{
|
{
|
||||||
signed64 val;
|
signed64 val;
|
||||||
if (Source & 0x1)
|
if (Source & 0x1)
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: st.d with odd source register %d",
|
"0x%lx: st.d with odd source register %d",
|
||||||
cia.ip, Source);
|
cia.ip, Source);
|
||||||
addr = base + (S ? (offset << 3) : offset);
|
addr = base + (S ? (offset << 3) : offset);
|
||||||
val = (V4_H8 (GPR(Source + 1)) | V4_L8 (GPR(Source)));
|
val = (V4_H8 (GPR(Source + 1)) | V4_L8 (GPR(Source)));
|
||||||
STORE (addr, 8, val);
|
STORE (addr, 8, val);
|
||||||
@ -952,7 +953,7 @@ void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , in
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
addr = -1;
|
addr = -1;
|
||||||
engine_error (SD, CPU, cia, "st - invalid sz %d", sz);
|
sim_engine_abort (SD, CPU, cia, "st - invalid sz %d", sz);
|
||||||
}
|
}
|
||||||
if (m)
|
if (m)
|
||||||
*rBase = addr;
|
*rBase = addr;
|
||||||
@ -1035,7 +1036,7 @@ void::function::do_trap:unsigned32 trap_number
|
|||||||
{
|
{
|
||||||
case 1: /* EXIT */
|
case 1: /* EXIT */
|
||||||
{
|
{
|
||||||
engine_halt (SD, CPU, cia, sim_exited, GPR(2));
|
sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: /* WRITE */
|
case 4: /* WRITE */
|
||||||
@ -1056,9 +1057,9 @@ void::function::do_trap:unsigned32 trap_number
|
|||||||
sim_io_write_stderr (SD, &c, 1);
|
sim_io_write_stderr (SD, &c, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: write to invalid fid %d",
|
"0x%lx: write to invalid fid %d",
|
||||||
(unsigned long) cia.ip, GPR(2));
|
(unsigned long) cia.ip, GPR(2));
|
||||||
GPR(2) = GPR(6);
|
GPR(2) = GPR(6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1069,13 +1070,13 @@ void::function::do_trap:unsigned32 trap_number
|
|||||||
GPR(2) = -22; /* -EINVAL */
|
GPR(2) = -22; /* -EINVAL */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: unknown syscall %d",
|
"0x%lx: unknown syscall %d",
|
||||||
(unsigned long) cia.ip, GPR(15));
|
(unsigned long) cia.ip, GPR(15));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 73:
|
case 73:
|
||||||
engine_halt (SD, CPU, cia, sim_stopped, SIGTRAP);
|
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIGTRAP);
|
||||||
|
|
||||||
/* Add a few traps for now to print the register state */
|
/* Add a few traps for now to print the register state */
|
||||||
case 74:
|
case 74:
|
||||||
@ -1096,9 +1097,9 @@ void::function::do_trap:unsigned32 trap_number
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
engine_error (SD, CPU, cia,
|
sim_engine_abort (SD, CPU, cia,
|
||||||
"0x%lx: unsupported trap %d",
|
"0x%lx: unsupported trap %d",
|
||||||
(unsigned long) cia.ip, trap_number);
|
(unsigned long) cia.ip, trap_number);
|
||||||
}
|
}
|
||||||
31./,27.0,26./,21.0b0000001,14.UTN::::trap i
|
31./,27.0,26./,21.0b0000001,14.UTN::::trap i
|
||||||
do_trap (_SD, UTN);
|
do_trap (_SD, UTN);
|
||||||
|
@ -36,16 +36,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
|
||||||
engine_init (SIM_DESC sd)
|
|
||||||
{
|
|
||||||
memset (&STATE_CPU (sd, 0)->reg, 0, sizeof STATE_CPU (sd, 0)->reg);
|
|
||||||
memset (&STATE_CPU (sd, 0)->cia, 0, sizeof STATE_CPU (sd, 0)->cia);
|
|
||||||
CPU_STATE (STATE_CPU (sd, 0)) = sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Mechanisms for stopping/restarting the simulation */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
engine_error (SIM_DESC sd,
|
engine_error (SIM_DESC sd,
|
||||||
@ -59,13 +51,7 @@ engine_error (SIM_DESC sd,
|
|||||||
sim_io_evprintf (sd, fmt, ap);
|
sim_io_evprintf (sd, fmt, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
if (sd->halt_ok)
|
sim_halt (sd, cpu, NULL, cia, sim_stopped, SIGABRT);
|
||||||
{
|
|
||||||
sim_io_eprintf (sd, "\n");
|
|
||||||
engine_halt (sd, cpu, cia, sim_stopped, SIGABRT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sim_io_error (sd, " - aborting simulation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -139,3 +125,6 @@ engine_step (SIM_DESC sd)
|
|||||||
engine_halt (sd, cpu, cia, sim_stopped, SIGTRAP);
|
engine_halt (sd, cpu, cia, sim_stopped, SIGTRAP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -80,7 +80,13 @@ sim_open (SIM_OPEN_KIND kind, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine_init(&simulation);
|
/* Initialize the main processor */
|
||||||
|
memset (&STATE_CPU (&simulation, 0)->reg, 0, sizeof STATE_CPU (&simulation, 0)->reg);
|
||||||
|
memset (&STATE_CPU (&simulation, 0)->acc, 0, sizeof STATE_CPU (&simulation, 0)->acc);
|
||||||
|
memset (&STATE_CPU (&simulation, 0)->cr, 0, sizeof STATE_CPU (&simulation, 0)->cr);
|
||||||
|
STATE_CPU (&simulation, 0)->is_user_mode = 0;
|
||||||
|
memset (&STATE_CPU (&simulation, 0)->cia, 0, sizeof STATE_CPU (&simulation, 0)->cia);
|
||||||
|
CPU_STATE (STATE_CPU (&simulation, 0)) = &simulation;
|
||||||
|
|
||||||
#define TIC80_MEM_START 0x2000000
|
#define TIC80_MEM_START 0x2000000
|
||||||
#define TIC80_MEM_SIZE 0x100000
|
#define TIC80_MEM_SIZE 0x100000
|
||||||
@ -230,42 +236,6 @@ sim_create_inferior (SIM_DESC sd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
volatile int keep_running = 1;
|
|
||||||
|
|
||||||
void
|
|
||||||
sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
|
|
||||||
{
|
|
||||||
if (!keep_running)
|
|
||||||
{
|
|
||||||
*reason = sim_stopped;
|
|
||||||
*sigrc = SIGINT;
|
|
||||||
keep_running = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*reason = simulation.reason;
|
|
||||||
*sigrc = simulation.siggnal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
sim_stop (SIM_DESC sd)
|
|
||||||
{
|
|
||||||
keep_running = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sim_resume (SIM_DESC sd, int step, int siggnal)
|
|
||||||
{
|
|
||||||
/* keep_running = 1 - in sim_stop_reason */
|
|
||||||
if (step)
|
|
||||||
engine_step (sd);
|
|
||||||
else
|
|
||||||
engine_run_until_stop (sd, &keep_running);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sim_do_command (SIM_DESC sd, char *cmd)
|
sim_do_command (SIM_DESC sd, char *cmd)
|
||||||
{
|
{
|
||||||
|
@ -69,39 +69,4 @@ extern void engine_init
|
|||||||
(SIM_DESC sd);
|
(SIM_DESC sd);
|
||||||
|
|
||||||
|
|
||||||
/* Mechanisms for stopping/restarting the simulation.
|
|
||||||
|
|
||||||
A non NULL CPU argument designates the processor that is initiating
|
|
||||||
the halt. After the simulation has stopped that processor should
|
|
||||||
be marked as the last one active */
|
|
||||||
|
|
||||||
extern void engine_error
|
|
||||||
(SIM_DESC sd,
|
|
||||||
sim_cpu *cpu,
|
|
||||||
instruction_address cia,
|
|
||||||
const char *fmt,
|
|
||||||
...);
|
|
||||||
|
|
||||||
extern void engine_halt
|
|
||||||
(SIM_DESC sd,
|
|
||||||
sim_cpu *cpu,
|
|
||||||
instruction_address cia,
|
|
||||||
enum sim_stop reason,
|
|
||||||
int siggnal);
|
|
||||||
|
|
||||||
extern void engine_restart
|
|
||||||
(SIM_DESC sd,
|
|
||||||
sim_cpu *cpu,
|
|
||||||
instruction_address cia);
|
|
||||||
|
|
||||||
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
|
|
||||||
thing (others later) */
|
|
||||||
|
|
||||||
extern void engine_run_until_stop
|
|
||||||
(SIM_DESC sd,
|
|
||||||
volatile int *keep_running);
|
|
||||||
|
|
||||||
extern void engine_step
|
|
||||||
(SIM_DESC sd);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user