mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-01 07:50:49 +00:00
* Monster patch - may destablize MIPS sims for a little while.
* Followup patch for SCEI PR 15853 * First check-in of TX3904 interrupt controller devices for ECC. [sanitized] * First implementation of MIPS hardware interrupt emulation. Mon May 18 18:22:42 1998 Frank Ch. Eigler <fche@cygnus.com> * configure.in (SIM_AC_OPTION_HARDWARE): Added common hardware modules. Recognize TX39 target with "mips*tx39" pattern. * configure: Rebuilt. * sim-main.h (*): Added many macros defining bits in TX39 control registers. (SignalInterrupt): Send actual PC instead of NULL. (SignalNMIReset): New exception type. * interp.c (board): New variable for future use to identify a particular board being simulated. (mips_option_handler,mips_options): Added "--board" option. (interrupt_event): Send actual PC. (sim_open): Make memory layout conditional on board setting. (signal_exception): Initial implementation of hardware interrupt handling. Accept another break instruction variant for simulator exit. (decode_coproc): Implement RFE instruction for TX39. (mips.igen): Decode RFE instruction as such. start-sanitize-tx3904 * configure.in (tx3904cpu,tx3904irc): Added devices for tx3904. * interp.c: Define "jmr3904" and "jmr3904debug" board types and bbegin to implement memory map. * dv-tx3904cpu.c: New file. * dv-tx3904irc.c: New file. end-sanitize-tx3904
This commit is contained in:
parent
d9c2c0c569
commit
3fa454e95f
@ -31,6 +31,13 @@ else
|
||||
lose_these_too="${vr4320_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
tx3904_files="dv-tx3904cpu.c dv-tx3904irc.c"
|
||||
if ( echo $* | grep keep\-tx3904 > /dev/null ) ; then
|
||||
keep_these_too="${tx3904_files} ${keep_these_too}"
|
||||
else
|
||||
lose_these_too="${tx3904_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
sky_files="ChangeLog.sky sky-device.c sky-device.h sky-dma.c sky-dma.h sky-bits.h"
|
||||
sky_files="$sky_files sky-engine.c sky-gpuif.c sky-gpuif.h"
|
||||
sky_files="$sky_files sky-gs.c sky-gs.h"
|
||||
@ -264,6 +271,36 @@ else
|
||||
fi
|
||||
|
||||
|
||||
tx3904_files="ChangeLog configure configure.in interp.c"
|
||||
|
||||
if ( echo $* | grep keep\-tx3904 > /dev/null ) ; then
|
||||
for i in $tx3904_files ; do
|
||||
if test ! -d $i && (grep sanitize-tx3904 $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Keeping tx3904 stuff in $i
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else
|
||||
for i in * ; do
|
||||
if test ! -d $i && (grep sanitize-tx3904 $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Removing traces of \"tx3904\" from $i...
|
||||
fi
|
||||
cp $i new
|
||||
sed '/start\-sanitize\-tx3904/,/end-\sanitize\-tx3904/d' < $i > new
|
||||
if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Caching $i in .Recover...
|
||||
fi
|
||||
mv $i .Recover
|
||||
fi
|
||||
mv new $i
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
|
||||
never_files="ChangeLog configure configure.in interp.c gencode.c mips.igen mips.dc"
|
||||
|
||||
|
@ -1,3 +1,34 @@
|
||||
Mon May 18 18:22:42 1998 Frank Ch. Eigler <fche@cygnus.com>
|
||||
|
||||
* configure.in (SIM_AC_OPTION_HARDWARE): Added common hardware
|
||||
modules. Recognize TX39 target with "mips*tx39" pattern.
|
||||
* configure: Rebuilt.
|
||||
* sim-main.h (*): Added many macros defining bits in
|
||||
TX39 control registers.
|
||||
(SignalInterrupt): Send actual PC instead of NULL.
|
||||
(SignalNMIReset): New exception type.
|
||||
* interp.c (board): New variable for future use to identify
|
||||
a particular board being simulated.
|
||||
(mips_option_handler,mips_options): Added "--board" option.
|
||||
(interrupt_event): Send actual PC.
|
||||
(sim_open): Make memory layout conditional on board setting.
|
||||
(signal_exception): Initial implementation of hardware interrupt
|
||||
handling. Accept another break instruction variant for simulator
|
||||
exit.
|
||||
(decode_coproc): Implement RFE instruction for TX39.
|
||||
(mips.igen): Decode RFE instruction as such.
|
||||
start-sanitize-tx3904
|
||||
* configure.in (tx3904cpu,tx3904irc): Added devices for tx3904.
|
||||
* interp.c: Define "jmr3904" and "jmr3904debug" board types and
|
||||
bbegin to implement memory map.
|
||||
* dv-tx3904cpu.c: New file.
|
||||
* dv-tx3904irc.c: New file.
|
||||
end-sanitize-tx3904
|
||||
|
||||
Wed May 13 14:40:11 1998 Gavin Koch <gavin@cygnus.com>
|
||||
|
||||
* mips.igen (check_mt_hilo): Create a separate r3900 version.
|
||||
|
||||
Wed May 13 14:27:53 1998 Gavin Koch <gavin@cygnus.com>
|
||||
|
||||
* r5900.igen: Replace the calls and the definition of the
|
||||
|
410
sim/mips/configure
vendored
410
sim/mips/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,6 @@ SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT)
|
||||
SIM_AC_OPTION_HOSTENDIAN
|
||||
SIM_AC_OPTION_WARNINGS
|
||||
|
||||
|
||||
# Ensure a reasonable default simulator is constructed: (DEPRECATED)
|
||||
case "${target}" in
|
||||
# start-sanitize-tx19
|
||||
@ -41,7 +40,7 @@ case "${target}" in
|
||||
# start-sanitize-tx19
|
||||
mipstx19*-*-*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";;
|
||||
# end-sanitize-tx19
|
||||
mipstx39*-*-*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";;
|
||||
mips*tx39*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";;
|
||||
*) SIM_SUBTARGET="";;
|
||||
esac
|
||||
AC_SUBST(SIM_SUBTARGET)
|
||||
@ -98,7 +97,7 @@ case "${target}" in
|
||||
# start-sanitize-tx19
|
||||
mipstx19*-*-*) mips_fpu=SOFT_FLOATING_POINT ;;
|
||||
# end-sanitize-tx19
|
||||
mipstx39*-*-*) mips_fpu=HARD_FLOATING_POINT
|
||||
mips*tx39*) mips_fpu=HARD_FLOATING_POINT
|
||||
mips_fpu_bitsize=32
|
||||
;;
|
||||
# start-sanitize-r5900
|
||||
@ -144,7 +143,7 @@ case "${target}" in
|
||||
sim_m16_filter="16"
|
||||
;;
|
||||
# end-sanitize-tx19
|
||||
mipstx39*-*-*) sim_default_gen=IGEN
|
||||
mipst*tx39*) sim_default_gen=IGEN
|
||||
sim_use_gen=IGEN
|
||||
sim_igen_filter="32,f"
|
||||
sim_igen_machine="-M r3900"
|
||||
@ -239,6 +238,18 @@ esac
|
||||
AC_SUBST(mips_extra_objs)
|
||||
|
||||
|
||||
|
||||
# Add simulated hardware devices
|
||||
#
|
||||
SIM_AC_OPTION_HARDWARE()
|
||||
case "${target}" in
|
||||
# start-sanitize-tx3904
|
||||
mips*tx39*) SIM_AC_OPTION_HARDWARE(,tx3904cpu tx3904irc) ;;
|
||||
# end-sanitize-tx3904
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
|
||||
AC_PATH_X
|
||||
mips_extra_libs=""
|
||||
# start-sanitize-sky
|
||||
|
230
sim/mips/dv-tx3904cpu.c
Normal file
230
sim/mips/dv-tx3904cpu.c
Normal file
@ -0,0 +1,230 @@
|
||||
/* This file is part of the program GDB, the GU debugger.
|
||||
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "hw-base.h"
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
PORTS
|
||||
|
||||
|
||||
reset (input)
|
||||
|
||||
Currently ignored.
|
||||
|
||||
|
||||
nmi (input)
|
||||
|
||||
Deliver a non-maskable interrupt to the processor.
|
||||
|
||||
|
||||
level (input)
|
||||
|
||||
Deliver a maskable interrupt of given level, corresponding to
|
||||
IP[5:0], to processor.
|
||||
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
|
||||
When delivering an interrupt, this code assumes that there is only
|
||||
one processor (number 0).
|
||||
|
||||
This code does not attempt to be efficient at handling pending
|
||||
interrupts. It simply schedules the interrupt delivery handler
|
||||
every instruction cycle until all pending interrupts go away. An
|
||||
alternative implementation might modify instructions that change
|
||||
the PSW and have them check to see if the change makes an interrupt
|
||||
delivery possible.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
struct tx3904cpu {
|
||||
/* Pending interrupts for delivery by event handler */
|
||||
int pending_reset, pending_nmi, pending_level;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* input port ID's */
|
||||
|
||||
enum {
|
||||
RESET_PORT,
|
||||
NMI_PORT,
|
||||
LEVEL_PORT,
|
||||
};
|
||||
|
||||
|
||||
static const struct hw_port_descriptor tx3904cpu_ports[] = {
|
||||
|
||||
/* interrupt inputs */
|
||||
{ "reset", RESET_PORT, 0, input_port, },
|
||||
{ "nmi", NMI_PORT, 0, input_port, },
|
||||
{ "level", LEVEL_PORT, 0, input_port, },
|
||||
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
/* Finish off the partially created hw device. Attach our local
|
||||
callbacks. Wire up our port names etc */
|
||||
|
||||
static hw_port_event_callback tx3904cpu_port_event;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
tx3904cpu_finish (struct hw *me)
|
||||
{
|
||||
struct tx3904cpu *controller;
|
||||
|
||||
controller = HW_ZALLOC (me, struct tx3904cpu);
|
||||
set_hw_data (me, controller);
|
||||
set_hw_ports (me, tx3904cpu_ports);
|
||||
set_hw_port_event (me, tx3904cpu_port_event);
|
||||
|
||||
/* Initialize the pending interrupt flags */
|
||||
controller->pending_level = 0;
|
||||
controller->pending_reset = 0;
|
||||
controller->pending_nmi = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* An event arrives on an interrupt port */
|
||||
|
||||
static void
|
||||
deliver_tx3904cpu_interrupt (struct hw *me,
|
||||
void *data)
|
||||
{
|
||||
struct tx3904cpu *controller = hw_data (me);
|
||||
SIM_DESC simulator = hw_system (me);
|
||||
sim_cpu *cpu = STATE_CPU (simulator, 0); /* NB: fix CPU 0. */
|
||||
address_word cia = CIA_GET (cpu);
|
||||
|
||||
#define CPU cpu
|
||||
#define SD current_state
|
||||
|
||||
if (controller->pending_reset)
|
||||
{
|
||||
controller->pending_reset = 0;
|
||||
HW_TRACE ((me, "reset pc=0x%08lx", (long) CIA_GET (cpu)));
|
||||
SignalExceptionNMIReset();
|
||||
}
|
||||
else if (controller->pending_nmi)
|
||||
{
|
||||
controller->pending_nmi = 0;
|
||||
HW_TRACE ((me, "nmi pc=0x%08lx", (long) CIA_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));
|
||||
|
||||
/* Don't overwrite the CAUSE field since we have no good place to clear
|
||||
it again. The specs allow it to be zero by the time the interrupt
|
||||
handler is invoked. */
|
||||
/* CAUSE &= ~ (cause_IP_mask << cause_IP_shift);
|
||||
CAUSE |= (controller->pending_level & cause_IP_mask) << cause_IP_shift; */
|
||||
|
||||
/* check for enabled / unmasked interrupts */
|
||||
if((SR & status_IEc) &&
|
||||
(controller->pending_level & ((SR >> status_IM_shift) & status_IM_mask)))
|
||||
{
|
||||
controller->pending_level = 0;
|
||||
SignalExceptionInterrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reschedule soon */
|
||||
hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL);
|
||||
}
|
||||
}
|
||||
#undef CPU cpu
|
||||
#undef SD current_state
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tx3904cpu_port_event (struct hw *me,
|
||||
int my_port,
|
||||
struct hw *source,
|
||||
int source_port,
|
||||
int level)
|
||||
{
|
||||
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:
|
||||
controller->pending_level |= level; /* accumulate bits until they are cleared */
|
||||
HW_TRACE ((me, "port-in level=%d", level));
|
||||
break;
|
||||
|
||||
default:
|
||||
hw_abort (me, "bad switch");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Schedule an event to be delivered immediately after current
|
||||
instruction. */
|
||||
hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL);
|
||||
}
|
||||
|
||||
|
||||
const struct hw_device_descriptor dv_tx3904cpu_descriptor[] = {
|
||||
{ "tx3904cpu", tx3904cpu_finish, },
|
||||
{ NULL },
|
||||
};
|
392
sim/mips/dv-tx3904irc.c
Normal file
392
sim/mips/dv-tx3904irc.c
Normal file
@ -0,0 +1,392 @@
|
||||
/* This file is part of the program GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "hw-base.h"
|
||||
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
tx3904irc - tx3904 interrupt controller
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
Implements the tx3904 interrupt controller described in the tx3904
|
||||
user guide. It does not include the interrupt detection circuit
|
||||
that preprocesses the eight external interrupts.
|
||||
|
||||
|
||||
PROPERTIES
|
||||
|
||||
|
||||
reg <base> <length>
|
||||
|
||||
Base of IRC control register bank. <length> must equal 0x20.
|
||||
Registers offsets: 0: ISR: interrupt status register
|
||||
4: IMR: interrupt mask register
|
||||
16: ILR0: interrupt level register 3..0
|
||||
20: ILR1: interrupt level register 7..4
|
||||
24: ILR2: interrupt level register 11..8
|
||||
28: ILR3: interrupt level register 15..12
|
||||
|
||||
|
||||
|
||||
PORTS
|
||||
|
||||
|
||||
ip (output)
|
||||
|
||||
Interrupt priority port. An event is generated when an interrupt
|
||||
of a sufficient priority is passed through the IRC. The value
|
||||
associated with the event is the interrupt level (16-31), as given
|
||||
for bits IP[5:0] in the book TMPR3904F Rev. 2.0, pg. 11-3. Note
|
||||
that even though INT[0] is tied externally to IP[5], we simulate
|
||||
it as passing through the controller.
|
||||
|
||||
|
||||
int0-7 (input)
|
||||
|
||||
External interrupts.
|
||||
|
||||
|
||||
dmac0-3 (input)
|
||||
|
||||
DMA internal interrupts, correspond to DMA channels 0-3.
|
||||
|
||||
|
||||
sio0-1 (input)
|
||||
|
||||
SIO internal interrupts.
|
||||
|
||||
|
||||
tmr0-2 (input)
|
||||
|
||||
Timer internal interrupts.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* port ID's */
|
||||
|
||||
enum {
|
||||
/* inputs, ordered to correspond to interrupt sources 0..15 */
|
||||
INT1_PORT = 0, INT2_PORT, INT3_PORT, INT4_PORT, INT5_PORT, INT6_PORT, INT7_PORT,
|
||||
DMAC3_PORT, DMAC2_PORT, DMAC1_PORT, DMAC0_PORT, SIO0_PORT, SIO1_PORT,
|
||||
TMR0_PORT, TMR1_PORT, TMR2_PORT,
|
||||
|
||||
/* special INT[0] port */
|
||||
INT0_PORT,
|
||||
|
||||
/* reset */
|
||||
RESET_PORT,
|
||||
|
||||
/* output */
|
||||
IP_PORT
|
||||
};
|
||||
|
||||
|
||||
/* register numbers; each is one word long */
|
||||
enum {
|
||||
ISR_REG = 0,
|
||||
IMR_REG = 1,
|
||||
ILR0_REG = 4,
|
||||
ILR1_REG = 5,
|
||||
ILR2_REG = 6,
|
||||
ILR3_REG = 7,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const struct hw_port_descriptor tx3904irc_ports[] = {
|
||||
|
||||
/* interrupt output */
|
||||
|
||||
{ "ip", IP_PORT, 0, output_port, },
|
||||
|
||||
/* interrupt inputs (as names) */
|
||||
/* in increasing order of level number */
|
||||
|
||||
{ "int1", INT1_PORT, 0, input_port, },
|
||||
{ "int2", INT2_PORT, 0, input_port, },
|
||||
{ "int3", INT3_PORT, 0, input_port, },
|
||||
{ "int4", INT4_PORT, 0, input_port, },
|
||||
{ "int5", INT5_PORT, 0, input_port, },
|
||||
{ "int6", INT6_PORT, 0, input_port, },
|
||||
{ "int7", INT7_PORT, 0, input_port, },
|
||||
|
||||
{ "dmac3", DMAC3_PORT, 0, input_port, },
|
||||
{ "dmac2", DMAC2_PORT, 0, input_port, },
|
||||
{ "dmac1", DMAC1_PORT, 0, input_port, },
|
||||
{ "dmac0", DMAC0_PORT, 0, input_port, },
|
||||
|
||||
{ "sio0", SIO0_PORT, 0, input_port, },
|
||||
{ "sio1", SIO1_PORT, 0, input_port, },
|
||||
|
||||
{ "tmr0", TMR0_PORT, 0, input_port, },
|
||||
{ "tmr1", TMR1_PORT, 0, input_port, },
|
||||
{ "tmr2", TMR2_PORT, 0, input_port, },
|
||||
|
||||
{ "reset", RESET_PORT, 0, input_port, },
|
||||
{ "int0", INT0_PORT, 0, input_port, },
|
||||
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
#define NR_SOURCES (TMR3_PORT - INT1_PORT + 1) /* 16: number of interrupt sources */
|
||||
|
||||
|
||||
/* The interrupt controller register internal state. Note that we
|
||||
store state using the control register images, in host endian
|
||||
order. */
|
||||
|
||||
struct tx3904irc {
|
||||
address_word base_address; /* control register base */
|
||||
unsigned_4 isr;
|
||||
#define ISR_SET(c,s) ((c)->isr &= ~ (1 << (s)))
|
||||
unsigned_4 imr;
|
||||
#define IMR_GET(c) ((c)->imr)
|
||||
unsigned_4 ilr[4];
|
||||
#define ILR_GET(c,s) LSEXTRACTED32((c)->ilr[(s)/4], (s) % 4 * 8 + 2, (s) % 4 * 8)
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Finish off the partially created hw device. Attach our local
|
||||
callbacks. Wire up our port names etc */
|
||||
|
||||
static hw_io_read_buffer_callback tx3904irc_io_read_buffer;
|
||||
static hw_io_write_buffer_callback tx3904irc_io_write_buffer;
|
||||
static hw_port_event_callback tx3904irc_port_event;
|
||||
|
||||
static void
|
||||
attach_tx3904irc_regs (struct hw *me,
|
||||
struct tx3904irc *controller)
|
||||
{
|
||||
unsigned_word attach_address;
|
||||
int attach_space;
|
||||
unsigned attach_size;
|
||||
reg_property_spec reg;
|
||||
|
||||
if (hw_find_property (me, "reg") == NULL)
|
||||
hw_abort (me, "Missing \"reg\" property");
|
||||
|
||||
if (!hw_find_reg_array_property (me, "reg", 0, ®))
|
||||
hw_abort (me, "\"reg\" property must contain one addr/size entry");
|
||||
|
||||
hw_unit_address_to_attach_address (hw_parent (me),
|
||||
®.address,
|
||||
&attach_space,
|
||||
&attach_address,
|
||||
me);
|
||||
hw_unit_size_to_attach_size (hw_parent (me),
|
||||
®.size,
|
||||
&attach_size, me);
|
||||
|
||||
hw_attach_address (hw_parent (me), 0,
|
||||
attach_space, attach_address, attach_size,
|
||||
me);
|
||||
|
||||
controller->base_address = attach_address;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tx3904irc_finish (struct hw *me)
|
||||
{
|
||||
int i;
|
||||
struct tx3904irc *controller;
|
||||
|
||||
controller = HW_ZALLOC (me, struct tx3904irc);
|
||||
set_hw_data (me, controller);
|
||||
set_hw_io_read_buffer (me, tx3904irc_io_read_buffer);
|
||||
set_hw_io_write_buffer (me, tx3904irc_io_write_buffer);
|
||||
set_hw_ports (me, tx3904irc_ports);
|
||||
set_hw_port_event (me, tx3904irc_port_event);
|
||||
|
||||
/* Attach ourself to our parent bus */
|
||||
attach_tx3904irc_regs (me, controller);
|
||||
|
||||
/* Initialize to reset state */
|
||||
controller->isr = 0x0000ffff;
|
||||
controller->imr = 0;
|
||||
controller->ilr[0] =
|
||||
controller->ilr[1] =
|
||||
controller->ilr[2] =
|
||||
controller->ilr[3] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* An event arrives on an interrupt port */
|
||||
|
||||
static void
|
||||
tx3904irc_port_event (struct hw *me,
|
||||
int my_port,
|
||||
struct hw *source,
|
||||
int source_port,
|
||||
int level)
|
||||
{
|
||||
struct tx3904irc *controller = hw_data (me);
|
||||
|
||||
switch (my_port)
|
||||
{
|
||||
case INT0_PORT:
|
||||
{
|
||||
int ip_number = 32; /* compute IP[5:0] */
|
||||
HW_TRACE ((me, "port-event INT[0]"));
|
||||
hw_port_event(me, IP_PORT, ip_number);
|
||||
break;
|
||||
}
|
||||
|
||||
case INT1_PORT: case INT2_PORT: case INT3_PORT: case INT4_PORT:
|
||||
case INT5_PORT: case INT6_PORT: case INT7_PORT: case DMAC3_PORT:
|
||||
case DMAC2_PORT: case DMAC1_PORT: case DMAC0_PORT: case SIO0_PORT:
|
||||
case SIO1_PORT: case TMR0_PORT: case TMR1_PORT: case TMR2_PORT:
|
||||
{
|
||||
int source = my_port - INT1_PORT;
|
||||
|
||||
HW_TRACE ((me, "port-event interrupt source %d", source));
|
||||
ISR_SET(controller, source);
|
||||
if(ILR_GET(controller, source) > IMR_GET(controller))
|
||||
{
|
||||
int ip_number = 16 + source; /* compute IP[4:0] */
|
||||
HW_TRACE ((me, "interrupt level %d", ILR_GET(controller,source)));
|
||||
hw_port_event(me, IP_PORT, ip_number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RESET_PORT:
|
||||
{
|
||||
HW_TRACE ((me, "reset"));
|
||||
controller->isr = 0x0000ffff;
|
||||
controller->imr = 0;
|
||||
controller->ilr[0] =
|
||||
controller->ilr[1] =
|
||||
controller->ilr[2] =
|
||||
controller->ilr[3] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case IP_PORT:
|
||||
hw_abort (me, "Event on output port %d", my_port);
|
||||
break;
|
||||
|
||||
default:
|
||||
hw_abort (me, "Event on unknown port %d", my_port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* generic read/write */
|
||||
|
||||
static unsigned
|
||||
tx3904irc_io_read_buffer (struct hw *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
struct tx3904irc *controller = hw_data (me);
|
||||
unsigned byte;
|
||||
|
||||
HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
|
||||
for (byte = 0; byte < nr_bytes; byte++)
|
||||
{
|
||||
address_word address = base + byte;
|
||||
int reg_number = (address - controller->base_address) / 4;
|
||||
int reg_offset = (address - controller->base_address) % 4;
|
||||
unsigned_4 register_value; /* in target byte order */
|
||||
|
||||
/* fill in entire register_value word */
|
||||
switch (reg_number)
|
||||
{
|
||||
case ISR_REG: register_value = controller->isr; break;
|
||||
case IMR_REG: register_value = controller->imr; break;
|
||||
case ILR0_REG: register_value = controller->ilr[0]; break;
|
||||
case ILR1_REG: register_value = controller->ilr[1]; break;
|
||||
case ILR2_REG: register_value = controller->ilr[2]; break;
|
||||
case ILR3_REG: register_value = controller->ilr[3]; break;
|
||||
default: register_value = 0;
|
||||
}
|
||||
|
||||
/* write requested byte out */
|
||||
memcpy(dest+byte, ((char*)& register_value)+reg_offset, 1);
|
||||
}
|
||||
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned
|
||||
tx3904irc_io_write_buffer (struct hw *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes)
|
||||
{
|
||||
struct tx3904irc *controller = hw_data (me);
|
||||
unsigned byte;
|
||||
|
||||
HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
|
||||
for (byte = 0; byte < nr_bytes; byte++)
|
||||
{
|
||||
address_word address = base + byte;
|
||||
int reg_number = (address - controller->base_address) / 4;
|
||||
int reg_offset = (address - controller->base_address) % 4;
|
||||
unsigned_4* register_ptr;
|
||||
unsigned_4 register_value;
|
||||
|
||||
/* fill in entire register_value word */
|
||||
switch (reg_number)
|
||||
{
|
||||
case ISR_REG: register_ptr = & controller->isr; break;
|
||||
case IMR_REG: register_ptr = & controller->imr; break;
|
||||
case ILR0_REG: register_ptr = & controller->ilr[0]; break;
|
||||
case ILR1_REG: register_ptr = & controller->ilr[1]; break;
|
||||
case ILR2_REG: register_ptr = & controller->ilr[2]; break;
|
||||
case ILR3_REG: register_ptr = & controller->ilr[3]; break;
|
||||
default: register_ptr = & register_value; /* used as a dummy */
|
||||
}
|
||||
|
||||
HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr));
|
||||
|
||||
/* overwrite requested byte */
|
||||
memcpy(((char*)register_ptr)+reg_offset, source+byte, 1);
|
||||
|
||||
HW_TRACE ((me, "post: %08lx", (long) *register_ptr));
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
const struct hw_device_descriptor dv_tx3904irc_descriptor[] = {
|
||||
{ "tx3904irc", tx3904irc_finish, },
|
||||
{ NULL },
|
||||
};
|
@ -37,6 +37,7 @@ code on the hardware.
|
||||
#include "sim-utils.h"
|
||||
#include "sim-options.h"
|
||||
#include "sim-assert.h"
|
||||
#include "sim-hw.h"
|
||||
|
||||
/* start-sanitize-sky */
|
||||
#ifdef TARGET_SKY
|
||||
@ -113,6 +114,7 @@ char* pr_uword64 PARAMS ((uword64 addr));
|
||||
halt is required. NOTE: Care must be taken, since this value may
|
||||
be used in later revisions of the MIPS ISA. */
|
||||
#define HALT_INSTRUCTION (0x03ff000d)
|
||||
#define HALT_INSTRUCTION2 (0x0000ffcd)
|
||||
#define HALT_INSTRUCTION_MASK (0x03FFFFC0)
|
||||
|
||||
|
||||
@ -180,6 +182,10 @@ FILE *tracefh = NULL;
|
||||
static void open_trace PARAMS((SIM_DESC sd));
|
||||
#endif /* TRACE */
|
||||
|
||||
/* simulation target board. NULL=canonical */
|
||||
static char* board = NULL;
|
||||
|
||||
|
||||
static DECLARE_OPTION_HANDLER (mips_option_handler);
|
||||
|
||||
enum {
|
||||
@ -195,8 +201,10 @@ enum {
|
||||
,OPTION_GS_REFRESH2
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
,OPTION_BOARD
|
||||
};
|
||||
|
||||
|
||||
static SIM_RC
|
||||
mips_option_handler (sd, cpu, opt, arg, is_command)
|
||||
SIM_DESC sd;
|
||||
@ -265,10 +273,10 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
|
||||
#ifdef SKY_FUNIT
|
||||
case OPTION_FLOAT_TYPE:
|
||||
/* Use host (fast) or target (accurate) floating point implementation. */
|
||||
if (arg && strcmp (arg, "host") == 0)
|
||||
STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
|
||||
else if (arg && strcmp (arg, "target") == 0)
|
||||
STATE_FP_TYPE_OPT (sd) |= STATE_FP_TYPE_OPT_TARGET;
|
||||
if (arg && strcmp (arg, "fast") == 0)
|
||||
STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_ACCURATE;
|
||||
else if (arg && strcmp (arg, "accurate") == 0)
|
||||
STATE_FP_TYPE_OPT (sd) |= STATE_FP_TYPE_OPT_ACCURATE;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Unrecognized float-type option `%s'\n", arg);
|
||||
@ -318,11 +326,22 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
|
||||
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
|
||||
case OPTION_BOARD:
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
board = zalloc(strlen(arg) + 1);
|
||||
strcpy(board, arg);
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
static const OPTION mips_options[] =
|
||||
{
|
||||
{ {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE},
|
||||
@ -335,7 +354,7 @@ static const OPTION mips_options[] =
|
||||
#ifdef TARGET_SKY
|
||||
#ifdef SKY_FUNIT
|
||||
{ {"float-type", required_argument, NULL, OPTION_FLOAT_TYPE},
|
||||
'\0', "host|target", "Use host (fast) or target (accurate) floating point",
|
||||
'\0', "fast|accurate", "Use fast (host) or accurate (target) floating point",
|
||||
mips_option_handler },
|
||||
#endif
|
||||
{ {"enable-gs", required_argument, NULL, OPTION_GS_ENABLE},
|
||||
@ -349,6 +368,19 @@ static const OPTION mips_options[] =
|
||||
mips_option_handler },
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
|
||||
{ {"board", required_argument, NULL, OPTION_BOARD},
|
||||
'\0', "none" /* rely on compile-time string concatenation for other options */
|
||||
|
||||
/* start-sanitize-tx3904 */
|
||||
#define BOARD_JMR3904 "jmr3904"
|
||||
"|" BOARD_JMR3904
|
||||
#define BOARD_JMR3904_DEBUG "jmr3904debug"
|
||||
"|" BOARD_JMR3904_DEBUG
|
||||
/* end-sanitize-tx3904 */
|
||||
|
||||
, "Customize simulation for a particular board.", mips_option_handler },
|
||||
|
||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -359,6 +391,7 @@ static void
|
||||
interrupt_event (SIM_DESC sd, void *data)
|
||||
{
|
||||
sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
|
||||
address_word cia = CIA_GET (cpu);
|
||||
if (SR & status_IE)
|
||||
{
|
||||
interrupt_pending = 0;
|
||||
@ -397,8 +430,8 @@ sim_open (kind, cb, abfd, argv)
|
||||
/* start-sanitize-sky */
|
||||
|
||||
#if defined(TARGET_SKY) && defined(SKY_FUNIT)
|
||||
/* Set "--float-type host" as the default. */
|
||||
STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_TARGET;
|
||||
/* Set "--float-type fast" as the default. */
|
||||
STATE_FP_TYPE_OPT (sd) &= ~STATE_FP_TYPE_OPT_ACCURATE;
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
|
||||
@ -413,33 +446,6 @@ sim_open (kind, cb, abfd, argv)
|
||||
return 0;
|
||||
sim_add_option_table (sd, NULL, mips_options);
|
||||
|
||||
/* Allocate core managed memory */
|
||||
|
||||
/* the monitor */
|
||||
sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
|
||||
/* For compatibility with the old code - under this (at level one)
|
||||
are the kernel spaces K0 & K1. Both of these map to a single
|
||||
smaller sub region */
|
||||
sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
|
||||
/* start-sanitize-sky */
|
||||
#ifndef TARGET_SKY
|
||||
/* end-sanitize-sky */
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
|
||||
K1BASE, K0SIZE,
|
||||
MEM_SIZE, /* actual size */
|
||||
K0BASE);
|
||||
/* start-sanitize-sky */
|
||||
#else
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
|
||||
K1BASE, K0SIZE,
|
||||
MEM_SIZE, /* actual size */
|
||||
K0BASE,
|
||||
0); /* add alias at 0x0000 */
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
|
||||
device_init(sd);
|
||||
|
||||
/* getopt will print the error message so we just have to exit if this fails.
|
||||
FIXME: Hmmm... in the case of gdb we need getopt to call
|
||||
print_filtered. */
|
||||
@ -451,6 +457,99 @@ sim_open (kind, cb, abfd, argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* handle board-specific memory maps */
|
||||
if (board == NULL)
|
||||
{
|
||||
/* Allocate core managed memory */
|
||||
|
||||
/* the monitor */
|
||||
sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
|
||||
/* For compatibility with the old code - under this (at level one)
|
||||
are the kernel spaces K0 & K1. Both of these map to a single
|
||||
smaller sub region */
|
||||
sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
|
||||
/* start-sanitize-sky */
|
||||
#ifndef TARGET_SKY
|
||||
/* end-sanitize-sky */
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
|
||||
K1BASE, K0SIZE,
|
||||
MEM_SIZE, /* actual size */
|
||||
K0BASE);
|
||||
/* start-sanitize-sky */
|
||||
#else
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x,0x%0x",
|
||||
K1BASE, K0SIZE,
|
||||
MEM_SIZE, /* actual size */
|
||||
K0BASE,
|
||||
0); /* add alias at 0x0000 */
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
|
||||
device_init(sd);
|
||||
}
|
||||
|
||||
/* start-sanitize-tx3904 */
|
||||
else if(! strcmp(board, BOARD_JMR3904) ||
|
||||
(! strcmp(board, BOARD_JMR3904_DEBUG)))
|
||||
{
|
||||
/* match VIRTUAL memory layout of JMR-TX3904 board */
|
||||
|
||||
/* --- memory --- */
|
||||
|
||||
/* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
|
||||
0x9FC00000,
|
||||
4 * 1024 * 1024, /* 4 MB */
|
||||
0xBFC00000);
|
||||
|
||||
/* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
|
||||
0x80000000,
|
||||
4 * 1024 * 1024, /* 4 MB */
|
||||
0xA0000000);
|
||||
|
||||
/* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
|
||||
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
|
||||
0x88000000,
|
||||
32 * 1024 * 1024, /* 32 MB */
|
||||
0xA8000000);
|
||||
|
||||
/* --- simulated devices --- */
|
||||
sim_hw_parse (sd, "/tx3904irc@0xffffc00/reg 0xffffc000 0x20");
|
||||
sim_hw_parse (sd, "/tx3904cpu");
|
||||
|
||||
/* -- device connections --- */
|
||||
sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu");
|
||||
|
||||
if(! strcmp(board, BOARD_JMR3904_DEBUG))
|
||||
{
|
||||
/* -- DEBUG: glue interrupt generators --- */
|
||||
sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
|
||||
sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
|
||||
}
|
||||
|
||||
device_init(sd);
|
||||
}
|
||||
/* end-sanitize-tx3904 */
|
||||
|
||||
|
||||
/* check for/establish the a reference program image */
|
||||
if (sim_analyze_program (sd,
|
||||
(STATE_PROG_ARGV (sd) != NULL
|
||||
@ -1275,7 +1374,7 @@ sim_monitor (SIM_DESC sd,
|
||||
int width = 0, trunc = 0, haddot = 0, longlong = 0;
|
||||
while (sim_read (sd, s++, &c, 1) && c != '\0')
|
||||
{
|
||||
if (strchr ("dobxXulscefg%", s))
|
||||
if (strchr ("dobxXulscefg%", c))
|
||||
break;
|
||||
else if (c == '-')
|
||||
fmt = FMT_LJUST;
|
||||
@ -1622,7 +1721,7 @@ ColdReset (SIM_DESC sd)
|
||||
{
|
||||
sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
|
||||
/* RESET: Fixed PC address: */
|
||||
PC = UNSIGNED64 (0xFFFFFFFFBFC00000);
|
||||
PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000);
|
||||
/* The reset vector address is in the unmapped, uncached memory space. */
|
||||
|
||||
SR &= ~(status_SR | status_TS | status_RP);
|
||||
@ -1760,8 +1859,8 @@ signal_exception (SIM_DESC sd,
|
||||
instruction = va_arg(ap,unsigned int);
|
||||
va_end(ap);
|
||||
/* Check for our special terminating BREAK: */
|
||||
if ((instruction & HALT_INSTRUCTION_MASK)
|
||||
== (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK))
|
||||
if ((instruction & HALT_INSTRUCTION_MASK) == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK) ||
|
||||
(instruction & HALT_INSTRUCTION_MASK) == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK))
|
||||
{
|
||||
sim_engine_halt (SD, CPU, NULL, cia,
|
||||
sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
|
||||
@ -1781,6 +1880,28 @@ signal_exception (SIM_DESC sd,
|
||||
/* TODO: If not simulating exceptions then stop the simulator
|
||||
execution. At the moment we always stop the simulation. */
|
||||
|
||||
#ifdef SUBTARGET_R3900
|
||||
/* update interrupt-related registers */
|
||||
|
||||
/* insert exception code in bits 6:2 */
|
||||
CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2);
|
||||
/* shift IE/KU history bits left */
|
||||
SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2);
|
||||
|
||||
if (STATE & simDELAYSLOT)
|
||||
{
|
||||
STATE &= ~simDELAYSLOT;
|
||||
CAUSE |= cause_BD;
|
||||
EPC = (cia - 4); /* reference the branch instruction */
|
||||
}
|
||||
else
|
||||
EPC = cia;
|
||||
|
||||
if (SR & status_BEV)
|
||||
PC = (signed)0xBFC00000 + 0x180;
|
||||
else
|
||||
PC = (signed)0x80000000 + 0x080;
|
||||
#else
|
||||
/* See figure 5-17 for an outline of the code below */
|
||||
if (! (SR & status_EXL))
|
||||
{
|
||||
@ -1804,10 +1925,12 @@ signal_exception (SIM_DESC sd,
|
||||
SR |= status_EXL;
|
||||
/* Store exception code into current exception id variable (used
|
||||
by exit code): */
|
||||
|
||||
if (SR & status_BEV)
|
||||
PC = (signed)0xBFC00200 + 0x180;
|
||||
else
|
||||
PC = (signed)0x80000000 + 0x180;
|
||||
#endif
|
||||
|
||||
switch ((CAUSE >> 2) & 0x1F)
|
||||
{
|
||||
@ -1815,7 +1938,15 @@ signal_exception (SIM_DESC sd,
|
||||
/* Interrupts arrive during event processing, no need to
|
||||
restart */
|
||||
return;
|
||||
|
||||
|
||||
case NMIReset:
|
||||
/* Ditto */
|
||||
#ifdef SUBTARGET_3900
|
||||
/* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
|
||||
PC = (signed)0xBFC00000;
|
||||
#endif SUBTARGET_3900
|
||||
return;
|
||||
|
||||
case TLBModification:
|
||||
case TLBLoad:
|
||||
case TLBStore:
|
||||
@ -3304,6 +3435,14 @@ decode_coproc (SIM_DESC sd,
|
||||
else if (code == 0x10 && (instruction & 0x3f) == 0x10)
|
||||
{
|
||||
/* RFE */
|
||||
#ifdef SUBTARGET_R3900
|
||||
/* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
|
||||
|
||||
/* shift IE/KU history bits right */
|
||||
SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0);
|
||||
|
||||
/* TODO: CACHE register */
|
||||
#endif /* SUBTARGET_R3900 */
|
||||
}
|
||||
else if (code == 0x10 && (instruction & 0x3f) == 0x1F)
|
||||
{
|
||||
|
@ -124,6 +124,17 @@
|
||||
}
|
||||
|
||||
:function:::int:check_mt_hilo:hilo_history *history
|
||||
*mipsI,mipsII,mipsIII,mipsIV:
|
||||
*vr5000:
|
||||
// start-sanitize-vr4320
|
||||
*vr4320:
|
||||
// end-sanitize-vr4320
|
||||
// start-sanitize-vr5400
|
||||
*vr5400:
|
||||
// end-sanitize-vr5400
|
||||
// start-sanitize-r5900
|
||||
*r5900:
|
||||
// end-sanitize-r5900
|
||||
{
|
||||
signed64 time = sim_events_time (SD);
|
||||
int ok = check_mf_cycles (SD_, history, time, "MT");
|
||||
@ -132,6 +143,18 @@
|
||||
return ok;
|
||||
}
|
||||
|
||||
:function:::int:check_mt_hilo:hilo_history *history
|
||||
*r3900:
|
||||
// start-sanitize-tx19
|
||||
*tx19:
|
||||
// end-sanitize-tx19
|
||||
{
|
||||
signed64 time = sim_events_time (SD);
|
||||
history->mt.timestamp = time;
|
||||
history->mt.cia = CIA;
|
||||
return 1;
|
||||
}
|
||||
|
||||
:function:::int:check_mf_hilo:hilo_history *history, hilo_history *peer
|
||||
{
|
||||
signed64 time = sim_events_time (SD);
|
||||
@ -5351,6 +5374,7 @@
|
||||
010000,00000,5.RT,5.RD,00000,6.REGX:COP0:32::MFC0
|
||||
"mfc0 r<RT>, r<RD> # <REGX>"
|
||||
*mipsI,mipsII,mipsIII,mipsIV:
|
||||
*r3900:
|
||||
*vr5000:
|
||||
// start-sanitize-vr4320
|
||||
*vr4320:
|
||||
@ -5389,6 +5413,28 @@
|
||||
}
|
||||
|
||||
|
||||
010000,10000,000000000000000,010000:COP0:32::RFE
|
||||
"rfe"
|
||||
*mipsI,mipsII,mipsIII,mipsIV:
|
||||
// start-sanitize-tx19
|
||||
*tx19:
|
||||
// end-sanitize-tx19
|
||||
*r3900:
|
||||
// start-sanitize-vr4320
|
||||
*vr4320:
|
||||
// end-sanitize-vr4320
|
||||
*vr5000:
|
||||
// start-sanitize-vr5400
|
||||
*vr5400:
|
||||
// end-sanitize-vr5400
|
||||
// start-sanitize-r5900
|
||||
*r5900:
|
||||
// end-sanitize-r5900
|
||||
{
|
||||
DecodeCoproc (instruction_0);
|
||||
}
|
||||
|
||||
|
||||
010000,10000,000000000000000,001000:COP0:32::TLBP
|
||||
"tlbp"
|
||||
*mipsI,mipsII,mipsIII,mipsIV:
|
||||
|
@ -561,7 +561,6 @@ struct _sim_cpu {
|
||||
/* start-sanitize-sky */
|
||||
#ifdef TARGET_SKY
|
||||
#ifndef TM_TXVU_H
|
||||
|
||||
/* Number of machine registers */
|
||||
#define NUM_VU_REGS 153
|
||||
#define NUM_VU_INTEGER_REGS 16
|
||||
@ -574,7 +573,8 @@ struct _sim_cpu {
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS (NUM_R5900_REGS + 2*(NUM_VU_REGS) + 2*(NUM_VIF_REGS))
|
||||
#endif /* no tm-txvu.h */
|
||||
#endif
|
||||
#endif /* TARGET_SKY */
|
||||
/* end-sanitize-sky */
|
||||
|
||||
enum float_operation
|
||||
/* start-sanitize-sky */
|
||||
@ -665,7 +665,6 @@ enum float_operation
|
||||
hilo_history lo_history;
|
||||
#define LOHISTORY (&(CPU)->lo_history)
|
||||
|
||||
|
||||
/* start-sanitize-r5900 */
|
||||
sim_r5900_cpu r5900;
|
||||
|
||||
@ -675,7 +674,13 @@ enum float_operation
|
||||
/* The MDMX ISA has a very very large accumulator */
|
||||
unsigned8 acc[3 * 8];
|
||||
/* end-sanitize-vr5400 */
|
||||
/* start-sanitize-sky */
|
||||
|
||||
#ifdef TARGET_SKY
|
||||
/* Device on which instruction issue last occured. */
|
||||
char cur_device;
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
sim_cpu_base base;
|
||||
};
|
||||
|
||||
@ -709,7 +714,7 @@ struct sim_state {
|
||||
/* Record of option for floating point implementation type. */
|
||||
int fp_type_opt;
|
||||
#define STATE_FP_TYPE_OPT(sd) ((sd)->fp_type_opt)
|
||||
#define STATE_FP_TYPE_OPT_TARGET 0x80000000
|
||||
#define STATE_FP_TYPE_OPT_ACCURATE 0x80000000
|
||||
#endif
|
||||
#endif
|
||||
/* end-sanitize-sky */
|
||||
@ -746,7 +751,29 @@ struct sim_state {
|
||||
#define status_CU2 (1 << 30) /* COP2 usable */
|
||||
/* end-sanitize-r5900 */
|
||||
|
||||
#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
|
||||
/* Specializations for TX39 family */
|
||||
#define status_IEc (1 << 0) /* Interrupt enable (current) */
|
||||
#define status_KUc (1 << 1) /* Kernel/User mode */
|
||||
#define status_IEp (1 << 2) /* Interrupt enable (previous) */
|
||||
#define status_KUp (1 << 3) /* Kernel/User mode */
|
||||
#define status_IEo (1 << 4) /* Interrupt enable (old) */
|
||||
#define status_KUo (1 << 5) /* Kernel/User mode */
|
||||
#define status_IM_mask (0xff) /* Interrupt mask */
|
||||
#define status_IM_shift (8)
|
||||
#define status_NMI (1 << 20) /* NMI */
|
||||
#define status_NMI (1 << 20) /* NMI */
|
||||
|
||||
#define cause_EXC_mask (0x1f) /* Exception code */
|
||||
#define cause_EXC_shift (2)
|
||||
#define cause_SW0 (1 << 8) /* Software interrupt 0 */
|
||||
#define cause_SW1 (1 << 9) /* Software interrupt 1 */
|
||||
#define cause_IP_mask (0x3f) /* Interrupt pending field */
|
||||
#define cause_IP_shift (10)
|
||||
#define cause_CE_mask (0x3) /* Coprocessor error */
|
||||
#define cause_CE_shift (28)
|
||||
|
||||
#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
|
||||
|
||||
|
||||
/* NOTE: We keep the following status flags as bit values (1 for true,
|
||||
0 for false). This allows them to be used in binary boolean
|
||||
@ -754,7 +781,11 @@ struct sim_state {
|
||||
value is. */
|
||||
|
||||
/* UserMode */
|
||||
#ifdef SUBTARGET_R3900
|
||||
#define UserMode ((SR & status_KUc) ? 1 : 0)
|
||||
#else
|
||||
#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
|
||||
#endif /* SUBTARGET_R3900 */
|
||||
|
||||
/* BigEndianMem */
|
||||
/* Hardware configuration. Affects endianness of LoadMemory and
|
||||
@ -799,6 +830,8 @@ struct sim_state {
|
||||
#define FPE (15)
|
||||
#define DebugBreakPoint (16)
|
||||
#define Watch (23)
|
||||
#define NMIReset (31)
|
||||
|
||||
|
||||
/* The following exception code is actually private to the simulator
|
||||
world. It is *NOT* a processor feature, and is used to signal
|
||||
@ -807,7 +840,7 @@ struct sim_state {
|
||||
|
||||
void signal_exception (SIM_DESC sd, sim_cpu *cpu, address_word cia, int exception, ...);
|
||||
#define SignalException(exc,instruction) signal_exception (SD, CPU, cia, (exc), (instruction))
|
||||
#define SignalExceptionInterrupt() signal_exception (SD, CPU, NULL_CIA, Interrupt)
|
||||
#define SignalExceptionInterrupt() signal_exception (SD, CPU, cia, Interrupt)
|
||||
#define SignalExceptionInstructionFetch() signal_exception (SD, CPU, cia, InstructionFetch)
|
||||
#define SignalExceptionAddressStore() signal_exception (SD, CPU, cia, AddressStore)
|
||||
#define SignalExceptionAddressLoad() signal_exception (SD, CPU, cia, AddressLoad)
|
||||
@ -815,7 +848,7 @@ void signal_exception (SIM_DESC sd, sim_cpu *cpu, address_word cia, int exceptio
|
||||
#define SignalExceptionFPE() signal_exception (SD, CPU, cia, FPE)
|
||||
#define SignalExceptionIntegerOverflow() signal_exception (SD, CPU, cia, IntegerOverflow)
|
||||
#define SignalExceptionCoProcessorUnusable() signal_exception (SD, CPU, cia, CoProcessorUnusable)
|
||||
|
||||
#define SignalExceptionNMIReset() signal_exception (SD, CPU, cia, NMIReset)
|
||||
|
||||
/* Co-processor accesses */
|
||||
|
||||
@ -931,6 +964,38 @@ INLINE_SIM_MAIN (void) pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_
|
||||
char* pr_addr PARAMS ((SIM_ADDR addr));
|
||||
char* pr_uword64 PARAMS ((uword64 addr));
|
||||
|
||||
/* start-sanitize-sky */
|
||||
#ifdef TARGET_SKY
|
||||
#ifdef SIM_ENGINE_HALT_HOOK
|
||||
#undef SIM_ENGINE_HALT_HOOK
|
||||
#endif
|
||||
|
||||
void sky_sim_engine_halt PARAMS ((SIM_DESC sd, sim_cpu *last, sim_cia cia));
|
||||
#define SIM_ENGINE_HALT_HOOK(sd, last, cia) sky_sim_engine_halt(sd, last, cia);
|
||||
|
||||
#ifndef TM_TXVU_H /* In case GDB hasn't been configured yet */
|
||||
enum txvu_cpu_context
|
||||
{
|
||||
TXVU_CPU_AUTO = -1, /* context-sensitive context */
|
||||
TXVU_CPU_MASTER, /* R5900 core */
|
||||
TXVU_CPU_VU0, /* Vector units */
|
||||
TXVU_CPU_VU1,
|
||||
TXVU_CPU_VIF0, /* FIFO's */
|
||||
TXVU_CPU_VIF1,
|
||||
TXVU_CPU_LAST /* Count of context types */
|
||||
};
|
||||
|
||||
/* memory segment for communication with GDB */
|
||||
#define GDB_COMM_AREA 0x21010000
|
||||
#define GDB_COMM_SIZE 0x4000
|
||||
|
||||
/* Memory address containing last device to execute */
|
||||
#define LAST_DEVICE GDB_COMM_AREA
|
||||
|
||||
#define BREAK_MASK 0x02 /* Breakpoint bit is #57 */
|
||||
#endif /* !TM_TXVU_H */
|
||||
#endif /* TARGET_SKY */
|
||||
/* end-sanitize-sky */
|
||||
|
||||
#if H_REVEALS_MODULE_P (SIM_MAIN_INLINE)
|
||||
#include "sim-main.c"
|
||||
|
Loading…
Reference in New Issue
Block a user