* 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:
Frank Ch. Eigler 1998-05-18 15:55:05 +00:00
parent d9c2c0c569
commit 3fa454e95f
9 changed files with 1271 additions and 192 deletions

View File

@ -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"

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
View 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, &reg))
hw_abort (me, "\"reg\" property must contain one addr/size entry");
hw_unit_address_to_attach_address (hw_parent (me),
&reg.address,
&attach_space,
&attach_address,
me);
hw_unit_size_to_attach_size (hw_parent (me),
&reg.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 },
};

View File

@ -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)
{

View File

@ -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:

View File

@ -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"