mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
interpro: various improvements
Many changes, most notable end result is the ability to boot the "blue screen" rebuild floppy, and nearly booting CLIX (hangs trying to mount the filesystems). Summary of changes: * added a softlist * refactored cpu/mmu memory access * added alignment faults * implemented most c400 instructions * fixed wait instruction * corrections to interpro driver * removed broken forced interrupt handling * added support for dma virtual addressing
This commit is contained in:
parent
2bd73cc977
commit
421d6dd2cc
248
hash/interpro.xml
Normal file
248
hash/interpro.xml
Normal file
@ -0,0 +1,248 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
|
||||
<softwarelist name="interpro" description="Intergraph InterPro software">
|
||||
|
||||
<!--
|
||||
Intergraph distributed all InterPro software, including that from 3rd
|
||||
parties, on CD-ROM disc sets. A base 4-CD set of system software
|
||||
contains the CLIX operating system and other programs such as editors,
|
||||
compilers and graphics tools. Additional sets were typically organised
|
||||
according to lines of business such as "Plant and Building Solutions",
|
||||
"Architecture, Engineering and Construction", etc., and contained
|
||||
application software aimed at companies in those industries.
|
||||
|
||||
All CD-ROM software is installed using the DELTOOLS package, and the
|
||||
"newprod" utility in particular. In some cases, valid load keys (serial
|
||||
numbers) are required to decrypt the delivered software and enable it
|
||||
to be installed. In addition, some software has other runtime licensing
|
||||
which must be configured before the programs will operate.
|
||||
|
||||
Finally, there are two sets of floppy disks that can be created via the
|
||||
REBUILD and DIAG products. The REBUILD floppy disks are used to boot the
|
||||
initial blue screen utility which allows configuring the system and
|
||||
preparing a hard disk for installation, and to initiate the installation
|
||||
process. The DIAG disks are used to launch the full suite of system
|
||||
hardware diagnostic routines, via the FDMDISK monitor.
|
||||
-->
|
||||
|
||||
<software name="iss">
|
||||
<description>Intergraph System Software</description>
|
||||
<year>1999</year>
|
||||
<publisher>Intergraph</publisher>
|
||||
|
||||
<info name="date" value="05-MAY-1999"/>
|
||||
|
||||
<!-- System Software Disc I#05-MAY-1999#050599#FMDA0320N -->
|
||||
<part name="disc1" interface="cdrom">
|
||||
<feature name="part_id" value="System Software Disc I" />
|
||||
<diskarea name="cdrom">
|
||||
<disk name="iss_050599_1" sha1="5d556b4df2dccdc681095fedcf836a5b0a7782a0" writeable="no" />
|
||||
</diskarea>
|
||||
</part>
|
||||
|
||||
<!-- System Software Disc II#05-MAY-1999#050599#FMDA0320N -->
|
||||
<part name="disc2" interface="cdrom">
|
||||
<feature name="part_id" value="System Software Disc II" />
|
||||
<diskarea name="cdrom">
|
||||
<disk name="iss_050599_2" sha1="3813db83871668eed97b43f2384b7e95a649598a" writeable="no" />
|
||||
</diskarea>
|
||||
</part>
|
||||
|
||||
<!-- System Software Disc III#05-MAY-1999#050599#FMDA0320N -->
|
||||
<part name="disc3" interface="cdrom">
|
||||
<feature name="part_id" value="System Software Disc III" />
|
||||
<diskarea name="cdrom">
|
||||
<disk name="iss_050599_3" sha1="c8b08cd45ef1614b3db1cd0fb8e6539e3bcc5725" writeable="no" />
|
||||
</diskarea>
|
||||
</part>
|
||||
|
||||
<!-- System Software Disc IV#05-MAY-1999#050599#FMDA0170B -->
|
||||
<part name="disc4" interface="cdrom">
|
||||
<feature name="part_id" value="System Software Disc IV" />
|
||||
<diskarea name="cdrom">
|
||||
<disk name="iss_050599_4" sha1="2681b4cd8d355b6abfcfebb1b40a6d8a5ef37fe9" writeable="no" />
|
||||
</diskarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<!--
|
||||
The REBUILD product allows a set of system rebuild floppy disks to be
|
||||
created from source binary data. When using the software, the user is
|
||||
prompted to select from the following options, causing different
|
||||
combinations of "boot" and "root" source data to be written to disk.
|
||||
|
||||
1) 125/32C/220/225 Systems (80186 IOP and ROP Graphics)
|
||||
2) 200/240 Systems (80186 IOP and optional IFB Graphics)
|
||||
3) 300/400/3000/4000 Systems (80386 IOP and optional IFB Graphics)
|
||||
4) 2000 Systems (C300 Clipper IOP and optional MMG Graphics)
|
||||
5) 6000 Systems (C300 Clipper IOP and optional EDGE Graphics)
|
||||
6) 2400 Systems (C4T Clipper GTPLUS Graphics)
|
||||
7) 6440/6480 Systems (C4T Clipper EDGE Graphics)
|
||||
8) 6400/6450 Systems (C4T Clipper GTII Graphics)
|
||||
9) 6640/6680 Systems (C400 Clipper EDGE graphics)
|
||||
10) 6600 Servers (C400 Clipper Servers)
|
||||
11) 6700/6800 Servers (C400I Clipper Server)
|
||||
12) 6740/6780/6840/6880 Systems (C400I Clipper EDGE graphics)
|
||||
13) 6750/6850 Systems (C400I Clipper GT graphics)
|
||||
14) 2500/2700/2800 Systems (C400I Clipper Servers)
|
||||
15) 2530/2730/2830 Systems (C400I Clipper GT graphics)
|
||||
|
||||
Ignoring the first 3 options which are unsupported in MAME at this point,
|
||||
the remaining systems use one of 3 possible boot images: CLIPPER, C400 or
|
||||
C400E.
|
||||
-->
|
||||
<software name="rebuild">
|
||||
<description>Rebuild Floppies</description>
|
||||
<year>1998</year>
|
||||
<publisher>Intergraph</publisher>
|
||||
|
||||
<info name="product_id" value="SS01003AA-0706A" />
|
||||
<info name="product_title" value="Rebuild Floppies" />
|
||||
<info name="product_date" value="10-JAN-1998" />
|
||||
<info name="product_name" value="REBUILD" />
|
||||
<info name="product_version" value="07.06.00.09" />
|
||||
<info name="product_class" value="System Nucleus" />
|
||||
|
||||
<!-- rebuild boot floppies for C300, C400E and C400 respectively -->
|
||||
<part name="boot_clipper" interface="floppy_3_5">
|
||||
<feature name="part_id" value="C300 Rebuild Boot Floppy" />
|
||||
<feature name="compatibility" value="2000,2020,6000,6040" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="clipper.img" size="1474560" offset="0" crc="f182eb64" sha1="0e104e4db9f666ccc0d618b402666d90f025a3b4" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="boot_c400e" interface="floppy_3_5">
|
||||
<feature name="part_id" value="C400E Rebuild Boot Floppy" />
|
||||
<feature name="compatibility" value="6600,6640,6680" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="c400e.img" size="1474560" offset="0" status="nodump" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="boot_c400" interface="floppy_3_5">
|
||||
<feature name="part_id" value="C400 Rebuild Boot Floppy" />
|
||||
<feature name="compatibility" value="2400,2430,6440,6480,6400,6450,6750,6850,6740,6780,6840,6880,6700,6800,2500,2700,2800,2530,2730,2830" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="c400.img" size="1474560" offset="0" crc="7e739d42" sha1="ca3f2244d1167553482cd73c59cea74e181f37c7" />
|
||||
</dataarea>
|
||||
</part>
|
||||
|
||||
<!-- rebuild root floppies for 2000 and 2020 systems -->
|
||||
<part name="20x0_root2" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #2/4" />
|
||||
<feature name="compatibility" value="2000,2020"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="20x0_root2.img" size="1474560" offset="0" crc="66ee95eb" sha1="9b6e316f4c038ef471a84a82e396376b361c970a" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="20x0_root3" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #3/4" />
|
||||
<feature name="compatibility" value="2000,2020"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="20x0_root3.img" size="1474560" offset="0" crc="de490556" sha1="882c46e193a5467b66ffe2cd0ac8518df087d112" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="20x0_root4" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #4/4" />
|
||||
<feature name="compatibility" value="2000,2020"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="20x0_root4.img" size="1474560" offset="0" crc="2b0e3f01" sha1="e191057117aee120301143f25d5446f55789009c" />
|
||||
</dataarea>
|
||||
</part>
|
||||
|
||||
<!-- rebuild root floppies for 2400 and 2430 systems -->
|
||||
<part name="24x0_root2" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #2/4" />
|
||||
<feature name="compatibility" value="2400,2430"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="24x0_root2.img" size="1474560" offset="0" crc="f6a7ba45" sha1="c810cec284f61921ab1ffffe5e71b291d0a295a6" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="24x0_root3" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #3/4" />
|
||||
<feature name="compatibility" value="2400,2430"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="24x0_root3.img" size="1474560" offset="0" crc="1659399b" sha1="9ad4b4492654e76f4d5284af15b0235553b63f46" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="24x0_root4" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Rebuild Floppy #4/4" />
|
||||
<feature name="compatibility" value="2400,2430"/>
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="24x0_root4.img" size="1474560" offset="0" crc="594b2c9c" sha1="b69812399b7b32abbe81d00945b0d96a27b04c19" />
|
||||
</dataarea>
|
||||
</part>
|
||||
|
||||
<!-- TODO: root floppy images for all other systems -->
|
||||
</software>
|
||||
|
||||
<!--
|
||||
The DIAG product allows a set of system hardware diagnostic floppy disks
|
||||
to be created from source binary data. When using the software, the user is
|
||||
prompted to select from the following options, causing different
|
||||
combinations of source data to be written to disk.
|
||||
|
||||
1) amethyst - 32C/100/200
|
||||
2) emerald - 6000/6100/6200/6500/6600
|
||||
3) topaz - 300/3000/4000/5000
|
||||
4) turquoise - 2000
|
||||
5) IOP based 6500 ( Manufacturing Test Only )
|
||||
6) sapphire - 2400/2500/6400/2700/6700/6800/2800
|
||||
|
||||
Currently only the Turquoise and Sapphire systems are supported. Turquoise
|
||||
diagnostics consists of a single floppy, while Sapphire systems have a 4
|
||||
disk set. The first Sapphire disk contains a flash ROM image, with the
|
||||
remaining 3 disks holding the diagnostic utilities.
|
||||
-->
|
||||
<software name="diag">
|
||||
<description>Diagnostic Floppies</description>
|
||||
<year>1994</year>
|
||||
<publisher>Intergraph</publisher>
|
||||
|
||||
<info name="product_id" value="SS01086AA-0703A" />
|
||||
<info name="product_title" value="Workstation/Server Diagnostics" />
|
||||
<info name="product_date" value="30-MAR-1994" />
|
||||
<info name="product_name" value="DIAG" />
|
||||
<info name="product_version" value="07.03.15.00" />
|
||||
<info name="product_class" value="Hardware Diagnostics" />
|
||||
|
||||
<!-- Turquoise systems have a single diagnostic floppy -->
|
||||
<part name="turq" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Turqouise Diagnostic Floppy" />
|
||||
<feature name="compatibility" value="2000,2020" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="turq.img" size="1474560" offset="0" crc="70e2980a" sha1="3fa2f0c54ef27e16e579563db9cd70b68e11e403" />
|
||||
</dataarea>
|
||||
</part>
|
||||
|
||||
<!-- Sapphire systems have a four-disk set of diagnostic floppies -->
|
||||
<part name="sapphire" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Sapphire Flash ROM Floppy" />
|
||||
<feature name="compatibility" value="2400,2430,6440,6480,6400,6450,6750,6850,6740,6780,6840,6880,6700,6800,2500,2700,2800,2530,2730,2830" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="sapphire.img" size="1474560" offset="0" crc="1721d7d1" sha1="fc25109c4c7b2d94d0fd55e7cebaa03e7177ad5e" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="sapphire1" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Sapphire Diagnostic Floppy #1/3" />
|
||||
<feature name="compatibility" value="2400,2430,6440,6480,6400,6450,6750,6850,6740,6780,6840,6880,6700,6800,2500,2700,2800,2530,2730,2830" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="sapphire1.img" size="1474560" offset="0" crc="e0db6354" sha1="75fb42ae87d78daaeac30390bef335419425da09" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="sapphire2" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Sapphire Diagnostic Floppy #2/3" />
|
||||
<feature name="compatibility" value="2400,2430,6440,6480,6400,6450,6750,6850,6740,6780,6840,6880,6700,6800,2500,2700,2800,2530,2730,2830" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="sapphire2.img" size="1474560" offset="0" crc="955065d1" sha1="6df92a7986a83d31e91189c8097b9b4f8d02960f" />
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="sapphire3" interface="floppy_3_5">
|
||||
<feature name="part_id" value="Sapphire Diagnostic Floppy #3/3" />
|
||||
<feature name="compatibility" value="2400,2430,6440,6480,6400,6450,6750,6850,6740,6780,6840,6880,6700,6800,2500,2700,2800,2530,2730,2830" />
|
||||
<dataarea name="flop" size="1474560">
|
||||
<rom name="sapphire3.img" size="1474560" offset="0" crc="2f14fcb2" sha1="2d33087273c14597fc065e13d05e1ce9d1841704" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
</softwarelist>
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
* TODO:
|
||||
* - save/restore state
|
||||
* - unimplemented C400 instructions
|
||||
* - unimplemented C400 instructions (cdb, cnvx[ds]w, loadts, waitd)
|
||||
* - correct boot logic
|
||||
* - condition codes for multiply instructions
|
||||
* - instruction timing
|
||||
@ -57,25 +57,29 @@ DEFINE_DEVICE_TYPE(CLIPPER_C400, clipper_c400_device, "clipper_c400", "C400 CLIP
|
||||
|
||||
clipper_c100_device::clipper_c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: clipper_device(mconfig, CLIPPER_C100, tag, owner, clock, ENDIANNESS_LITTLE, 0)
|
||||
, m_icammu(*this, "^cammu_i")
|
||||
, m_dcammu(*this, "^cammu_d")
|
||||
{
|
||||
}
|
||||
|
||||
clipper_c300_device::clipper_c300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: clipper_device(mconfig, CLIPPER_C300, tag, owner, clock, ENDIANNESS_LITTLE, 0)
|
||||
, m_icammu(*this, "^cammu_i")
|
||||
, m_dcammu(*this, "^cammu_d")
|
||||
{
|
||||
}
|
||||
|
||||
clipper_c400_device::clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: clipper_device(mconfig, CLIPPER_C400, tag, owner, clock, ENDIANNESS_LITTLE, SSW_ID_C400R4)
|
||||
, m_cammu(*this, "^cammu")
|
||||
{
|
||||
}
|
||||
|
||||
clipper_device::clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const endianness_t endianness, const u32 cpuid)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_insn_config("insn", endianness, 32, 32, 0)
|
||||
, m_data_config("data", endianness, 32, 32, 0)
|
||||
, m_insn(nullptr)
|
||||
, m_data(nullptr)
|
||||
, m_main_config("main", endianness, 32, 32, 0)
|
||||
, m_io_config("io", endianness, 32, 32, 0)
|
||||
, m_boot_config("boot", endianness, 32, 32, 0)
|
||||
, m_icount(0)
|
||||
, m_psw(endianness == ENDIANNESS_BIG ? PSW_BIG : 0)
|
||||
, m_ssw(cpuid)
|
||||
@ -110,9 +114,12 @@ inline u64 rotr64(u64 x, u8 shift)
|
||||
|
||||
void clipper_device::device_start()
|
||||
{
|
||||
// get our address spaces
|
||||
m_insn = &space(AS_PROGRAM);
|
||||
m_data = &space(AS_DATA);
|
||||
// map spaces to system tags
|
||||
std::vector<address_space *> spaces = { &space(0), &space(0), &space(0), &space(0), &space(1), &space(2), nullptr, nullptr };
|
||||
|
||||
// configure the cammu address spaces
|
||||
get_icammu().set_spaces(spaces);
|
||||
get_dcammu().set_spaces(spaces);
|
||||
|
||||
// set our instruction counter
|
||||
m_icountptr = &m_icount;
|
||||
@ -156,6 +163,8 @@ void clipper_device::device_reset()
|
||||
* ssw: EI, TP, M, U, K, KU, UU, P cleared, ID set from hardware, others undefined
|
||||
*/
|
||||
|
||||
m_wait = false;
|
||||
|
||||
// clear the psw and ssw
|
||||
set_psw(0);
|
||||
set_ssw(0);
|
||||
@ -205,11 +214,15 @@ void clipper_device::execute_run()
|
||||
// acknowledge interrupt
|
||||
standard_irq_callback(INPUT_LINE_IRQ0);
|
||||
|
||||
LOGMASKED(LOG_EXCEPTION, "transferring control to ivec 0x%02x\n", m_ivec);
|
||||
m_ip = intrap(EXCEPTION_INTERRUPT_BASE + m_ivec * 8, m_ip);
|
||||
|
||||
LOGMASKED(LOG_EXCEPTION, "transferring control to ivec 0x%02x address 0x%08x\n", m_ivec, m_ip);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wait)
|
||||
m_icount = 0;
|
||||
|
||||
while (m_icount > 0)
|
||||
{
|
||||
debugger_instruction_hook(this, m_ip);
|
||||
@ -282,6 +295,9 @@ void clipper_device::execute_run()
|
||||
|
||||
void clipper_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
if (state)
|
||||
m_wait = false;
|
||||
|
||||
switch (inputnum)
|
||||
{
|
||||
case INPUT_LINE_IRQ0:
|
||||
@ -294,15 +310,12 @@ void clipper_device::execute_set_input(int inputnum, int state)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The CLIPPER has a true Harvard architecture. In the InterPro, these are tied back together
|
||||
* again by the MMU, which then directs the access to one of 3 address spaces: main, i/o or boot.
|
||||
*/
|
||||
device_memory_interface::space_config_vector clipper_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(AS_PROGRAM, &m_insn_config),
|
||||
std::make_pair(AS_DATA, &m_data_config)
|
||||
std::make_pair(0, &m_main_config),
|
||||
std::make_pair(1, &m_io_config),
|
||||
std::make_pair(2, &m_boot_config)
|
||||
};
|
||||
}
|
||||
|
||||
@ -324,17 +337,15 @@ WRITE16_MEMBER(clipper_device::set_exception)
|
||||
*/
|
||||
bool clipper_device::decode_instruction()
|
||||
{
|
||||
// fetch instruction word
|
||||
u16 insn = m_insn->read_word(m_ip + 0);
|
||||
if (m_exception)
|
||||
// fetch and decode the primary parcel
|
||||
if (!get_icammu().fetch<u16>(m_ssw, m_ip + 0, [this](u16 insn) {
|
||||
m_info.opcode = insn >> 8;
|
||||
m_info.subopcode = insn & 0xff;
|
||||
m_info.r1 = (insn & 0x00f0) >> 4;
|
||||
m_info.r2 = insn & 0x000f;
|
||||
}))
|
||||
return false;
|
||||
|
||||
// decode the primary parcel
|
||||
m_info.opcode = insn >> 8;
|
||||
m_info.subopcode = insn & 0xff;
|
||||
m_info.r1 = (insn & 0x00f0) >> 4;
|
||||
m_info.r2 = insn & 0x000f;
|
||||
|
||||
// initialise the other fields
|
||||
m_info.imm = 0;
|
||||
m_info.macro = 0;
|
||||
@ -343,112 +354,93 @@ bool clipper_device::decode_instruction()
|
||||
// default instruction size is 2 bytes
|
||||
int size = 2;
|
||||
|
||||
if ((insn & 0xf800) == 0x3800)
|
||||
if ((m_info.opcode & 0xf8) == 0x38)
|
||||
{
|
||||
// instruction has a 16 bit immediate operand
|
||||
|
||||
// fetch 16 bit immediate and sign extend
|
||||
m_info.imm = (s16)m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<s16>(m_ssw, m_ip + 2, [this](s32 v) { m_info.imm = v; }))
|
||||
return false;
|
||||
size = 4;
|
||||
}
|
||||
else if ((insn & 0xd300) == 0x8300)
|
||||
else if ((m_info.opcode & 0xd3) == 0x83)
|
||||
{
|
||||
// instruction has an immediate operand, either 16 or 32 bit
|
||||
if (insn & 0x0080)
|
||||
if (m_info.subopcode & 0x80)
|
||||
{
|
||||
// fetch 16 bit immediate and sign extend
|
||||
m_info.imm = (s16)m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<s16>(m_ssw, m_ip + 2, [this](s32 v) { m_info.imm = v; }))
|
||||
return false;
|
||||
size = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fetch 32 bit immediate
|
||||
m_info.imm = m_insn->read_dword_unaligned(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u32>(m_ssw, m_ip + 2, [this](u32 v) { m_info.imm = v; }))
|
||||
return false;
|
||||
size = 6;
|
||||
}
|
||||
}
|
||||
else if ((insn & 0xc000) == 0x4000)
|
||||
else if ((m_info.opcode & 0xc0) == 0x40)
|
||||
{
|
||||
// instructions with addresses
|
||||
if (insn & 0x0100)
|
||||
if (m_info.opcode & 0x01)
|
||||
{
|
||||
// instructions with complex modes
|
||||
u16 temp;
|
||||
|
||||
switch (insn & 0x00f0)
|
||||
switch (m_info.subopcode & 0xf0)
|
||||
{
|
||||
case ADDR_MODE_PC32:
|
||||
m_info.address = m_ip + m_insn->read_dword_unaligned(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u32>(m_ssw, m_ip + 2, [this](u32 v) { m_info.address = m_ip + v; }))
|
||||
return false;
|
||||
size = 6;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_ABS32:
|
||||
m_info.address = m_insn->read_dword_unaligned(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u32>(m_ssw, m_ip + 2, [this](u32 v) { m_info.address = v; }))
|
||||
return false;
|
||||
size = 6;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_REL32:
|
||||
m_info.r2 = m_insn->read_word(m_ip + 2) & 0xf;
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u16>(m_ssw, m_ip + 2, [this](u16 v) { m_info.r2 = v & 0xf; }))
|
||||
return false;
|
||||
|
||||
m_info.address = m_r[insn & 0xf] + m_insn->read_dword_unaligned(m_ip + 4);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u32>(m_ssw, m_ip + 4, [this](u32 v) { m_info.address = m_r[m_info.subopcode & 0xf] + v; }))
|
||||
return false;
|
||||
size = 8;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_PC16:
|
||||
m_info.address = m_ip + (s16)m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<s16>(m_ssw, m_ip + 2, [this](s16 v) { m_info.address = m_ip + v; }))
|
||||
return false;
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_REL12:
|
||||
temp = m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<s16>(m_ssw, m_ip + 2, [this](s16 v) {
|
||||
m_info.r2 = v & 0xf;
|
||||
m_info.address = m_r[m_info.subopcode & 0xf] + (v >> 4); }))
|
||||
return false;
|
||||
|
||||
m_info.r2 = temp & 0xf;
|
||||
m_info.address = m_r[insn & 0xf] + ((s16)temp >> 4);
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_ABS16:
|
||||
m_info.address = (s16)m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<s16>(m_ssw, m_ip + 2, [this](s32 v) { m_info.address = v; }))
|
||||
return false;
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_PCX:
|
||||
temp = m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u16>(m_ssw, m_ip + 2, [this](u16 v) {
|
||||
m_info.r2 = v & 0xf;
|
||||
m_info.address = m_ip + m_r[(v >> 4) & 0xf]; }))
|
||||
return false;
|
||||
|
||||
m_info.r2 = temp & 0xf;
|
||||
m_info.address = m_ip + m_r[(temp >> 4) & 0xf];
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case ADDR_MODE_RELX:
|
||||
temp = m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u16>(m_ssw, m_ip + 2, [this](u16 v) {
|
||||
m_info.r2 = v & 0xf;
|
||||
m_info.address = m_r[m_info.subopcode & 0xf] + m_r[(v >> 4) & 0xf]; }))
|
||||
return false;
|
||||
|
||||
m_info.r2 = temp & 0xf;
|
||||
m_info.address = m_r[insn & 0xf] + m_r[(temp >> 4) & 0xf];
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
@ -461,11 +453,10 @@ bool clipper_device::decode_instruction()
|
||||
// relative addressing mode
|
||||
m_info.address = m_r[m_info.r1];
|
||||
}
|
||||
else if ((insn & 0xfd00) == 0xb400)
|
||||
else if ((m_info.opcode & 0xfd) == 0xb4)
|
||||
{
|
||||
// macro instructions
|
||||
m_info.macro = m_insn->read_word(m_ip + 2);
|
||||
if (m_exception)
|
||||
if (!get_icammu().fetch<u16>(m_ssw, m_ip + 2, [this](u16 v) { m_info.macro = v; }))
|
||||
return false;
|
||||
size = 4;
|
||||
}
|
||||
@ -479,9 +470,6 @@ bool clipper_device::decode_instruction()
|
||||
|
||||
void clipper_device::execute_instruction()
|
||||
{
|
||||
// memory fetch temporary
|
||||
u64 temp;
|
||||
|
||||
switch (m_info.opcode)
|
||||
{
|
||||
case 0x00: // noop
|
||||
@ -511,27 +499,25 @@ void clipper_device::execute_instruction()
|
||||
break;
|
||||
case 0x13:
|
||||
// ret: return from subroutine
|
||||
temp = m_data->read_dword(m_r[R2]);
|
||||
if (!m_exception)
|
||||
{
|
||||
m_ip = temp;
|
||||
get_dcammu().load<u32>(m_ssw, m_r[R2], [this](u32 v) {
|
||||
m_ip = v;
|
||||
m_r[R2] += 4;
|
||||
}
|
||||
});
|
||||
// TRAPS: C,U,A,P,R
|
||||
break;
|
||||
case 0x14:
|
||||
// pushw: push word
|
||||
m_data->write_dword(m_r[R1] - 4, m_r[R2]);
|
||||
m_r[R1] -= 4;
|
||||
if (get_dcammu().store<u32>(m_ssw, m_r[R1] - 4, m_r[R2]))
|
||||
m_r[R1] -= 4;
|
||||
// TRAPS: A,P,W
|
||||
break;
|
||||
|
||||
case 0x16:
|
||||
// popw: pop word
|
||||
m_r[R1] += 4;
|
||||
temp = m_data->read_dword(m_r[R1] - 4);
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<u32>(m_ssw, m_r[R1], [this](u32 v) {
|
||||
m_r[R1] += 4;
|
||||
m_r[R2] = v;
|
||||
});
|
||||
// TRAPS: C,U,A,P,R
|
||||
break;
|
||||
|
||||
@ -774,8 +760,7 @@ void clipper_device::execute_instruction()
|
||||
case 0x44:
|
||||
case 0x45:
|
||||
// call: call subroutine
|
||||
m_data->write_dword(m_r[R2] - 4, m_ip);
|
||||
if (!m_exception)
|
||||
if (get_dcammu().store<u32>(m_ssw, m_r[R2] - 4, m_ip))
|
||||
{
|
||||
m_ip = m_info.address;
|
||||
m_r[R2] -= 4;
|
||||
@ -818,9 +803,7 @@ void clipper_device::execute_instruction()
|
||||
case 0x60:
|
||||
case 0x61:
|
||||
// loadw: load word
|
||||
temp = m_data->read_dword(m_info.address);
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<u32>(m_ssw, m_info.address, [this](u32 v) { m_r[R2] = v; });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x62:
|
||||
@ -832,92 +815,77 @@ void clipper_device::execute_instruction()
|
||||
case 0x64:
|
||||
case 0x65:
|
||||
// loads: load single floating
|
||||
temp = m_data->read_dword(m_info.address);
|
||||
if (!m_exception)
|
||||
set_fp(R2, (float32)temp, F_NONE);
|
||||
get_dcammu().load<float32>(m_ssw, m_info.address, [this](float32 v) { set_fp(R2, v, F_NONE); });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x66:
|
||||
case 0x67:
|
||||
// loadd: load double floating
|
||||
temp = m_data->read_qword(m_info.address);
|
||||
if (!m_exception)
|
||||
set_fp(R2, (float64)temp, F_NONE);
|
||||
get_dcammu().load<float64>(m_ssw, m_info.address, [this](float64 v) { set_fp(R2, float64(v), F_NONE); });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x68:
|
||||
case 0x69:
|
||||
// loadb: load byte
|
||||
temp = s64(s8(m_data->read_byte(m_info.address)));
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<s8>(m_ssw, m_info.address, [this](s32 v) { m_r[R2] = v; });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x6a:
|
||||
case 0x6b:
|
||||
// loadbu: load byte unsigned
|
||||
temp = m_data->read_byte(m_info.address);
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<u8>(m_ssw, m_info.address, [this](u32 v) { m_r[R2] = v; });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x6c:
|
||||
case 0x6d:
|
||||
// loadh: load halfword
|
||||
temp = s64(s16(m_data->read_word(m_info.address)));
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<s16>(m_ssw, m_info.address, [this](s32 v) { m_r[R2] = v; });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x6e:
|
||||
case 0x6f:
|
||||
// loadhu: load halfword unsigned
|
||||
temp = m_data->read_word(m_info.address);
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
get_dcammu().load<u16>(m_ssw, m_info.address, [this](u32 v) { m_r[R2] = v; });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
// storw: store word
|
||||
m_data->write_dword(m_info.address, m_r[R2]);
|
||||
get_dcammu().store<u32>(m_ssw, m_info.address, m_r[R2]);
|
||||
// TRAPS: A,P,W,I
|
||||
break;
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
// tsts: test and set
|
||||
temp = m_data->read_dword(m_info.address);
|
||||
if (!m_exception)
|
||||
{
|
||||
m_data->write_dword(m_info.address, temp | 0x80000000U);
|
||||
if (!m_exception)
|
||||
m_r[R2] = temp;
|
||||
}
|
||||
get_dcammu().modify<u32>(m_ssw, m_info.address, [this](u32 v) {
|
||||
m_r[R2] = v;
|
||||
return v | 0x80000000U;
|
||||
});
|
||||
// TRAPS: C,U,A,P,R,W,I
|
||||
break;
|
||||
case 0x74:
|
||||
case 0x75:
|
||||
// stors: store single floating
|
||||
m_data->write_dword(m_info.address, get_fp32(R2));
|
||||
get_dcammu().store<float32>(m_ssw, m_info.address, get_fp32(R2));
|
||||
// TRAPS: A,P,W,I
|
||||
break;
|
||||
case 0x76:
|
||||
case 0x77:
|
||||
// stord: store double floating
|
||||
m_data->write_qword(m_info.address, get_fp64(R2));
|
||||
get_dcammu().store<float64>(m_ssw, m_info.address, get_fp64(R2));
|
||||
// TRAPS: A,P,W,I
|
||||
break;
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
// storb: store byte
|
||||
m_data->write_byte(m_info.address, m_r[R2]);
|
||||
get_dcammu().store<u8>(m_ssw, m_info.address, m_r[R2]);
|
||||
// TRAPS: A,P,W,I
|
||||
break;
|
||||
|
||||
case 0x7c:
|
||||
case 0x7d:
|
||||
// storh: store halfword
|
||||
m_data->write_word(m_info.address, m_r[R2]);
|
||||
get_dcammu().store<u16>(m_ssw, m_info.address, m_r[R2]);
|
||||
// TRAPS: A,P,W,I
|
||||
break;
|
||||
|
||||
@ -1163,7 +1131,7 @@ void clipper_device::execute_instruction()
|
||||
|
||||
// store ri at sp - 4 * (15 - i)
|
||||
for (int i = R2; i < 15 && !m_exception; i++)
|
||||
m_data->write_dword(m_r[15] - 4 * (15 - i), m_r[i]);
|
||||
get_dcammu().store<u32>(m_ssw, m_r[15] - 4 * (15 - i), m_r[i]);
|
||||
|
||||
// decrement sp after push to allow restart on exceptions
|
||||
if (!m_exception)
|
||||
@ -1179,11 +1147,8 @@ void clipper_device::execute_instruction()
|
||||
|
||||
while (m_r[0])
|
||||
{
|
||||
const u8 byte = m_data->read_byte(m_r[1]);
|
||||
if (m_exception)
|
||||
break;
|
||||
get_dcammu().load<u8>(m_ssw, m_r[1], [this](u8 byte) { get_dcammu().store<u8>(m_ssw, m_r[2], byte); });
|
||||
|
||||
m_data->write_byte(m_r[2], byte);
|
||||
if (m_exception)
|
||||
break;
|
||||
|
||||
@ -1197,8 +1162,7 @@ void clipper_device::execute_instruction()
|
||||
// initc: initialise r0 bytes at r1 with value in r2
|
||||
while (m_r[0])
|
||||
{
|
||||
m_data->write_byte(m_r[1], m_r[2]);
|
||||
if (m_exception)
|
||||
if (!get_dcammu().store<u8>(m_ssw, m_r[1], m_r[2]))
|
||||
break;
|
||||
|
||||
m_r[0]--;
|
||||
@ -1215,18 +1179,15 @@ void clipper_device::execute_instruction()
|
||||
|
||||
while (m_r[0])
|
||||
{
|
||||
// set condition codes and abort the loop if the current byte does not match
|
||||
s32 byte1 = s8(m_data->read_byte(m_r[1]));
|
||||
if (m_exception)
|
||||
// read and compare bytes (as signed 32 bit integers)
|
||||
get_dcammu().load<s8>(m_ssw, m_r[1], [this](s32 byte1) {
|
||||
get_dcammu().load<s8>(m_ssw, m_r[2], [this, byte1](s32 byte2) {
|
||||
if (byte1 != byte2)
|
||||
FLAGS(C_SUB(byte2, byte1), V_SUB(byte2, byte1), byte2 == byte1, byte2 < byte1); }); });
|
||||
|
||||
// abort on exception or mismatch
|
||||
if (m_exception || !PSW(Z))
|
||||
break;
|
||||
s32 byte2 = s8(m_data->read_byte(m_r[2]));
|
||||
if (m_exception)
|
||||
break;
|
||||
if (byte1 != byte2)
|
||||
{
|
||||
FLAGS(C_SUB(byte2, byte1), V_SUB(byte2, byte1), byte2 == byte1, byte2 < byte1)
|
||||
break;
|
||||
}
|
||||
|
||||
m_r[0]--;
|
||||
m_r[1]++;
|
||||
@ -1241,13 +1202,8 @@ void clipper_device::execute_instruction()
|
||||
// restwN..restw12: pop registers rN:r14
|
||||
|
||||
// load ri from sp + 4 * (i - N)
|
||||
for (int i = R2; i < 15; i++)
|
||||
{
|
||||
temp = m_data->read_dword(m_r[15] + 4 * (i - R2));
|
||||
if (m_exception)
|
||||
break;
|
||||
m_r[i] = temp;
|
||||
}
|
||||
for (int i = R2; i < 15 && !m_exception; i++)
|
||||
get_dcammu().load<u32>(m_ssw, m_r[15] + 4 * (i - R2), [this, i](u32 v) { m_r[i] = v; });
|
||||
|
||||
// increment sp after pop to allow restart on exceptions
|
||||
if (!m_exception)
|
||||
@ -1261,7 +1217,7 @@ void clipper_device::execute_instruction()
|
||||
|
||||
// store fi at sp - 8 * (8 - i)
|
||||
for (int i = R2; i < 8 && !m_exception; i++)
|
||||
m_data->write_qword(m_r[15] - 8 * (8 - i), get_fp64(i));
|
||||
get_dcammu().store<float64>(m_ssw, m_r[15] - 8 * (8 - i), get_fp64(i));
|
||||
|
||||
// decrement sp after push to allow restart on exceptions
|
||||
if (!m_exception)
|
||||
@ -1273,13 +1229,8 @@ void clipper_device::execute_instruction()
|
||||
// restd0..restd7: pop registers fN:f7
|
||||
|
||||
// load fi from sp + 8 * (i - N)
|
||||
for (int i = R2; i < 8; i++)
|
||||
{
|
||||
temp = m_data->read_qword(m_r[15] + 8 * (i - R2));
|
||||
if (m_exception)
|
||||
break;
|
||||
set_fp(i, (float64)temp, F_NONE);
|
||||
}
|
||||
for (int i = R2; i < 8 && !m_exception; i++)
|
||||
get_dcammu().load<float64>(m_ssw, m_r[15] + 8 * (i - R2), [this, i](float64 v) { set_fp(i, v, F_NONE); });
|
||||
|
||||
// increment sp after pop to allow restart on exceptions
|
||||
if (!m_exception)
|
||||
@ -1438,7 +1389,7 @@ void clipper_device::execute_instruction()
|
||||
case 0x02:
|
||||
// saveur: save user registers
|
||||
for (int i = 0; i < 16 && !m_exception; i++)
|
||||
m_data->write_dword(m_rs[(m_info.macro >> 4) & 0xf] - 4 * (i + 1), m_ru[15 - i]);
|
||||
get_dcammu().store<u32>(m_ssw, m_rs[(m_info.macro >> 4) & 0xf] - 4 * (i + 1), m_ru[15 - i]);
|
||||
|
||||
if (!m_exception)
|
||||
m_rs[(m_info.macro >> 4) & 0xf] -= 64;
|
||||
@ -1446,13 +1397,8 @@ void clipper_device::execute_instruction()
|
||||
break;
|
||||
case 0x03:
|
||||
// restur: restore user registers
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
temp = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4 * i);
|
||||
if (m_exception)
|
||||
break;
|
||||
m_ru[i] = temp;
|
||||
}
|
||||
for (int i = 0; i < 16 && !m_exception; i++)
|
||||
get_dcammu().load<u32>(m_ssw, m_rs[(m_info.macro >> 4) & 0xf] + 4 * i, [this, i](u32 v) { m_ru[i] = v; });
|
||||
|
||||
if (!m_exception)
|
||||
m_rs[(m_info.macro >> 4) & 0xf] += 64;
|
||||
@ -1465,7 +1411,7 @@ void clipper_device::execute_instruction()
|
||||
break;
|
||||
case 0x05:
|
||||
// wait: wait for interrupt
|
||||
m_ip = m_pc;
|
||||
m_wait = true;
|
||||
// TRAPS: S
|
||||
break;
|
||||
|
||||
@ -1486,17 +1432,16 @@ void clipper_device::execute_instruction()
|
||||
|
||||
u32 clipper_device::reti()
|
||||
{
|
||||
u32 new_psw = 0, new_ssw = 0, new_pc = 0;
|
||||
|
||||
// fetch the psw, ssw and pc from the supervisor stack
|
||||
const u32 new_psw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 0);
|
||||
if (m_exception)
|
||||
if (!get_dcammu().load<u32>(m_ssw, m_rs[(m_info.macro >> 4) & 0xf] + 0, [&new_psw](u32 v) { new_psw = v; }))
|
||||
fatalerror("reti unrecoverable fault 0x%04x read psw address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 0, m_pc);
|
||||
|
||||
const u32 new_ssw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4);
|
||||
if (m_exception)
|
||||
if (!get_dcammu().load<u32>(m_ssw, m_rs[(m_info.macro >> 4) & 0xf] + 4, [&new_ssw](u32 v) { new_ssw = v; }))
|
||||
fatalerror("reti unrecoverable fault 0x%04x read ssw address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 4, m_pc);
|
||||
|
||||
const u32 new_pc = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8);
|
||||
if (m_exception)
|
||||
if (!get_dcammu().load<u32>(m_ssw, m_rs[(m_info.macro >> 4) & 0xf] + 8, [&new_pc](u32 v) { new_pc = v; }))
|
||||
fatalerror("reti unrecoverable fault 0x%04x read pc address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 8, m_pc);
|
||||
|
||||
LOGMASKED(LOG_EXCEPTION, "reti r%d ssp 0x%08x pc 0x%08x ssw 0x%08x psw 0x%08x new_pc 0x%08x new_ssw 0x%08x new_psw 0x%08x\n",
|
||||
@ -1522,6 +1467,7 @@ u32 clipper_device::intrap(const u16 vector, const u32 old_pc)
|
||||
{
|
||||
const u32 old_ssw = m_ssw;
|
||||
const u32 old_psw = m_psw;
|
||||
u32 new_pc = 0, new_ssw = 0;
|
||||
|
||||
// clear ssw bits to enable supervisor memory access
|
||||
m_ssw &= ~(SSW_U | SSW_K | SSW_UU | SSW_KU);
|
||||
@ -1530,13 +1476,10 @@ u32 clipper_device::intrap(const u16 vector, const u32 old_pc)
|
||||
m_exception = 0;
|
||||
|
||||
// fetch next pc and ssw from interrupt vector
|
||||
const u32 new_pc = m_data->read_dword(vector + get_evpc_offset());
|
||||
if (m_exception)
|
||||
fatalerror("intrap unrecoverable fault 0x%04x read pc address 0x%08x pc 0x%08x\n", m_exception, vector + get_evpc_offset(), old_pc);
|
||||
|
||||
const u32 new_ssw = m_data->read_dword(vector + get_evssw_offset());
|
||||
if (m_exception)
|
||||
fatalerror("intrap unrecoverable fault 0x%04x read ssw address 0x%08x pc 0x%08x\n", m_exception, vector + get_evssw_offset(), old_pc);
|
||||
if (!get_dcammu().load<u32>(m_ssw, vector + 0, [&new_pc](u32 v) { new_pc = v; }))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x load pc address 0x%08x pc 0x%08x\n", m_exception, vector + 0, old_pc);
|
||||
if (!get_dcammu().load<u32>(m_ssw, vector + 4, [&new_ssw](u32 v) { new_ssw = v; }))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x load ssw address 0x%08x pc 0x%08x\n", m_exception, vector + 4, old_pc);
|
||||
|
||||
LOGMASKED(LOG_EXCEPTION, "intrap vector 0x%04x pc 0x%08x ssp 0x%08x new_pc 0x%08x new_ssw 0x%08x\n", vector, old_pc, m_rs[15], new_pc, new_ssw);
|
||||
|
||||
@ -1581,18 +1524,107 @@ u32 clipper_device::intrap(const u16 vector, const u32 old_pc)
|
||||
}
|
||||
|
||||
// push pc, ssw and psw onto supervisor stack
|
||||
m_data->write_dword(m_rs[15] - 0x4, old_pc);
|
||||
if (m_exception)
|
||||
fatalerror("intrap unrecoverable fault 0x%04x write pc address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x4, old_pc);
|
||||
m_data->write_dword(m_rs[15] - 0x8, old_ssw);
|
||||
if (m_exception)
|
||||
fatalerror("intrap unrecoverable fault 0x%04x write ssw address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x8, old_pc);
|
||||
m_data->write_dword(m_rs[15] - 0xc, (old_psw & ~(PSW_CTS | PSW_MTS)) | source);
|
||||
if (m_exception)
|
||||
fatalerror("intrap unrecoverable fault 0x%04x write psw address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0xc, old_pc);
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0x4, old_pc))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push pc ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x4, old_pc);
|
||||
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0x8, old_ssw))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push ssw ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x8, old_pc);
|
||||
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0xc, (old_psw & ~(PSW_CTS | PSW_MTS)) | source))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push psw ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0xc, old_pc);
|
||||
|
||||
// decrement supervisor stack pointer
|
||||
m_rs[15] -= get_eframe_size();
|
||||
m_rs[15] -= 12;
|
||||
|
||||
// set ssw from vector and previous mode
|
||||
set_ssw((new_ssw & ~SSW_P) | (old_ssw & SSW_U) << 1);
|
||||
|
||||
// clear psw
|
||||
set_psw(0);
|
||||
|
||||
// return new pc from trap vector
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
u32 clipper_c400_device::intrap(const u16 vector, const u32 old_pc)
|
||||
{
|
||||
const u32 old_ssw = m_ssw;
|
||||
const u32 old_psw = m_psw;
|
||||
u32 new_pc = 0, new_ssw = 0;
|
||||
|
||||
// clear ssw bits to enable supervisor memory access
|
||||
m_ssw &= ~(SSW_U | SSW_K | SSW_UU | SSW_KU);
|
||||
|
||||
// clear exception state
|
||||
m_exception = 0;
|
||||
|
||||
// fetch ssw and pc from interrupt vector (C400 reversed wrt C100/C300)
|
||||
if (!get_dcammu().load<u32>(m_ssw, vector + 0, [&new_ssw](u32 v) { new_ssw = v; }))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x load ssw address 0x%08x pc 0x%08x\n", m_exception, vector + 0, old_pc);
|
||||
if (!get_dcammu().load<u32>(m_ssw, vector + 4, [&new_pc](u32 v) { new_pc = v; }))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x load pc address 0x%08x pc 0x%08x\n", m_exception, vector + 4, old_pc);
|
||||
|
||||
LOGMASKED(LOG_EXCEPTION, "intrap vector 0x%04x pc 0x%08x ssp 0x%08x new_pc 0x%08x new_ssw 0x%08x\n", vector, old_pc, m_rs[15], new_pc, new_ssw);
|
||||
|
||||
// derive cts and mts from vector
|
||||
u32 source = 0;
|
||||
switch (vector)
|
||||
{
|
||||
// data memory trap group
|
||||
case EXCEPTION_D_CORRECTED_MEMORY_ERROR:
|
||||
case EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR:
|
||||
case EXCEPTION_D_ALIGNMENT_FAULT:
|
||||
case EXCEPTION_D_PAGE_FAULT:
|
||||
case EXCEPTION_D_READ_PROTECT_FAULT:
|
||||
case EXCEPTION_D_WRITE_PROTECT_FAULT:
|
||||
|
||||
// instruction memory trap group
|
||||
case EXCEPTION_I_CORRECTED_MEMORY_ERROR:
|
||||
case EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR:
|
||||
case EXCEPTION_I_ALIGNMENT_FAULT:
|
||||
case EXCEPTION_I_PAGE_FAULT:
|
||||
case EXCEPTION_I_EXECUTE_PROTECT_FAULT:
|
||||
source = (vector & MTS_VMASK) << (MTS_SHIFT - MTS_VSHIFT);
|
||||
break;
|
||||
|
||||
// integer arithmetic trap group
|
||||
case EXCEPTION_INTEGER_DIVIDE_BY_ZERO:
|
||||
source = CTS_DIVIDE_BY_ZERO;
|
||||
break;
|
||||
|
||||
// illegal operation trap group
|
||||
case EXCEPTION_ILLEGAL_OPERATION:
|
||||
source = CTS_ILLEGAL_OPERATION;
|
||||
break;
|
||||
case EXCEPTION_PRIVILEGED_INSTRUCTION:
|
||||
source = CTS_PRIVILEGED_INSTRUCTION;
|
||||
break;
|
||||
|
||||
// diagnostic trap group
|
||||
case EXCEPTION_TRACE:
|
||||
source = CTS_TRACE_TRAP;
|
||||
break;
|
||||
}
|
||||
|
||||
// push pc, ssw and psw onto supervisor stack
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0x4, old_pc))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push pc ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x4, old_pc);
|
||||
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0x8, old_ssw))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push ssw ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x8, old_pc);
|
||||
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0xc, (old_psw & ~(PSW_CTS | PSW_MTS)) | source))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push psw ssp 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0xc, old_pc);
|
||||
|
||||
// TODO: push pc1
|
||||
// TODO: push pc2
|
||||
|
||||
// push delayed branch pc onto supervisor stack
|
||||
if (!get_dcammu().store<u32>(m_ssw, m_rs[15] - 0x18, m_db_pc))
|
||||
fatalerror("intrap unrecoverable fault 0x%04x push db_pc address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x18, old_pc);
|
||||
|
||||
// decrement supervisor stack pointer
|
||||
m_rs[15] -= 24;
|
||||
|
||||
// set ssw from vector and previous mode
|
||||
set_ssw((new_ssw & ~SSW_P) | (old_ssw & SSW_U) << 1);
|
||||
@ -1736,37 +1768,119 @@ void clipper_device::fp_exception()
|
||||
|
||||
void clipper_c400_device::execute_instruction()
|
||||
{
|
||||
// update delay slot pointer
|
||||
switch (PSW(DSP))
|
||||
{
|
||||
case DSP_S1:
|
||||
// take delayed branch
|
||||
m_psw &= ~PSW_DSP;
|
||||
m_ip = m_db_pc;
|
||||
return;
|
||||
|
||||
case DSP_SALL:
|
||||
// one delay slot still active
|
||||
m_psw &= ~PSW_DSP;
|
||||
m_psw |= DSP_S1;
|
||||
break;
|
||||
|
||||
case DSP_SETUP:
|
||||
// two delay slots active
|
||||
m_psw &= ~PSW_DSP;
|
||||
m_psw |= DSP_SALL;
|
||||
break;
|
||||
}
|
||||
|
||||
// if executing a delay slot instruction, test for valid type
|
||||
if (PSW(DSP))
|
||||
{
|
||||
switch (m_info.opcode)
|
||||
{
|
||||
case 0x13: // ret
|
||||
case 0x44: // call
|
||||
case 0x45:
|
||||
case 0x48: // b*
|
||||
case 0x49:
|
||||
case 0x4a: // cdb
|
||||
case 0x4b:
|
||||
case 0x4c: // cdbeq
|
||||
case 0x4d:
|
||||
case 0x4e: // cdbne
|
||||
case 0x4f:
|
||||
case 0x50: // db*
|
||||
case 0x51:
|
||||
// TODO: this should throw some kind of illegal instruction trap, not abort
|
||||
fatalerror("instruction type 0x%02x invalid in branch delay slot pc 0x%08x\n", m_info.opcode, m_pc);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_info.opcode)
|
||||
{
|
||||
#ifdef UNIMPLEMENTED_C400
|
||||
case 0x46:
|
||||
case 0x47:
|
||||
// loadd2:
|
||||
// loadd2: load double floating double
|
||||
// TODO: 128-bit load
|
||||
get_dcammu().load<float64>(m_ssw, m_info.address + 0, [this](float64 v) { set_fp(R2 + 0, v, F_NONE); });
|
||||
get_dcammu().load<float64>(m_ssw, m_info.address + 8, [this](float64 v) { set_fp(R2 + 1, v, F_NONE); });
|
||||
// TRAPS: C,U,A,P,R,I
|
||||
break;
|
||||
|
||||
case 0x4a:
|
||||
case 0x4b:
|
||||
// cdb:
|
||||
break;
|
||||
// cdb: call with delayed branch?
|
||||
// emulate.h: "cdb is special because it does not support all addressing modes", 2-3 parcels
|
||||
fatalerror("cdb pc 0x%08x\n", m_pc);
|
||||
case 0x4c:
|
||||
case 0x4d:
|
||||
// cdbeq:
|
||||
break;
|
||||
// cdbeq: call with delayed branch if equal?
|
||||
fatalerror("cdbeq pc 0x%08x\n", m_pc);
|
||||
case 0x4e:
|
||||
case 0x4f:
|
||||
// cdbne:
|
||||
break;
|
||||
// cdbne: call with delayed branch if not equal?
|
||||
fatalerror("cdbne pc 0x%08x\n", m_pc);
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
// db*:
|
||||
// db*: delayed branch on condition
|
||||
if (evaluate_branch())
|
||||
{
|
||||
m_psw |= DSP_SETUP;
|
||||
m_db_pc = m_info.address;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb0:
|
||||
// abss: absolute value single floating?
|
||||
if (float32_lt(get_fp32(R1), 0))
|
||||
set_fp(R2, float32_mul(get_fp32(R1), int32_to_float32(-1)), F_IVUX);
|
||||
else
|
||||
set_fp(R2, get_fp32(R1), F_IVUX);
|
||||
break;
|
||||
|
||||
case 0xb2:
|
||||
// absd: absolute value double floating?
|
||||
if (float64_lt(get_fp64(R1), 0))
|
||||
set_fp(R2, float64_mul(get_fp64(R1), int32_to_float64(-1)), F_IVUX);
|
||||
else
|
||||
set_fp(R2, get_fp64(R1), F_IVUX);
|
||||
break;
|
||||
|
||||
case 0xb4:
|
||||
// unprivileged macro instructions
|
||||
switch (m_info.subopcode)
|
||||
{
|
||||
case 0x44:
|
||||
// cnvxsw: ??
|
||||
fatalerror("cnvxsw pc 0x%08x\n", m_pc);
|
||||
case 0x46:
|
||||
// cnvxdw: ??
|
||||
fatalerror("cnvxdw pc 0x%08x\n", m_pc);
|
||||
|
||||
default:
|
||||
clipper_device::execute_instruction();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb6:
|
||||
@ -1777,19 +1891,29 @@ void clipper_c400_device::execute_instruction()
|
||||
{
|
||||
case 0x07:
|
||||
// loadts: unknown?
|
||||
fatalerror("loadts pc 0x%08x\n", m_pc);
|
||||
|
||||
default:
|
||||
clipper_device::execute_instruction();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_exception = EXCEPTION_PRIVILEGED_INSTRUCTION;
|
||||
break;
|
||||
|
||||
case 0xbc:
|
||||
// waitd:
|
||||
if (!SSW(U))
|
||||
; // TODO: don't know what this instruction does
|
||||
else
|
||||
m_exception = EXCEPTION_PRIVILEGED_INSTRUCTION;
|
||||
break;
|
||||
|
||||
case 0xc0:
|
||||
// s*:
|
||||
// s*: set register on condition
|
||||
m_r[R1] = evaluate_branch() ? 1 : 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
clipper_device::execute_instruction();
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "softfloat/milieu.h"
|
||||
#include "softfloat/softfloat.h"
|
||||
|
||||
#include "cpu/clipper/common.h"
|
||||
#include "machine/cammu.h"
|
||||
|
||||
// convenience macros for dealing with the psw and ssw
|
||||
#define PSW(mask) (m_psw & PSW_##mask)
|
||||
#define SSW(mask) (m_ssw & SSW_##mask)
|
||||
@ -17,22 +20,9 @@
|
||||
class clipper_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
DECLARE_READ32_MEMBER(get_ssw) const { return m_ssw; }
|
||||
DECLARE_WRITE8_MEMBER(set_ivec) { m_ivec = data; }
|
||||
DECLARE_WRITE16_MEMBER(set_exception);
|
||||
|
||||
enum addressing_modes : u8
|
||||
{
|
||||
ADDR_MODE_PC32 = 0x10, // pc relative with 32 bit displacement
|
||||
ADDR_MODE_ABS32 = 0x30, // 32 bit absolute
|
||||
ADDR_MODE_REL32 = 0x60, // relative with 32 bit displacement
|
||||
ADDR_MODE_PC16 = 0x90, // pc relative with 16 bit displacement
|
||||
ADDR_MODE_REL12 = 0xa0, // relative with 12 bit displacement
|
||||
ADDR_MODE_ABS16 = 0xb0, // 16 bit absolute
|
||||
ADDR_MODE_PCX = 0xd0, // pc indexed
|
||||
ADDR_MODE_RELX = 0xe0 // relative indexed
|
||||
};
|
||||
|
||||
// branch conditions (first description for comparison, second for move/logical)
|
||||
enum branch_conditions : u8
|
||||
{
|
||||
@ -94,73 +84,21 @@ public:
|
||||
FR_3 = 0x00018000 // round toward zero
|
||||
};
|
||||
|
||||
enum ssw : u32
|
||||
enum psw_dsp : u32
|
||||
{
|
||||
SSW_IN = 0x0000000f, // interrupt number (4 bits)
|
||||
SSW_IL = 0x000000f0, // interrupt level (4 bits)
|
||||
SSW_EI = 0x00000100, // enable interrupts
|
||||
SSW_ID = 0x0001fe00, // cpu rev # and type (8 bits)
|
||||
// unused (5 bits)
|
||||
SSW_FRD = 0x00400000, // floating registers dirty
|
||||
SSW_TP = 0x00800000, // trace trap pending
|
||||
SSW_ECM = 0x01000000, // enable corrected memory error
|
||||
SSW_DF = 0x02000000, // fpu disabled
|
||||
SSW_M = 0x04000000, // mapped mode
|
||||
SSW_KU = 0x08000000, // user protect key
|
||||
SSW_UU = 0x10000000, // user data mode
|
||||
SSW_K = 0x20000000, // protect key
|
||||
SSW_U = 0x40000000, // user mode
|
||||
SSW_P = 0x80000000 // previous mode
|
||||
DSP_NONE = 0x00000000, // no delayed branch active
|
||||
DSP_S1 = 0x00100000, // delayed branch slot 1 active
|
||||
DSP_SALL = 0x00200000, // delayed branch slots 0 and 1 active
|
||||
DSP_SETUP = 0x00300000 // delayed branch taken
|
||||
};
|
||||
|
||||
enum ssw_id : u32
|
||||
{
|
||||
SSW_ID_C400R0 = 0x00000,
|
||||
SSW_ID_C400R1 = 0x04000,
|
||||
SSW_ID_C400R2 = 0x08000,
|
||||
SSW_ID_C400R3 = 0x0c000,
|
||||
SSW_ID_C400R4 = 0x10000
|
||||
};
|
||||
|
||||
enum exception_vectors : u16
|
||||
{
|
||||
// data memory trap group
|
||||
EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108,
|
||||
EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR = 0x110,
|
||||
EXCEPTION_D_ALIGNMENT_FAULT = 0x120,
|
||||
EXCEPTION_D_PAGE_FAULT = 0x128,
|
||||
EXCEPTION_D_READ_PROTECT_FAULT = 0x130,
|
||||
EXCEPTION_D_WRITE_PROTECT_FAULT = 0x138,
|
||||
|
||||
// floating-point arithmetic trap group
|
||||
EXCEPTION_FLOATING_INEXACT = 0x180,
|
||||
EXCEPTION_FLOATING_UNDERFLOW = 0x188,
|
||||
EXCEPTION_FLOATING_DIVIDE_BY_ZERO = 0x190,
|
||||
EXCEPTION_FLOATING_OVERFLOW = 0x1a0,
|
||||
EXCEPTION_FLOATING_INVALID_OPERATION = 0x1c0,
|
||||
|
||||
// integer arithmetic trap group
|
||||
EXCEPTION_INTEGER_DIVIDE_BY_ZERO = 0x208,
|
||||
|
||||
// instruction memory trap group
|
||||
EXCEPTION_I_CORRECTED_MEMORY_ERROR = 0x288,
|
||||
EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR = 0x290,
|
||||
EXCEPTION_I_ALIGNMENT_FAULT = 0x2a0,
|
||||
EXCEPTION_I_PAGE_FAULT = 0x2a8,
|
||||
EXCEPTION_I_EXECUTE_PROTECT_FAULT = 0x2b0,
|
||||
|
||||
// illegal operation trap group
|
||||
EXCEPTION_ILLEGAL_OPERATION = 0x300,
|
||||
EXCEPTION_PRIVILEGED_INSTRUCTION = 0x308,
|
||||
|
||||
// diagnostic trap group
|
||||
EXCEPTION_TRACE = 0x380,
|
||||
|
||||
// supervisor calls (0x400-0x7f8)
|
||||
EXCEPTION_SUPERVISOR_CALL_BASE = 0x400,
|
||||
|
||||
// prioritized interrupts (0x800-0xff8)
|
||||
EXCEPTION_INTERRUPT_BASE = 0x800
|
||||
SSW_ID_C400R0 = 0x00800,
|
||||
SSW_ID_C400R1 = 0x04800,
|
||||
SSW_ID_C400R2 = 0x08800,
|
||||
SSW_ID_C400R3 = 0x0c800,
|
||||
SSW_ID_C400R4 = 0x10800
|
||||
};
|
||||
|
||||
// trap source values are shifted into the correct field in the psw
|
||||
@ -230,13 +168,17 @@ protected:
|
||||
// device_disasm_interface overrides
|
||||
virtual util::disasm_interface *create_disassembler() override;
|
||||
|
||||
// mmu helpers
|
||||
virtual cammu_device &get_icammu() const = 0;
|
||||
virtual cammu_device &get_dcammu() const = 0;
|
||||
|
||||
// cpu execution logic
|
||||
bool decode_instruction();
|
||||
virtual void execute_instruction();
|
||||
bool evaluate_branch() const;
|
||||
|
||||
// exception entry and return helpers
|
||||
u32 intrap(const u16 vector, const u32 old_pc);
|
||||
virtual u32 intrap(const u16 vector, const u32 old_pc);
|
||||
u32 reti();
|
||||
|
||||
// cpu state helpers
|
||||
@ -248,11 +190,6 @@ protected:
|
||||
virtual int get_ireg_count() const { return 16; }
|
||||
virtual int get_freg_count() const { return 8; }
|
||||
|
||||
// exception vector and frame helpers
|
||||
virtual int get_eframe_size() const { return 12; }
|
||||
virtual int get_evpc_offset() const { return 0; }
|
||||
virtual int get_evssw_offset() const { return 4; }
|
||||
|
||||
// floating point helpers
|
||||
float32 get_fp32(const u8 reg) const { return m_f[reg & 0xf]; }
|
||||
float64 get_fp64(const u8 reg) const { return m_f[reg & 0xf]; }
|
||||
@ -317,11 +254,9 @@ protected:
|
||||
};
|
||||
|
||||
// emulation state
|
||||
address_space_config m_insn_config;
|
||||
address_space_config m_data_config;
|
||||
|
||||
address_space *m_insn;
|
||||
address_space *m_data;
|
||||
address_space_config m_main_config;
|
||||
address_space_config m_io_config;
|
||||
address_space_config m_boot_config;
|
||||
|
||||
enum registers
|
||||
{
|
||||
@ -333,6 +268,7 @@ protected:
|
||||
};
|
||||
|
||||
int m_icount; // instruction cycle count
|
||||
bool m_wait;
|
||||
|
||||
// program-visible cpu state
|
||||
u32 m_pc; // current instruction address
|
||||
@ -372,12 +308,28 @@ class clipper_c100_device : public clipper_device
|
||||
{
|
||||
public:
|
||||
clipper_c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
virtual cammu_device &get_icammu() const override { return *m_icammu; }
|
||||
virtual cammu_device &get_dcammu() const override { return *m_dcammu; }
|
||||
|
||||
private:
|
||||
required_device<cammu_device> m_icammu;
|
||||
required_device<cammu_device> m_dcammu;
|
||||
};
|
||||
|
||||
class clipper_c300_device : public clipper_device
|
||||
{
|
||||
public:
|
||||
clipper_c300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
virtual cammu_device &get_icammu() const override { return *m_icammu; }
|
||||
virtual cammu_device &get_dcammu() const override { return *m_dcammu; }
|
||||
|
||||
private:
|
||||
required_device<cammu_device> m_icammu;
|
||||
required_device<cammu_device> m_dcammu;
|
||||
};
|
||||
|
||||
class clipper_c400_device : public clipper_device
|
||||
@ -386,19 +338,20 @@ public:
|
||||
clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
virtual u32 intrap(const u16 vector, const u32 old_pc) override;
|
||||
|
||||
// C400 has additional 8 floating point registers
|
||||
virtual int get_freg_count() const override { return 16; }
|
||||
|
||||
// C400 creates a 24 byte exception frame (C100/C300 is 12 bytes), but the
|
||||
// service routine must increment sp by 12 prior to executing reti
|
||||
// exception frame size
|
||||
virtual int get_eframe_size() const override { return 24; }
|
||||
|
||||
// C400 pc and ssw are reversed in exception vector compared to C100/C300
|
||||
virtual int get_evpc_offset() const override { return 4; }
|
||||
virtual int get_evssw_offset() const override { return 0; }
|
||||
|
||||
virtual void execute_instruction() override;
|
||||
|
||||
virtual cammu_device &get_icammu() const override { return *m_cammu; }
|
||||
virtual cammu_device &get_dcammu() const override { return *m_cammu; }
|
||||
|
||||
private:
|
||||
u32 m_db_pc; // delayed branch pc
|
||||
|
||||
required_device<cammu_device> m_cammu;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(CLIPPER_C100, clipper_c100_device)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/clipper/common.h"
|
||||
#include "clipperd.h"
|
||||
|
||||
/*
|
||||
@ -297,6 +298,10 @@ offs_t clipper_disassembler::disassemble(std::ostream &stream, offs_t pc, const
|
||||
case 0x3e: util::stream_format(stream, "trapfn"); break;
|
||||
case 0x3f: util::stream_format(stream, "loadfs r%d,f%d", (opcodes.r16(pc+2) & 0xf0) >> 4, opcodes.r16(pc+2) & 0xf); break;
|
||||
|
||||
#if C400_INSTRUCTIONS
|
||||
case 0x44: util::stream_format(stream, "cnvxsw f%d,f%d", (opcodes.r16(pc + 2) & 0xf0) >> 4, opcodes.r16(pc + 2) & 0xf); break;
|
||||
case 0x46: util::stream_format(stream, "cnvxdw f%d,f%d", (opcodes.r16(pc + 2) & 0xf0) >> 4, opcodes.r16(pc + 2) & 0xf); break;
|
||||
#endif
|
||||
default:
|
||||
util::stream_format(stream, "macro 0x%04x 0x%04x", opcodes.r16(pc), opcodes.r16(pc+2));
|
||||
break;
|
||||
|
@ -16,22 +16,8 @@ public:
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
|
||||
private:
|
||||
enum addressing_modes : u8
|
||||
{
|
||||
ADDR_MODE_PC32 = 0x10, // pc relative with 32 bit displacement
|
||||
ADDR_MODE_ABS32 = 0x30, // 32 bit absolute
|
||||
ADDR_MODE_REL32 = 0x60, // relative with 32 bit displacement
|
||||
ADDR_MODE_PC16 = 0x90, // pc relative with 16 bit displacement
|
||||
ADDR_MODE_REL12 = 0xa0, // relative with 12 bit displacement
|
||||
ADDR_MODE_ABS16 = 0xb0, // 16 bit absolute
|
||||
ADDR_MODE_PCX = 0xd0, // pc indexed
|
||||
ADDR_MODE_RELX = 0xe0 // relative indexed
|
||||
};
|
||||
|
||||
static const char *const cc[];
|
||||
std::string address (offs_t pc, const data_buffer &opcodes);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
83
src/devices/cpu/clipper/common.h
Normal file
83
src/devices/cpu/clipper/common.h
Normal file
@ -0,0 +1,83 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_CPU_CLIPPER_COMMON_H
|
||||
#define MAME_CPU_CLIPPER_COMMON_H
|
||||
|
||||
#pragma once
|
||||
|
||||
enum addressing_modes : u8
|
||||
{
|
||||
ADDR_MODE_PC32 = 0x10, // pc relative with 32 bit displacement
|
||||
ADDR_MODE_ABS32 = 0x30, // 32 bit absolute
|
||||
ADDR_MODE_REL32 = 0x60, // relative with 32 bit displacement
|
||||
ADDR_MODE_PC16 = 0x90, // pc relative with 16 bit displacement
|
||||
ADDR_MODE_REL12 = 0xa0, // relative with 12 bit displacement
|
||||
ADDR_MODE_ABS16 = 0xb0, // 16 bit absolute
|
||||
ADDR_MODE_PCX = 0xd0, // pc indexed
|
||||
ADDR_MODE_RELX = 0xe0 // relative indexed
|
||||
};
|
||||
|
||||
enum ssw_mask : u32
|
||||
{
|
||||
SSW_IN = 0x0000000f, // interrupt number (4 bits)
|
||||
SSW_IL = 0x000000f0, // interrupt level (4 bits)
|
||||
SSW_EI = 0x00000100, // enable interrupts
|
||||
SSW_ID = 0x0001fe00, // cpu rev # and type (8 bits)
|
||||
// unused (5 bits)
|
||||
SSW_FRD = 0x00400000, // floating registers dirty
|
||||
SSW_TP = 0x00800000, // trace trap pending
|
||||
SSW_ECM = 0x01000000, // enable corrected memory error
|
||||
SSW_DF = 0x02000000, // fpu disabled
|
||||
SSW_M = 0x04000000, // mapped mode
|
||||
SSW_KU = 0x08000000, // user protect key
|
||||
SSW_UU = 0x10000000, // user data mode
|
||||
SSW_K = 0x20000000, // protect key
|
||||
SSW_U = 0x40000000, // user mode
|
||||
SSW_P = 0x80000000, // previous mode
|
||||
|
||||
SSW_PL = 0x78000000 // protection level relevant bits
|
||||
};
|
||||
|
||||
enum exception_vector : u16
|
||||
{
|
||||
// data memory trap group
|
||||
EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108,
|
||||
EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR = 0x110,
|
||||
EXCEPTION_D_ALIGNMENT_FAULT = 0x120,
|
||||
EXCEPTION_D_PAGE_FAULT = 0x128,
|
||||
EXCEPTION_D_READ_PROTECT_FAULT = 0x130,
|
||||
EXCEPTION_D_WRITE_PROTECT_FAULT = 0x138,
|
||||
|
||||
// floating-point arithmetic trap group
|
||||
EXCEPTION_FLOATING_INEXACT = 0x180,
|
||||
EXCEPTION_FLOATING_UNDERFLOW = 0x188,
|
||||
EXCEPTION_FLOATING_DIVIDE_BY_ZERO = 0x190,
|
||||
EXCEPTION_FLOATING_OVERFLOW = 0x1a0,
|
||||
EXCEPTION_FLOATING_INVALID_OPERATION = 0x1c0,
|
||||
|
||||
// integer arithmetic trap group
|
||||
EXCEPTION_INTEGER_DIVIDE_BY_ZERO = 0x208,
|
||||
|
||||
// instruction memory trap group
|
||||
EXCEPTION_I_CORRECTED_MEMORY_ERROR = 0x288,
|
||||
EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR = 0x290,
|
||||
EXCEPTION_I_ALIGNMENT_FAULT = 0x2a0,
|
||||
EXCEPTION_I_PAGE_FAULT = 0x2a8,
|
||||
EXCEPTION_I_EXECUTE_PROTECT_FAULT = 0x2b0,
|
||||
|
||||
// illegal operation trap group
|
||||
EXCEPTION_ILLEGAL_OPERATION = 0x300,
|
||||
EXCEPTION_PRIVILEGED_INSTRUCTION = 0x308,
|
||||
|
||||
// diagnostic trap group
|
||||
EXCEPTION_TRACE = 0x380,
|
||||
|
||||
// supervisor calls (0x400-0x7f8)
|
||||
EXCEPTION_SUPERVISOR_CALL_BASE = 0x400,
|
||||
|
||||
// prioritized interrupts (0x800-0xff8)
|
||||
EXCEPTION_INTERRUPT_BASE = 0x800
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_CLIPPER_COMMON_H
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* The first systems were built using the original C100 CLIPPER CPU, and used
|
||||
* an additional Intel 80186 as an I/O processor, later moving to a C300 with
|
||||
* 80386 IOP. Around 1989, the CLIPPER became fast enough to obviate the need
|
||||
* 80386 IOP. Around 1990, the CLIPPER became fast enough to obviate the need
|
||||
* for the separate I/O processor, and systems from that point used the main
|
||||
* CPU for both compute and I/O, along with some custom ASICs.
|
||||
*
|
||||
@ -17,66 +17,77 @@
|
||||
* Year Family Models CPU
|
||||
* 1986 amethyst 32C/100/200 C100 (80186 IOP)
|
||||
* 1988 topaz 300/3000/4000/5000 C300/C300Plus (80386 IOP)
|
||||
* 1989 turquoise 2000 C300
|
||||
* 1989 emerald 6000/6100/6200/6500/6600 C300/C300Plus (C4T in 6600?)
|
||||
* 1991 sapphire 2400/6400 C4T
|
||||
* 1992 sapphire 2500/2700/6700/6800/2800 C4I
|
||||
* 1990 emerald 6000/6100/6200/6500 C300/C300Plus
|
||||
* 1990 turquoise 2000 C300
|
||||
* 1991 emerald? 6600 C4?
|
||||
* 1992 sapphire 2400/6400 C4T
|
||||
* 1993 sapphire 2500/2700/6700/6800 C4I
|
||||
* 1994 sapphire 2800 C4I
|
||||
*
|
||||
* Individual models and some of their specific attributes include:
|
||||
*
|
||||
* Model Year CPU Clock Family
|
||||
* 2000 1989 C300 turquoise
|
||||
* 6000 1989 C300 emerald
|
||||
* 2400 1991? C4T 40MHz? sapphire
|
||||
* 6400 1991 C4T 40MHz sapphire
|
||||
* 6600 C400 emerald (IOI, SRX bus?)
|
||||
* 6700 1992 C400I 70MHz? sapphire
|
||||
* 6800 1993 C400I 80MHz? sapphire
|
||||
* 2500 1993? C400I 50MHz? sapphire
|
||||
* 2700 1992 C400I 70MHz? sapphire
|
||||
* 2800 1994 C400I 80MHz? sapphire
|
||||
* Model Year CPU Performance Clock Family Bus
|
||||
* 6000 1990 C300 10 MIPS 40MHz emerald SRX
|
||||
* 6100 1990 14 MIPS emerald IOI?, 6105 has 5-slot chassis
|
||||
* 6500 C300+ emerald IOI, QWIC bus?
|
||||
* 6200 1990 C300+ 14 MIPS 60MHz emerald
|
||||
* 1991 18 MIPS
|
||||
* 2000 1990 C300 12.5 MIPS 50MHz? turquoise CBUS
|
||||
* 6600 1991 C400 40 MIPS emerald? IOI, SRX bus?
|
||||
* 2400 1992 C4T 36 MIPS/33 SPECmarks 40MHz? sapphire CBUS
|
||||
* 6400 1992 C4T 36 MIPS/33 SPECmarks 40MHz sapphire SRX
|
||||
* 2700 1993 C400I 40.1 SPECmark89 sapphire 2 CBUS
|
||||
* 6700 1993 C400I 40.1 SPECmark89 sapphire 2 SRX
|
||||
* 6800 1993 C400I 67.2 SPECmark89 sapphire 3 SRX
|
||||
* 2500 1993 C400I 19.9 SPECint92 sapphire
|
||||
* 2800 1994 C400I sapphire 3 CBUS?
|
||||
*
|
||||
* 6100 emerald (IOI)
|
||||
* 6200 1989 C300Plus 60MHz emerald
|
||||
* 6500 C300Plus emerald (IOI, QWIC bus?)
|
||||
* IOI == I/O Interface (another type of bus?)
|
||||
* Sapphire 2 w/CBUS supports RETRY (maybe bus retry?)
|
||||
*
|
||||
* With many exceptions, the general model numbering system is ABCD, where:
|
||||
* With some exceptions, system models are numbered ABCD, where:
|
||||
*
|
||||
* A: case type (2=desktop, 6=tower)
|
||||
* A: case type (2=desktop, 6=minicase)
|
||||
* B: CPU type (0=C300, 4=C4T, 6=C400?, 7/8/5 = C400I)
|
||||
* C: graphics type (0=none, 3/5=GT, 4/8 = EDGE)
|
||||
* D: always 0?
|
||||
* C: graphics type (0=none, 3/5=GT, 4=EDGE-1, 8 = EDGE-2)
|
||||
* D: usually 0, 6xxx systems have 5, 7 and 9 options (backplane type?)
|
||||
*
|
||||
* Both the desktop and tower units supported an expansion bus with a variety
|
||||
* Graphics type 3 is for GT graphics fitted to a 2xxx system, and type 5 when
|
||||
* fitted to a 6xxx system. The latter is possibly also known as GTDB.
|
||||
*
|
||||
* Both the desktop and minicase units supported expansion slots with a variety
|
||||
* of cards, although with different profiles and connectors between 2xxx and
|
||||
* 6xxx systems. The bus is referred to as SR, SRX, SR Bus, CBUS and some
|
||||
* combinations of these in various places, but all appears to be compatible or
|
||||
* combinations of these in various places, but all appear to be compatible or
|
||||
* identical, possibly with SRX being an enhanced version. The bus supported a
|
||||
* range of add-in cards, ranging from expanded SCSI and serial controllers,
|
||||
* to specialised scanning and plotting controllers, a VME bridge, and most
|
||||
* importantly various single and dual-headed graphics boards.
|
||||
*
|
||||
* The InterPro graphics options included the GT range, generally fitted to the
|
||||
* desktop systems, and EDGE graphics for the towers. Systems with no graphics
|
||||
* were operated through a serial console on serial port 2, and were branded as
|
||||
* InterServe rather than InterPro systems.
|
||||
* desktops, and EDGE graphics for the 6xxx systems. Systems with no graphics
|
||||
* were operated through a serial terminal on serial port 2, and were branded
|
||||
* InterServe rather than InterPro.
|
||||
*
|
||||
* Model Year Performance
|
||||
* GT 1990? 360k 2D vec/s (in a 2020)
|
||||
* EDGE-1
|
||||
* EDGE-2
|
||||
* EDGE-1 8 planes + 1 highlight plane, double buffered (6040)
|
||||
* EDGE-2 24 bit, 400k 2D vec/s, 350k 3D vec/s (6280)
|
||||
* GT+ 760k 2D vec/s, 530k 3D vec/s (in a 2730)
|
||||
* GTII 830k 2D vec/s, 640k 3D vec/s (in a 6750)
|
||||
* 900k 2D vec/s, 700k 3D vec/s (in a 6850)
|
||||
* EDGE II+ 50k Gouraud-shaded poly/s (in a 6780)
|
||||
*
|
||||
* GT graphics are also referred to in various places as Memory Mapped Graphics
|
||||
* or MMG. EDGE stands for Extensible Display Geometry Engine.
|
||||
*
|
||||
* This emulation currently supports the Turquoise and Sapphire desktop systems (i.e. models
|
||||
* 2000/2400/2500/2700/2800). Base GT graphics can be used with any of these models, or the
|
||||
* graphics and keyboard removed and the systems used with a serial terminal instead.
|
||||
*
|
||||
* Key parts lists for the supported models are as follows.
|
||||
*
|
||||
* 2000 Turquoise (C300 @ 40MHz?, main board PCB962)
|
||||
* 2000 Turquoise (C300 @ 50MHz?, main board PCB962)
|
||||
*
|
||||
* Ref Part Function
|
||||
* U37 Intel 82072 Floppy drive controller
|
||||
@ -103,16 +114,16 @@
|
||||
* U34 Xilinix XC3020-50 Plotter control FPGA?
|
||||
* U35 128 kB EPROM (MPRGW510B) Boot ROM
|
||||
* U43? (MPRGM610P) Bitstream for XC3020?
|
||||
* U44 Intel 82596SX Ethernet controller (20MHz)
|
||||
* U67 Intel N28F010-200 128Kx8 flash memory (200ns)
|
||||
* U44 Intel 82596SX-20 Ethernet controller
|
||||
* U67 Intel N28F010-200 128Kx8 flash memory (Y226 0B03 0592)
|
||||
* U68 CYID21603 TC150G89AF
|
||||
* U71 LSI L1A6104 CICD 95801 Intergraph I/O gate array
|
||||
* U76 Intel N28F010-200 128Kx8 flash memory (200ns)
|
||||
* U76 Intel N28F010-200 128Kx8 flash memory (Y225 0B?? 27??)
|
||||
* U81 NCR 53C94 SCSI controller
|
||||
* U86 24.0 MHz crystal Clock source for 53C94?
|
||||
* U87 4.9152 MHz crystal Clock source for 8530s?
|
||||
* U88 20.0 MHz crystal Clock source for 82596?
|
||||
* U91 Intel N82077AA Floppy drive controller
|
||||
* U91 Intel N82077AA-1 Floppy drive controller
|
||||
* U96 32.0 MHz crystal
|
||||
* U97 40.0 MHz crystal
|
||||
* U112? (MPRG4230A) node ID prom?
|
||||
@ -129,23 +140,40 @@
|
||||
* U34 Xilinix XC3020-70 Plotter control FPGA?
|
||||
* U35 128 kB EPROM (MPRGZ530A) Boot ROM
|
||||
* U43? (MPRGM610P) Bitstream for XC3020?
|
||||
* U44 Intel 82596SX? Ethernet controller
|
||||
* U44 Intel 82596SX-20 Ethernet controller
|
||||
* U68 CYID21603 TC150G89AF
|
||||
* U67 Intel N28F010 128Kx8 flash memory
|
||||
* U67 Intel N28F010 128Kx8 flash memory (Y226 0C30 4291)
|
||||
* U71 LSI L1A7374 CIDC094A3 Intergraph I/O gate array
|
||||
* U76 Intel N28F010 128Kx8 flash memory
|
||||
* U76 Intel N28F010 128Kx8 flash memory (Y225 0C30 4220)
|
||||
* U81 NCR 53C94 SCSI controller
|
||||
* U86 24.0 MHz crystal Clock source for 53C94?
|
||||
* U86 24.0 MHz crystal Clock source for 82077
|
||||
* U87 4.9152 MHz crystal Clock source for 8530s?
|
||||
* U88 20.0 MHz crystal Clock source for 82596?
|
||||
* U91 Intel N82077AA? Floppy drive controller
|
||||
* U96 32.0 MHz crystal?
|
||||
* U91 Intel N82077SL-1 Floppy drive controller
|
||||
* U96 29.0 MHz crystal
|
||||
* U97 40.0 MHz crystal
|
||||
* U112? (MPRGZ260E) node ID prom?
|
||||
* U113? Dallas DS12887 RTC and NVRAM
|
||||
* U113 Dallas DS12887 RTC and NVRAM
|
||||
* U117? diagnostic 7-segment LED?
|
||||
* U118? ()
|
||||
* U155 CYID212?4 TC140G54AF?
|
||||
*
|
||||
* CPU daughter-boards
|
||||
* PCB824 Rev J - 2000 (also has label MPCBA5507)
|
||||
* SMT082 (MSMT0820B, 36MHz?) - 6400 (SMT046 "6400 36-MHz Series System Board")
|
||||
* SMT03? 2400/6400 - (MSMT03804 -> rev 2 cammu, goes with "6400 36-MHz Series System Board", MSMT0380A eco 3+ use rev 3 cammu)
|
||||
* SMT019 (MSMT019 C4E CPU Assembly)
|
||||
* SMT104 Rev A - 2700/6700 (aka MSMT1040A "C4I CPU", C4 CPU REV 3 + C4 FPU REV 3 + C4I CAMMU)
|
||||
*
|
||||
* PCB962 2000 System Board MPCB824 C300
|
||||
* SMT046 6400 36-MHz Series System Board MSMT03804 rev 2 CAMMU/30MHz Kryptonite Rev 3 CAMMU/32MHz Kryptonite Rev 3 CAMMU/MSMT0820B(36MHz)
|
||||
* SMT047 2400 Series System Board MSMT03804 rev 2 CAMMU/MSMT0380A eco 3+ Rev 3 CAMMU
|
||||
* SMT098A 6400 32-MHz Sapphire System Board
|
||||
* SMT098B 6400 32-MHz Sapphire System Board
|
||||
* SMT127 6700 Series System Board MSMT1040A C4I: C4 CPU Rev 3 + C4 FPU Rev 3 + C4I CAMMU
|
||||
* SMT128 2700 Series System Board MSMT1040A C4I: C4 CPU Rev 3 + C4 FPU Rev 3 + C4I CAMMU
|
||||
* SMT144 6800 Series System Board
|
||||
* SMT145 2800 Series System Board
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -184,12 +212,6 @@ void interpro_state::machine_reset()
|
||||
|
||||
DRIVER_INIT_MEMBER(interpro_state, common)
|
||||
{
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(turquoise_state, turquoise)
|
||||
{
|
||||
interpro_state::init_common();
|
||||
|
||||
// FIXME: not all memory sizes are reported properly using fdm "5 inqhw" and
|
||||
// "optimum_memory" commands
|
||||
|
||||
@ -200,25 +222,7 @@ DRIVER_INIT_MEMBER(turquoise_state, turquoise)
|
||||
// 256 = reports 256M, 32x8
|
||||
|
||||
// map the configured ram
|
||||
m_d_cammu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer());
|
||||
m_i_cammu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer());
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(sapphire_state, sapphire)
|
||||
{
|
||||
interpro_state::init_common();
|
||||
|
||||
// FIXME: not all memory sizes are reported properly using fdm "5 inqhw" and
|
||||
// "optimum_memory" commands
|
||||
|
||||
// 16 = reports 16M, banks empty?
|
||||
// 32 = reports 16M, banks empty?
|
||||
// 64 = reports 128M, 16x8
|
||||
// 128 = reports 128M, 16x8
|
||||
// 256 = reports 256M, 32x8
|
||||
|
||||
// map the configured ram
|
||||
m_mmu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer());
|
||||
m_maincpu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer());
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(interpro_state::sreg_led_w)
|
||||
@ -275,7 +279,7 @@ READ16_MEMBER(interpro_state::sreg_error_r)
|
||||
return result;
|
||||
}
|
||||
|
||||
READ32_MEMBER(interpro_state::unmapped_r)
|
||||
READ32_MEMBER(sapphire_state::unmapped_r)
|
||||
{
|
||||
// check if non-existent memory errors are enabled
|
||||
if (!machine().side_effects_disabled())
|
||||
@ -291,7 +295,7 @@ READ32_MEMBER(interpro_state::unmapped_r)
|
||||
return space.unmap();
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(interpro_state::unmapped_w)
|
||||
WRITE32_MEMBER(sapphire_state::unmapped_w)
|
||||
{
|
||||
// check if non-existent memory errors are enabled
|
||||
if (m_arbga->tctrl_r(space, offset, mem_mask) & interpro_arbga_device::TCTRL_ENNEM)
|
||||
@ -319,23 +323,6 @@ READ8_MEMBER(interpro_state::nodeid_r)
|
||||
return space.unmap();
|
||||
}
|
||||
|
||||
// these maps connect the cpu virtual addresses to the mmu
|
||||
ADDRESS_MAP_START(interpro_state::c300_insn_map)
|
||||
AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD(INTERPRO_MMU_TAG "_i", cammu_device, read)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START(interpro_state::c300_data_map)
|
||||
AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE(INTERPRO_MMU_TAG "_d", cammu_device, read, write)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START(interpro_state::c400_insn_map)
|
||||
AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD(INTERPRO_MMU_TAG, cammu_device, read)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START(interpro_state::c400_data_map)
|
||||
AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE(INTERPRO_MMU_TAG, cammu_device, read, write)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START(interpro_state::interpro_common_map)
|
||||
// FIXME: don't know what this range is for
|
||||
AM_RANGE(0x08000000, 0x08000fff) AM_NOP
|
||||
@ -343,7 +330,6 @@ ADDRESS_MAP_START(interpro_state::interpro_common_map)
|
||||
AM_RANGE(0x4f007e00, 0x4f007eff) AM_DEVICE(INTERPRO_SGA_TAG, interpro_sga_device, map)
|
||||
|
||||
AM_RANGE(0x7f000100, 0x7f00011f) AM_DEVICE8(INTERPRO_FDC_TAG, upd765_family_device, map, 0x000000ff)
|
||||
AM_RANGE(0x7f000200, 0x7f0002ff) AM_DEVICE(INTERPRO_ARBGA_TAG, interpro_arbga_device, map)
|
||||
AM_RANGE(0x7f000300, 0x7f000303) AM_READ16(sreg_error_r, 0x0000ffff)
|
||||
AM_RANGE(0x7f000304, 0x7f000307) AM_READWRITE16(sreg_status_r, sreg_led_w, 0x0000ffff)
|
||||
AM_RANGE(0x7f000308, 0x7f00030b) AM_READWRITE16(sreg_ctrl1_r, sreg_ctrl1_w, 0x0000ffff)
|
||||
@ -356,25 +342,10 @@ ADDRESS_MAP_START(interpro_state::interpro_common_map)
|
||||
|
||||
;map(0x7f000500, 0x7f000503).lrw8("rtc_rw", [this](address_space &space, offs_t offset, u8 mem_mask){ return m_rtc->read(space, offset^1, mem_mask); }, [this](address_space &space, offs_t offset, u8 data, u8 mem_mask){ m_rtc->write(space, offset^1, data, mem_mask); }).umask32(0x000000ff);
|
||||
AM_RANGE(0x7f000600, 0x7f000603) AM_DEVWRITE8(INTERPRO_RTC_TAG, mc146818_device, write, 0x000000ff)
|
||||
AM_RANGE(0x7f000600, 0x7f00060f) AM_READ8(nodeid_r, 0xff)
|
||||
|
||||
// the system board id prom
|
||||
AM_RANGE(0x7f000700, 0x7f00077f) AM_ROM AM_REGION(INTERPRO_IDPROM_TAG, 0)
|
||||
|
||||
// scsi registers have unusual address mapping
|
||||
AM_RANGE(0x7f001000, 0x7f001003) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, tcounter_lo_r, tcount_lo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001100, 0x7f001103) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, tcounter_hi_r, tcount_hi_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001200, 0x7f001203) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, fifo_r, fifo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001300, 0x7f001303) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, command_r, command_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001400, 0x7f001403) AM_DEVREAD8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, status_r, 0xff00) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, bus_id_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001500, 0x7f001503) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, istatus_r, timeout_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001600, 0x7f001603) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, seq_step_r, sync_period_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001700, 0x7f001703) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, fifo_flags_r, sync_offset_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001800, 0x7f001803) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, conf_r, conf_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001900, 0x7f001903) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, clock_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001a00, 0x7f001a03) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, test_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001b00, 0x7f001b03) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, conf2_r, conf2_w, 0x0000ff00)
|
||||
|
||||
AM_RANGE(0x7f0fff00, 0x7f0fffff) AM_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, map)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
@ -382,7 +353,24 @@ ADDRESS_MAP_START(turquoise_state::turquoise_base_map)
|
||||
AM_IMPORT_FROM(interpro_common_map)
|
||||
|
||||
AM_RANGE(0x40000000, 0x4000003f) AM_DEVICE(INTERPRO_MCGA_TAG, interpro_mcga_device, map)
|
||||
|
||||
// scsi registers have unusual address mapping
|
||||
AM_RANGE(0x7f000200, 0x7f000203) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, tcounter_lo_r, tcount_lo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000204, 0x7f000207) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, tcounter_hi_r, tcount_hi_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000208, 0x7f00020b) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, fifo_r, fifo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f00020c, 0x7f00020f) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, command_r, command_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000210, 0x7f000213) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, status_r, bus_id_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000214, 0x7f000217) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, istatus_r, timeout_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000218, 0x7f00021b) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, seq_step_r, sync_period_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f00021c, 0x7f00021f) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, fifo_flags_r, sync_offset_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000220, 0x7f000223) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, conf_r, conf_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000224, 0x7f000227) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, clock_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f000228, 0x7f00022b) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, test_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f00022c, 0x7f00022f) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, conf2_r, conf2_w, 0x0000ff00)
|
||||
|
||||
AM_RANGE(0x7f000300, 0x7f000303) AM_WRITE8(sreg_error_w, 0x000000ff)
|
||||
|
||||
AM_RANGE(0x7f000600, 0x7f00067f) AM_ROM AM_REGION(INTERPRO_NODEID_TAG, 0)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START(turquoise_state::turquoise_main_map)
|
||||
@ -396,6 +384,23 @@ ADDRESS_MAP_START(sapphire_state::sapphire_base_map)
|
||||
AM_IMPORT_FROM(interpro_common_map)
|
||||
|
||||
AM_RANGE(0x40000000, 0x4000004f) AM_DEVICE(INTERPRO_MCGA_TAG, interpro_fmcc_device, map)
|
||||
AM_RANGE(0x7f000200, 0x7f0002ff) AM_DEVICE(INTERPRO_ARBGA_TAG, interpro_arbga_device, map)
|
||||
|
||||
AM_RANGE(0x7f000600, 0x7f00060f) AM_READ8(nodeid_r, 0xff)
|
||||
|
||||
// scsi registers have unusual address mapping
|
||||
AM_RANGE(0x7f001000, 0x7f001003) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, tcounter_lo_r, tcount_lo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001100, 0x7f001103) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, tcounter_hi_r, tcount_hi_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001200, 0x7f001203) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, fifo_r, fifo_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001300, 0x7f001303) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, command_r, command_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001400, 0x7f001403) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, status_r, bus_id_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001500, 0x7f001503) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, istatus_r, timeout_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001600, 0x7f001603) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, seq_step_r, sync_period_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001700, 0x7f001703) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, fifo_flags_r, sync_offset_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001800, 0x7f001803) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, conf_r, conf_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001900, 0x7f001903) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, clock_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001a00, 0x7f001a03) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, test_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001b00, 0x7f001b03) AM_DEVREADWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, conf2_r, conf2_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001c00, 0x7f001c03) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, conf3_w, 0x0000ff00)
|
||||
AM_RANGE(0x7f001f00, 0x7f001f03) AM_DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, fifo_align_w, 0x0000ff00)
|
||||
ADDRESS_MAP_END
|
||||
@ -448,9 +453,8 @@ static SLOT_INTERFACE_START(interpro_floppies)
|
||||
SLOT_INTERFACE("35hd", FLOPPY_35_HD)
|
||||
SLOT_INTERFACE_END
|
||||
|
||||
MACHINE_CONFIG_START(interpro_state::interpro_serial1)
|
||||
MCFG_SCC85C30_ADD(INTERPRO_SCC1_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
|
||||
MACHINE_CONFIG_START(interpro_state::interpro_scc1)
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_SCC1_TAG)
|
||||
MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(INTERPRO_SERIAL_PORT1_TAG, rs232_port_device, write_txd))
|
||||
MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(INTERPRO_SERIAL_PORT2_TAG, rs232_port_device, write_txd))
|
||||
MCFG_Z80SCC_OUT_INT_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir11_w))
|
||||
@ -468,8 +472,8 @@ MACHINE_CONFIG_START(interpro_state::interpro_serial1)
|
||||
MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsb_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(interpro_state::interpro_serial2)
|
||||
MCFG_SCC85C30_ADD(INTERPRO_SCC2_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
MACHINE_CONFIG_START(interpro_state::interpro_scc2)
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_SCC2_TAG)
|
||||
MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(INTERPRO_KEYBOARD_PORT_TAG, interpro_keyboard_port_device, write_txd))
|
||||
MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(INTERPRO_SERIAL_PORT0_TAG, rs232_port_device, write_txd))
|
||||
MCFG_Z80SCC_OUT_INT_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir11_w))
|
||||
@ -542,9 +546,6 @@ MACHINE_CONFIG_START(interpro_state::interpro)
|
||||
|
||||
// floppy
|
||||
|
||||
// srx arbiter gate array
|
||||
MCFG_DEVICE_ADD(INTERPRO_ARBGA_TAG, INTERPRO_ARBGA, 0)
|
||||
|
||||
// serial
|
||||
|
||||
// real-time clock/non-volatile memory
|
||||
@ -557,8 +558,8 @@ MACHINE_CONFIG_START(interpro_state::interpro)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":0", interpro_scsi_devices, "harddisk", false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":1", interpro_scsi_devices, nullptr, false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":2", interpro_scsi_devices, nullptr, false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":3", interpro_scsi_devices, "cdrom", false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":4", interpro_scsi_devices, nullptr, false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":3", interpro_scsi_devices, nullptr, false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":4", interpro_scsi_devices, "cdrom", false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":5", interpro_scsi_devices, nullptr, false)
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":6", interpro_scsi_devices, nullptr, false)
|
||||
|
||||
@ -568,32 +569,29 @@ MACHINE_CONFIG_START(interpro_state::interpro)
|
||||
|
||||
// sr bus and slots
|
||||
MCFG_DEVICE_ADD(INTERPRO_SRBUS_TAG, SR, 0)
|
||||
MCFG_SR_OUT_IRQ0_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir6_w))
|
||||
MCFG_SR_SLOT_ADD(INTERPRO_SRBUS_TAG, INTERPRO_SRBUS_TAG ":0", sr_cards, "mpcb963", false)
|
||||
MCFG_SR_SLOT_ADD(INTERPRO_SRBUS_TAG, INTERPRO_SRBUS_TAG ":1", sr_cards, nullptr, false)
|
||||
|
||||
// system layout
|
||||
MCFG_DEFAULT_LAYOUT(layout_interpro)
|
||||
|
||||
// software lists
|
||||
MCFG_SOFTWARE_LIST_ADD("softlist", "interpro")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(turquoise_state::turquoise)
|
||||
interpro(config);
|
||||
MCFG_CPU_ADD(INTERPRO_CPU_TAG, CLIPPER_C300, XTAL(12'500'000))
|
||||
MCFG_CPU_PROGRAM_MAP(c300_insn_map)
|
||||
MCFG_CPU_DATA_MAP(c300_data_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(0, turquoise_main_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(1, turquoise_io_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, acknowledge_interrupt)
|
||||
|
||||
MCFG_DEVICE_ADD(INTERPRO_MMU_TAG "_i", CAMMU_C3, 0)
|
||||
MCFG_DEVICE_ADDRESS_MAP(0, turquoise_main_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(1, turquoise_io_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map)
|
||||
MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw))
|
||||
MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception))
|
||||
|
||||
MCFG_DEVICE_ADD(INTERPRO_MMU_TAG "_d", CAMMU_C3, 0)
|
||||
MCFG_DEVICE_ADDRESS_MAP(0, turquoise_main_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(1, turquoise_io_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map)
|
||||
MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw))
|
||||
MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception))
|
||||
MCFG_CAMMU_LINK(INTERPRO_MMU_TAG "_i")
|
||||
|
||||
@ -617,8 +615,10 @@ MACHINE_CONFIG_START(turquoise_state::turquoise)
|
||||
MCFG_FLOPPY_DRIVE_SOUND(false)
|
||||
|
||||
// serial controllers and ports
|
||||
interpro_serial1(config);
|
||||
interpro_serial2(config);
|
||||
MCFG_SCC85C30_ADD(INTERPRO_SCC1_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
interpro_scc1(config);
|
||||
MCFG_SCC85C30_ADD(INTERPRO_SCC2_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
interpro_scc2(config);
|
||||
|
||||
// scsi controller
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":7", turquoise_scsi_devices, INTERPRO_SCSI_ADAPTER_TAG, true)
|
||||
@ -631,25 +631,23 @@ MACHINE_CONFIG_START(turquoise_state::turquoise)
|
||||
|
||||
// i/o gate array
|
||||
MCFG_DEVICE_ADD(INTERPRO_IOGA_TAG, TURQUOISE_IOGA, 0)
|
||||
MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_MMU_TAG "_d", 0)
|
||||
MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_CPU_TAG, 0)
|
||||
ioga(config);
|
||||
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_SRBUS_TAG)
|
||||
MCFG_SR_MEMORY(INTERPRO_MMU_TAG "_d", 0, 1)
|
||||
MCFG_SR_MEMORY(INTERPRO_CPU_TAG, 0, 1)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(sapphire_state::sapphire)
|
||||
interpro(config);
|
||||
MCFG_CPU_ADD(INTERPRO_CPU_TAG, CLIPPER_C400, XTAL(12'500'000))
|
||||
MCFG_CPU_PROGRAM_MAP(c400_insn_map)
|
||||
MCFG_CPU_DATA_MAP(c400_data_map)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, acknowledge_interrupt)
|
||||
|
||||
MCFG_DEVICE_ADD(INTERPRO_MMU_TAG, CAMMU_C4T, 0)
|
||||
MCFG_DEVICE_ADDRESS_MAP(0, sapphire_main_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(1, sapphire_io_map)
|
||||
MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map)
|
||||
MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw))
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, acknowledge_interrupt)
|
||||
|
||||
// FIXME: 2400/6400 should be C4T cammu?
|
||||
MCFG_DEVICE_ADD(INTERPRO_MMU_TAG, CAMMU_C4I, 0)
|
||||
MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception))
|
||||
|
||||
// memory control gate array
|
||||
@ -665,22 +663,27 @@ MACHINE_CONFIG_START(sapphire_state::sapphire)
|
||||
MCFG_FLOPPY_DRIVE_ADD("fdc:1", interpro_floppies, "35hd", interpro_state::floppy_formats)
|
||||
MCFG_FLOPPY_DRIVE_SOUND(false)
|
||||
|
||||
// srx arbiter gate array
|
||||
MCFG_DEVICE_ADD(INTERPRO_ARBGA_TAG, INTERPRO_ARBGA, 0)
|
||||
|
||||
// serial controllers and ports
|
||||
interpro_serial1(config);
|
||||
interpro_serial2(config);
|
||||
MCFG_SCC85230_ADD(INTERPRO_SCC1_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
interpro_scc1(config);
|
||||
MCFG_SCC85C30_ADD(INTERPRO_SCC2_TAG, XTAL(4'915'200), 0, 0, 0, 0)
|
||||
interpro_scc2(config);
|
||||
|
||||
// scsi controller
|
||||
MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":7", sapphire_scsi_devices, INTERPRO_SCSI_ADAPTER_TAG, true)
|
||||
MCFG_DEVICE_CARD_MACHINE_CONFIG(INTERPRO_SCSI_ADAPTER_TAG, interpro_scsi_adapter)
|
||||
|
||||
// ethernet controller
|
||||
MCFG_DEVICE_ADD(INTERPRO_ETH_TAG, I82596_LE32, XTAL(20'000'000))
|
||||
MCFG_DEVICE_ADD(INTERPRO_ETH_TAG, I82596_LE16, XTAL(20'000'000))
|
||||
MCFG_I82586_IRQ_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir12_w))
|
||||
MCFG_DEVICE_ADDRESS_MAP(0, interpro_82596_map)
|
||||
|
||||
// i/o gate array
|
||||
MCFG_DEVICE_ADD(INTERPRO_IOGA_TAG, SAPPHIRE_IOGA, 0)
|
||||
MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_MMU_TAG, 0)
|
||||
MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_CPU_TAG, 0)
|
||||
ioga(config);
|
||||
|
||||
// flash memory
|
||||
@ -689,42 +692,72 @@ MACHINE_CONFIG_START(sapphire_state::sapphire)
|
||||
|
||||
// sr bus address spaces
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_SRBUS_TAG)
|
||||
MCFG_SR_MEMORY(INTERPRO_MMU_TAG, 0, 1)
|
||||
MCFG_SR_MEMORY(INTERPRO_CPU_TAG, 0, 1)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(turquoise_state::ip2000)
|
||||
turquoise(config);
|
||||
//MCFG_DEVICE_MODIFY(INTERPRO_CPU_TAG)
|
||||
//MCFG_DEVICE_CLOCK(XTAL(40'000'000))
|
||||
|
||||
MCFG_SOFTWARE_LIST_FILTER("softlist", "2000")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(sapphire_state::ip2400)
|
||||
sapphire(config);
|
||||
//MCFG_DEVICE_MODIFY(INTERPRO_CPU_TAG)
|
||||
//MCFG_DEVICE_CLOCK(XTAL(40'000'000))
|
||||
//MCFG_DEVICE_CLOCK(XTAL(50'000'000))
|
||||
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_MMU_TAG)
|
||||
MCFG_CAMMU_ID(cammu_c4i_device::CID_C4IR0)
|
||||
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_SRBUS_TAG ":0")
|
||||
MCFG_SLOT_DEFAULT_OPTION("mpcb070")
|
||||
|
||||
MCFG_SOFTWARE_LIST_FILTER("softlist", "2400")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(sapphire_state::ip2500)
|
||||
sapphire(config);
|
||||
//MCFG_DEVICE_MODIFY(INTERPRO_CPU_TAG)
|
||||
//MCFG_DEVICE_CLOCK(XTAL(50'000'000))
|
||||
//MCFG_DEVICE_CLOCK(XTAL(?)
|
||||
|
||||
// FIXME: don't know which cammu revision
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_MMU_TAG)
|
||||
MCFG_CAMMU_ID(cammu_c4i_device::CID_C4IR0)
|
||||
|
||||
MCFG_SOFTWARE_LIST_FILTER("softlist", "2500")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(sapphire_state::ip2700)
|
||||
sapphire(config);
|
||||
//MCFG_DEVICE_MODIFY(INTERPRO_CPU_TAG)
|
||||
//MCFG_DEVICE_CLOCK(XTAL_70MHz)
|
||||
//MCFG_DEVICE_CLOCK(?)
|
||||
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_MMU_TAG)
|
||||
MCFG_CAMMU_ID(cammu_c4i_device::CID_C4IR2)
|
||||
|
||||
MCFG_SOFTWARE_LIST_FILTER("softlist", "2700")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(sapphire_state::ip2800)
|
||||
sapphire(config);
|
||||
//MCFG_DEVICE_MODIFY(INTERPRO_CPU_TAG)
|
||||
//MCFG_DEVICE_CLOCK(XTAL_80MHz)
|
||||
//MCFG_DEVICE_CLOCK(?)
|
||||
|
||||
// FIXME: don't know which cammu revision
|
||||
MCFG_DEVICE_MODIFY(INTERPRO_MMU_TAG)
|
||||
MCFG_CAMMU_ID(cammu_c4i_device::CID_C4IR2)
|
||||
|
||||
MCFG_SOFTWARE_LIST_FILTER("softlist", "2800")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(ip2000)
|
||||
ROM_REGION(0x80, INTERPRO_NODEID_TAG, 0)
|
||||
ROM_LOAD32_BYTE("nodeid.bin", 0x0, 0x20, CRC(a38397a6) SHA1(9f45fb932bbe231c95b3d5470dcd1fa1c846486f))
|
||||
|
||||
ROM_REGION(0x80, INTERPRO_IDPROM_TAG, 0)
|
||||
ROM_LOAD32_BYTE("mpcb962a.bin", 0x0, 0x20, CRC(712f5ba9) SHA1(93ccdcb68be4038bb35b02cee612927ad4451190))
|
||||
ROM_LOAD32_BYTE("mpcb962a.bin", 0x0, 0x20, CRC(e391342c) SHA1(02e03aad760b6651b8599c3a41c7c457983ee97d))
|
||||
|
||||
ROM_REGION(0x0040000, INTERPRO_EPROM_TAG, 0)
|
||||
ROM_SYSTEM_BIOS(0, "ip2000", "InterPro 2000 EPROM")
|
||||
@ -734,7 +767,7 @@ ROM_END
|
||||
|
||||
ROM_START(ip2400)
|
||||
ROM_REGION(0x80, INTERPRO_IDPROM_TAG, 0)
|
||||
ROM_LOAD32_BYTE("msmt047a.bin", 0x0, 0x20, CRC(3078d84d) SHA1(2876b8b8054bb7528680d259fea428db6f1712b4))
|
||||
ROM_LOAD32_BYTE("msmt0470.bin", 0x0, 0x20, CRC(498c80df) SHA1(18a49732ac9d04b20a77747c1b946c2e88abb087))
|
||||
|
||||
ROM_REGION(0x0020000, INTERPRO_EPROM_TAG, 0)
|
||||
ROM_SYSTEM_BIOS(0, "ip2400", "InterPro 2400 EPROM")
|
||||
@ -749,7 +782,7 @@ ROM_END
|
||||
|
||||
ROM_START(ip2500)
|
||||
ROM_REGION(0x80, INTERPRO_IDPROM_TAG, 0)
|
||||
ROM_LOAD32_BYTE("msmt100a.bin", 0x0, 0x20, CRC(46647cdf) SHA1(581a3424a9b7028e619a7f03fa86ebdee3cf2494))
|
||||
ROM_LOAD32_BYTE("msmt1000.bin", 0x0, 0x20, CRC(548046c0) SHA1(ce7646e868f3aa35642d7f9348f6b9e91693918e))
|
||||
|
||||
ROM_REGION(0x0020000, INTERPRO_EPROM_TAG, 0)
|
||||
ROM_SYSTEM_BIOS(0, "ip2500", "InterPro 2500 EPROM")
|
||||
@ -764,7 +797,7 @@ ROM_END
|
||||
|
||||
ROM_START(ip2700)
|
||||
ROM_REGION(0x80, INTERPRO_IDPROM_TAG, 0)
|
||||
ROM_LOAD32_BYTE("msmt128a.bin", 0x0, 0x20, CRC(6d8e68e8) SHA1(a649097df730c79b03bbf777b788f0721e072f03))
|
||||
ROM_LOAD32_BYTE("msmt1280.bin", 0x0, 0x20, CRC(32d833af) SHA1(7225c5f5670fe49d86556a2cb453ae6fe09e3e19))
|
||||
|
||||
ROM_REGION(0x0020000, INTERPRO_EPROM_TAG, 0)
|
||||
ROM_SYSTEM_BIOS(0, "ip2700", "InterPro 2700 EPROM")
|
||||
@ -779,7 +812,7 @@ ROM_END
|
||||
|
||||
ROM_START(ip2800)
|
||||
ROM_REGION(0x80, INTERPRO_IDPROM_TAG, 0)
|
||||
ROM_LOAD32_BYTE("msmt145a.bin", 0x0, 0x20, CRC(e1c265e3) SHA1(105d646552d56c7af2f403aac1aa97b047b6a50e))
|
||||
ROM_LOAD32_BYTE("msmt1450.bin", 0x0, 0x20, CRC(61c7a305) SHA1(efcd045cbdfda8df44eaad761b0ba99367973cd7))
|
||||
|
||||
ROM_REGION(0x0020000, INTERPRO_EPROM_TAG, 0)
|
||||
ROM_SYSTEM_BIOS(0, "ip2800", "InterPro 2800 EPROM")
|
||||
@ -793,8 +826,8 @@ ROM_START(ip2800)
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 1989, ip2000, 0, 0, ip2000, interpro, turquoise_state, turquoise, "Intergraph", "InterPro 2000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1991?, ip2400, 0, 0, ip2400, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2400", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1993?, ip2500, 0, 0, ip2500, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2500", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1992, ip2700, 0, 0, ip2700, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2700", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1994, ip2800, 0, 0, ip2800, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2800", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1990, ip2000, 0, 0, ip2000, interpro, turquoise_state, common, "Intergraph", "InterPro 2000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1992, ip2400, 0, 0, ip2400, interpro, sapphire_state, common, "Intergraph", "InterPro 2400", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1993, ip2500, 0, 0, ip2500, interpro, sapphire_state, common, "Intergraph", "InterPro 2500", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1993, ip2700, 0, 0, ip2700, interpro, sapphire_state, common, "Intergraph", "InterPro 2700", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1994, ip2800, 0, 0, ip2800, interpro, sapphire_state, common, "Intergraph", "InterPro 2800", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
|
@ -33,9 +33,10 @@
|
||||
#include "bus/interpro/keyboard/keyboard.h"
|
||||
|
||||
#include "formats/pc_dsk.h"
|
||||
#include "softlist.h"
|
||||
|
||||
#define INTERPRO_CPU_TAG "cpu"
|
||||
#define INTERPRO_MMU_TAG "mmu"
|
||||
#define INTERPRO_MMU_TAG "cammu"
|
||||
#define INTERPRO_MCGA_TAG "mcga"
|
||||
#define INTERPRO_SGA_TAG "sga"
|
||||
#define INTERPRO_FDC_TAG "fdc"
|
||||
@ -53,6 +54,7 @@
|
||||
#define INTERPRO_ETH_TAG "eth"
|
||||
#define INTERPRO_IOGA_TAG "ioga"
|
||||
|
||||
#define INTERPRO_NODEID_TAG "nodeid"
|
||||
#define INTERPRO_IDPROM_TAG "idprom"
|
||||
#define INTERPRO_EPROM_TAG "eprom"
|
||||
#define INTERPRO_FLASH_TAG "flash"
|
||||
@ -69,12 +71,10 @@ public:
|
||||
, m_mcga(*this, INTERPRO_MCGA_TAG)
|
||||
, m_sga(*this, INTERPRO_SGA_TAG)
|
||||
, m_fdc(*this, INTERPRO_FDC_TAG)
|
||||
, m_arbga(*this, INTERPRO_ARBGA_TAG)
|
||||
, m_scc1(*this, INTERPRO_SCC1_TAG)
|
||||
, m_scc2(*this, INTERPRO_SCC2_TAG)
|
||||
, m_rtc(*this, INTERPRO_RTC_TAG)
|
||||
, m_scsibus(*this, INTERPRO_SCSI_TAG)
|
||||
, m_scsi(*this, INTERPRO_SCSI_DEVICE_TAG)
|
||||
, m_eth(*this, INTERPRO_ETH_TAG)
|
||||
, m_ioga(*this, INTERPRO_IOGA_TAG)
|
||||
{
|
||||
@ -86,12 +86,10 @@ public:
|
||||
required_device<interpro_mcga_device> m_mcga;
|
||||
required_device<interpro_sga_device> m_sga;
|
||||
required_device<upd765_family_device> m_fdc;
|
||||
required_device<interpro_arbga_device> m_arbga;
|
||||
required_device<z80scc_device> m_scc1;
|
||||
required_device<z80scc_device> m_scc2;
|
||||
required_device<mc146818_device> m_rtc;
|
||||
required_device<nscsi_bus_device> m_scsibus;
|
||||
required_device<ncr53c90a_device> m_scsi;
|
||||
required_device<i82586_base_device> m_eth;
|
||||
required_device<interpro_ioga_device> m_ioga;
|
||||
|
||||
@ -156,22 +154,16 @@ public:
|
||||
|
||||
DECLARE_READ8_MEMBER(nodeid_r);
|
||||
|
||||
DECLARE_READ32_MEMBER(unmapped_r);
|
||||
DECLARE_WRITE32_MEMBER(unmapped_w);
|
||||
|
||||
DECLARE_FLOPPY_FORMATS(floppy_formats);
|
||||
|
||||
void ioga(machine_config &config);
|
||||
void interpro_serial1(machine_config &config);
|
||||
void interpro_serial2(machine_config &config);
|
||||
void interpro_scc1(machine_config &config);
|
||||
void interpro_scc2(machine_config &config);
|
||||
void interpro(machine_config &config);
|
||||
static void interpro_scsi_adapter(device_t *device);
|
||||
void c300_data_map(address_map &map);
|
||||
void c300_insn_map(address_map &map);
|
||||
void c400_data_map(address_map &map);
|
||||
void c400_insn_map(address_map &map);
|
||||
void interpro_boot_map(address_map &map);
|
||||
void interpro_common_map(address_map &map);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
@ -192,15 +184,16 @@ public:
|
||||
: interpro_state(mconfig, type, tag)
|
||||
, m_d_cammu(*this, INTERPRO_MMU_TAG "_d")
|
||||
, m_i_cammu(*this, INTERPRO_MMU_TAG "_i")
|
||||
, m_scsi(*this, INTERPRO_SCSI_DEVICE_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
DECLARE_DRIVER_INIT(turquoise);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(sreg_error_w) { m_sreg_error = data; }
|
||||
|
||||
required_device<cammu_c3_device> m_d_cammu;
|
||||
required_device<cammu_c3_device> m_i_cammu;
|
||||
required_device<ncr53c90a_device> m_scsi;
|
||||
|
||||
void turquoise(machine_config &config);
|
||||
void ip2000(machine_config &config);
|
||||
void interpro_82586_map(address_map &map);
|
||||
@ -215,19 +208,23 @@ public:
|
||||
sapphire_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: interpro_state(mconfig, type, tag)
|
||||
, m_mmu(*this, INTERPRO_MMU_TAG)
|
||||
, m_scsi(*this, INTERPRO_SCSI_DEVICE_TAG)
|
||||
, m_arbga(*this, INTERPRO_ARBGA_TAG)
|
||||
, m_flash_lo(*this, INTERPRO_FLASH_TAG "_lo")
|
||||
, m_flash_hi(*this, INTERPRO_FLASH_TAG "_hi")
|
||||
{
|
||||
}
|
||||
|
||||
DECLARE_DRIVER_INIT(sapphire);
|
||||
|
||||
virtual DECLARE_WRITE16_MEMBER(sreg_ctrl2_w) override;
|
||||
DECLARE_READ32_MEMBER(unmapped_r);
|
||||
DECLARE_WRITE32_MEMBER(unmapped_w);
|
||||
|
||||
required_device<cammu_c4_device> m_mmu;
|
||||
|
||||
required_device<ncr53c94_device> m_scsi;
|
||||
required_device<interpro_arbga_device> m_arbga;
|
||||
required_device<intel_28f010_device> m_flash_lo;
|
||||
required_device<intel_28f010_device> m_flash_hi;
|
||||
|
||||
void sapphire(machine_config &config);
|
||||
void ip2500(machine_config &config);
|
||||
void ip2400(machine_config &config);
|
||||
|
@ -23,7 +23,6 @@
|
||||
*
|
||||
* TODO
|
||||
* - fault register values
|
||||
* - alignment faults
|
||||
* - c3 protection faults
|
||||
* - hard-wired and dynamic tlb
|
||||
* - cache
|
||||
@ -112,18 +111,17 @@ DEFINE_DEVICE_TYPE(CAMMU_C4I, cammu_c4i_device, "c4i", "C4I CAMMU")
|
||||
DEFINE_DEVICE_TYPE(CAMMU_C3, cammu_c3_device, "c3", "C1/C3 CAMMU")
|
||||
|
||||
cammu_c4t_device::cammu_c4t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock, CID_C4T)
|
||||
: cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
cammu_c4i_device::cammu_c4i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock, CID_C4I)
|
||||
: cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u32 cammu_id)
|
||||
cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cammu_device(mconfig, type, tag, owner, clock)
|
||||
, m_control(cammu_id)
|
||||
{
|
||||
}
|
||||
|
||||
@ -136,42 +134,13 @@ cammu_c3_device::cammu_c3_device(const machine_config &mconfig, const char *tag,
|
||||
|
||||
cammu_device::cammu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_memory_interface(mconfig, *this)
|
||||
, m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0)
|
||||
, m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0)
|
||||
, m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0)
|
||||
, m_main_space(nullptr)
|
||||
, m_io_space(nullptr)
|
||||
, m_boot_space(nullptr)
|
||||
, m_ssw_func(*this)
|
||||
, m_exception_func(*this)
|
||||
{
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector cammu_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(0, &m_main_space_config),
|
||||
std::make_pair(1, &m_io_space_config),
|
||||
std::make_pair(2, &m_boot_space_config)
|
||||
};
|
||||
}
|
||||
|
||||
void cammu_c3_device::static_add_linked(device_t &device, const char *const tag)
|
||||
{
|
||||
cammu_c3_device &parent = downcast<cammu_c3_device &>(device);
|
||||
|
||||
parent.m_linked.push_back(downcast<cammu_c3_device *>(parent.siblingdevice(tag)));
|
||||
}
|
||||
|
||||
void cammu_device::device_start()
|
||||
{
|
||||
m_ssw_func.resolve();
|
||||
m_exception_func.resolve();
|
||||
|
||||
m_main_space = &space(0);
|
||||
m_io_space = &space(1);
|
||||
m_boot_space = &space(2);
|
||||
}
|
||||
|
||||
void cammu_device::device_reset()
|
||||
@ -246,238 +215,168 @@ void cammu_c3_device::device_reset()
|
||||
m_reset = 0;
|
||||
}
|
||||
|
||||
READ32_MEMBER(cammu_device::read)
|
||||
void cammu_device::set_spaces(std::vector<address_space *> spaces)
|
||||
{
|
||||
const u32 virtual_address = (offset << 2) | (
|
||||
(mem_mask & 0x00ffffff) == 0 ? 0x3 :
|
||||
(mem_mask & 0x0000ffff) == 0 ? 0x2 :
|
||||
(mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0);
|
||||
offs_t physical_address;
|
||||
assert_always(spaces.size() == 8, "exactly 8 address space pointers are required");
|
||||
|
||||
LOGMASKED(LOG_ACCESS, "%s read address 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
space.name(), virtual_address, mem_mask, machine().describe_context());
|
||||
|
||||
address_space *physical_space = translate_address(virtual_address, space.spacenum() == AS_PROGRAM ? ACCESS_X : ACCESS_R, &physical_address);
|
||||
|
||||
if (physical_space != nullptr)
|
||||
return physical_space->read_dword(physical_address, mem_mask);
|
||||
else
|
||||
return space.unmap();
|
||||
for (int i = 0; i < spaces.size(); i++)
|
||||
m_space[i] = spaces[i];
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(cammu_device::write)
|
||||
cammu_device::translated_t cammu_device::translate_address(const u32 ssw, const u32 virtual_address, const access_size size, const access_type mode)
|
||||
{
|
||||
const u32 virtual_address = (offset << 2) | (
|
||||
(mem_mask & 0x00ffffff) == 0 ? 0x3 :
|
||||
(mem_mask & 0x0000ffff) == 0 ? 0x2 :
|
||||
(mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0);
|
||||
offs_t physical_address;
|
||||
// get effective user/supervisor mode
|
||||
const bool user = mode == EXECUTE ? ssw & SSW_U : ssw & (SSW_U | SSW_UU);
|
||||
|
||||
LOGMASKED(LOG_ACCESS, "%s write address 0x%08x data 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
space.name(), virtual_address, data, mem_mask, machine().describe_context());
|
||||
// check for alignment faults
|
||||
if (get_alignment() && !machine().side_effects_disabled())
|
||||
{
|
||||
if ((mode == EXECUTE && (virtual_address & 0x1)) || (mode != EXECUTE && virtual_address & (size - 1)))
|
||||
{
|
||||
set_fault_address(virtual_address);
|
||||
m_exception_func(mode == EXECUTE ? EXCEPTION_I_ALIGNMENT_FAULT : EXCEPTION_D_ALIGNMENT_FAULT);
|
||||
|
||||
address_space *physical_space = translate_address(virtual_address, ACCESS_W, &physical_address);
|
||||
|
||||
if (physical_space != nullptr)
|
||||
physical_space->write_dword(physical_address, data, mem_mask);
|
||||
}
|
||||
|
||||
address_space *cammu_device::translate_address(const offs_t virtual_address, const access_t mode, offs_t *physical_address)
|
||||
{
|
||||
// get ssw and user/supervisor mode
|
||||
const u32 ssw = m_ssw_func();
|
||||
const bool user = mode == ACCESS_X ? ssw & SSW_U : ssw & (SSW_U | SSW_UU);
|
||||
|
||||
// TODO: check for alignment faults
|
||||
return { nullptr, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
// in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb
|
||||
if (!user && (virtual_address & ~0x7fff) == 0)
|
||||
{
|
||||
switch (virtual_address & 0x7000)
|
||||
{
|
||||
case 0x0000:
|
||||
case 0x1000:
|
||||
case 0x2000:
|
||||
case 0x3000:
|
||||
// pages 0-3: main space pages 0-3
|
||||
*physical_address = virtual_address & 0x3fff;
|
||||
return m_main_space;
|
||||
case 0x0000: return { m_space[ST1], virtual_address & 0x3fff };
|
||||
case 0x1000: return { m_space[ST2], virtual_address & 0x3fff };
|
||||
case 0x2000: return { m_space[ST3], virtual_address & 0x3fff };
|
||||
case 0x3000: return { m_space[ST3], virtual_address & 0x3fff };
|
||||
|
||||
case 0x4000:
|
||||
case 0x5000:
|
||||
// pages 4-5: i/o space pages 0-1
|
||||
*physical_address = virtual_address & 0x1fff;
|
||||
return m_io_space;
|
||||
case 0x4000: return { m_space[ST4], virtual_address & 0x1fff };
|
||||
case 0x5000: return { m_space[ST4], virtual_address & 0x1fff };
|
||||
|
||||
case 0x6000:
|
||||
case 0x7000:
|
||||
// pages 6-7: boot space pages 0-1
|
||||
*physical_address = virtual_address & 0x1fff;
|
||||
return m_boot_space;
|
||||
case 0x6000: return { m_space[ST5], virtual_address & 0x1fff };
|
||||
case 0x7000: return { m_space[ST5], virtual_address & 0x1fff };
|
||||
}
|
||||
}
|
||||
|
||||
// if not in mapped mode, use unmapped system tag
|
||||
if ((ssw & SSW_M) == 0)
|
||||
{
|
||||
*physical_address = virtual_address;
|
||||
|
||||
return get_ust_space();
|
||||
}
|
||||
return { m_space[get_ust_space()], virtual_address };
|
||||
|
||||
// get the page table entry
|
||||
const u32 pte = get_pte(virtual_address, user);
|
||||
pte_t pte = get_pte(virtual_address, user);
|
||||
|
||||
// check for page faults
|
||||
if (pte & PTE_F)
|
||||
if (pte.entry & PTE_F)
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
LOG("%s page fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n",
|
||||
mode == ACCESS_X ? "instruction" : "data",
|
||||
virtual_address, ssw, pte, machine().describe_context());
|
||||
mode == EXECUTE ? "instruction" : "data",
|
||||
virtual_address, ssw, pte.entry, machine().describe_context());
|
||||
|
||||
set_fault_address(virtual_address);
|
||||
m_exception_func(mode == ACCESS_X ? EXCEPTION_I_PAGE_FAULT : EXCEPTION_D_PAGE_FAULT);
|
||||
m_exception_func(mode == EXECUTE ? EXCEPTION_I_PAGE_FAULT : EXCEPTION_D_PAGE_FAULT);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return { nullptr, 0 };
|
||||
}
|
||||
|
||||
// check for protection level faults
|
||||
if (!machine().side_effects_disabled() && !get_access(mode, pte, ssw))
|
||||
if (!machine().side_effects_disabled() && !get_access(mode, pte.entry, ssw))
|
||||
{
|
||||
LOG("%s protection fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n",
|
||||
mode == ACCESS_X ? "execute" : mode == ACCESS_R ? "read" : "write",
|
||||
virtual_address, ssw, pte, machine().describe_context());
|
||||
mode == EXECUTE ? "execute" : mode == READ ? "read" : "write",
|
||||
virtual_address, ssw, pte.entry, machine().describe_context());
|
||||
|
||||
set_fault_address(virtual_address);
|
||||
m_exception_func(
|
||||
mode == ACCESS_X ? EXCEPTION_I_EXECUTE_PROTECT_FAULT :
|
||||
mode == ACCESS_R ? EXCEPTION_D_READ_PROTECT_FAULT :
|
||||
mode == EXECUTE ? EXCEPTION_I_EXECUTE_PROTECT_FAULT :
|
||||
mode == READ ? EXCEPTION_D_READ_PROTECT_FAULT :
|
||||
EXCEPTION_D_WRITE_PROTECT_FAULT);
|
||||
|
||||
return nullptr;
|
||||
return { nullptr, 0 };
|
||||
}
|
||||
|
||||
// set pte referenced and dirty flags
|
||||
if (mode & WRITE && !(pte.entry & PTE_D))
|
||||
m_space[ST0]->write_dword(pte.address, pte.entry | PTE_D | PTE_R);
|
||||
else if (!(pte.entry & PTE_R))
|
||||
m_space[ST0]->write_dword(pte.address, pte.entry | PTE_R);
|
||||
|
||||
// translate the address
|
||||
*physical_address = (pte & ~CAMMU_PAGE_MASK) | (virtual_address & CAMMU_PAGE_MASK);
|
||||
LOGMASKED(LOG_DTU, "%s address translated 0x%08x\n", mode == ACCESS_X ? "instruction" : "data", *physical_address);
|
||||
LOGMASKED(LOG_DTU, "%s address translated 0x%08x\n", mode == EXECUTE ? "instruction" : "data",
|
||||
(pte.entry & ~CAMMU_PAGE_MASK) | (virtual_address & CAMMU_PAGE_MASK));
|
||||
|
||||
// return the physical space based on the system tag
|
||||
switch (pte & PTE_ST)
|
||||
{
|
||||
case ST_0:
|
||||
case ST_1:
|
||||
case ST_2:
|
||||
case ST_3:
|
||||
// main memory space
|
||||
return m_main_space;
|
||||
|
||||
case ST_4:
|
||||
// i/o space
|
||||
return m_io_space;
|
||||
|
||||
case ST_5:
|
||||
// boot space
|
||||
return m_boot_space;
|
||||
|
||||
case ST_6:
|
||||
// cache purge
|
||||
case ST_7:
|
||||
// main memory, slave mode
|
||||
if (!machine().side_effects_disabled())
|
||||
fatalerror("%s page table entry system tag %d not supported\n",
|
||||
mode == ACCESS_X ? "instruction" : "data", (pte & PTE_ST) >> 9);
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
// return the system tag and translated address
|
||||
return { m_space[system_tag_t((pte.entry & PTE_ST) >> PTE_ST_SHIFT)], (pte.entry & ~CAMMU_PAGE_MASK) | (virtual_address & CAMMU_PAGE_MASK) };
|
||||
}
|
||||
|
||||
// return the page table entry for a given virtual address
|
||||
u32 cammu_device::get_pte(const u32 va, const bool user)
|
||||
cammu_device::pte_t cammu_device::get_pte(const u32 va, const bool user)
|
||||
{
|
||||
const u32 tlb_index = user ? 1 : 0;
|
||||
if ((va & ~CAMMU_PAGE_MASK) != m_tlb[tlb_index].va)
|
||||
{
|
||||
// get page table directory origin from user or supervisor pdo register
|
||||
const u32 pdo = get_pdo(user);
|
||||
// get page table directory origin from user or supervisor pdo register
|
||||
const u32 pdo = get_pdo(user);
|
||||
|
||||
// get page table directory index from top 12 bits of virtual address
|
||||
const u32 ptdi = (va & VA_PTDI) >> 20;
|
||||
// get page table directory index from top 12 bits of virtual address
|
||||
const u32 ptdi = (va & VA_PTDI) >> 20;
|
||||
|
||||
// fetch page table directory entry
|
||||
const u32 ptde = m_main_space->read_dword(pdo | ptdi);
|
||||
// fetch page table directory entry
|
||||
const u32 ptde = m_space[ST0]->read_dword(pdo | ptdi);
|
||||
|
||||
LOGMASKED(LOG_DTU, "get_pte pdo 0x%08x ptdi 0x%08x ptde 0x%08x\n", pdo, ptdi, ptde);
|
||||
LOGMASKED(LOG_DTU, "get_pte pdo 0x%08x ptdi 0x%08x ptde 0x%08x\n", pdo, ptdi, ptde);
|
||||
|
||||
// check for page table directory entry fault
|
||||
if (ptde & PTDE_F)
|
||||
return PTE_F;
|
||||
// check for page table directory entry fault
|
||||
if (ptde & PTDE_F)
|
||||
return { PTE_F, pdo | ptdi };
|
||||
|
||||
// get the page table origin from the page table directory entry
|
||||
const u32 pto = ptde & PTDE_PTO;
|
||||
// get the page table origin from the page table directory entry
|
||||
const u32 pto = ptde & PTDE_PTO;
|
||||
|
||||
// get the page table index from the middle 12 bits of the virtual address
|
||||
const u32 pti = (va & VA_PTI) >> 10;
|
||||
// get the page table index from the middle 12 bits of the virtual address
|
||||
const u32 pti = (va & VA_PTI) >> 10;
|
||||
|
||||
// fetch page table entry
|
||||
const u32 pte = m_main_space->read_dword(pto | pti);
|
||||
// fetch page table entry
|
||||
pte_t pte = { m_space[ST0]->read_dword(pto | pti), pto | pti };
|
||||
|
||||
LOGMASKED(LOG_DTU, "get_pte pto 0x%08x pti 0x%08x pte 0x%08x\n", pto, pti, pte);
|
||||
LOGMASKED(LOG_DTU, "get_pte pto 0x%08x pti 0x%08x pte 0x%08x\n", pto, pti, pte.entry);
|
||||
|
||||
// check for page table entry fault
|
||||
if (pte & PTE_F)
|
||||
return PTE_F;
|
||||
// check for page table entry fault
|
||||
if (!(pte.entry & PTE_F))
|
||||
LOGMASKED(LOG_DTU, "get_pte address 0x%08x pte 0x%08x (%s)\n", va, pte.entry, machine().describe_context());
|
||||
|
||||
// add the pte to the tlb
|
||||
m_tlb[tlb_index].va = va & ~CAMMU_PAGE_MASK;
|
||||
m_tlb[tlb_index].pte = pte;
|
||||
|
||||
LOGMASKED(LOG_DTU, "get_pte address 0x%08x pte 0x%08x (%s)\n", va, pte, machine().describe_context());
|
||||
}
|
||||
|
||||
return m_tlb[tlb_index].pte;
|
||||
return pte;
|
||||
}
|
||||
|
||||
address_space *cammu_c4i_device::get_ust_space() const
|
||||
{
|
||||
switch (m_control & CNTL_UMM)
|
||||
{
|
||||
case UMM_MM: return m_main_space;
|
||||
case UMM_MMRIO: return m_main_space; // FIXME: what determines main or i/o?
|
||||
case UMM_IO: return m_io_space;
|
||||
}
|
||||
|
||||
return m_main_space;
|
||||
}
|
||||
|
||||
bool cammu_c4_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const
|
||||
bool cammu_c4_device::get_access(const access_type mode, const u32 pte, const u32 ssw) const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ACCESS_R: return pte & 0x20;
|
||||
case ACCESS_W: return pte & 0x10;
|
||||
case ACCESS_X: return pte & 0x08;
|
||||
case READ: return pte & 0x20;
|
||||
case WRITE: return pte & 0x10;
|
||||
case RMW: return (pte & 0x30) == 0x30;
|
||||
case EXECUTE: return pte & 0x08;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cammu_c3_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const
|
||||
bool cammu_c3_device::get_access(const access_type mode, const u32 pte, const u32 ssw) const
|
||||
{
|
||||
// FIXME: logic is not correct yet
|
||||
return true;
|
||||
|
||||
const u8 column = (mode == ACCESS_X ? i_cammu_column : d_cammu_column)[(ssw & SSW_PL) >> 9];
|
||||
const u8 column = (mode == EXECUTE ? i_cammu_column : d_cammu_column)[(ssw & SSW_PL) >> 9];
|
||||
const u8 access = cammu_matrix[column][(pte & PTE_PL) >> 3];
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case ACCESS_R: return access & R;
|
||||
case ACCESS_W: return access & W;
|
||||
case ACCESS_X: return access & E;
|
||||
case READ: return access & R;
|
||||
case WRITE: return access & W;
|
||||
case RMW: return (access & (R | W)) == (R | W);
|
||||
case EXECUTE: return access & E;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -494,5 +393,3 @@ const cammu_c3_device::c3_access_t cammu_c3_device::cammu_matrix[][16] =
|
||||
{ N, N, RW, RW, RW, R, R, RWE, N, N, RE, RE, N, RE, N, N },
|
||||
{ N, N, N, RW, R, R, R, RWE, N, N, N, RE, RE, N, RE, N }
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,53 +6,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MCFG_CAMMU_SSW_CB(_sswcb) \
|
||||
devcb = &downcast<cammu_device &>(*device).set_ssw_callback(DEVCB_##_sswcb);
|
||||
#include "cpu/clipper/common.h"
|
||||
|
||||
#define MCFG_CAMMU_ID(_id) \
|
||||
downcast<cammu_c4_device &>(*device).set_cammu_id(_id);
|
||||
|
||||
#define MCFG_CAMMU_EXCEPTION_CB(_exceptioncb) \
|
||||
devcb = &downcast<cammu_device &>(*device).set_exception_callback(DEVCB_##_exceptioncb);
|
||||
|
||||
#define MCFG_CAMMU_LINK(_tag) \
|
||||
cammu_c3_device::static_add_linked(*device, _tag);
|
||||
downcast<cammu_c3_device &>(*device).add_linked(_tag);
|
||||
|
||||
class cammu_device : public device_t, public device_memory_interface
|
||||
class cammu_device : public device_t
|
||||
{
|
||||
public:
|
||||
template <class Object> devcb_base &set_ssw_callback(Object &&cb) { return m_ssw_func.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_exception_callback(Object &&cb) { return m_exception_func.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
static const u32 CAMMU_PAGE_SIZE = 0x1000;
|
||||
static const u32 CAMMU_PAGE_MASK = (CAMMU_PAGE_SIZE - 1);
|
||||
|
||||
enum ssw_mask : u32
|
||||
{
|
||||
SSW_M = 0x04000000, // mapped mode
|
||||
SSW_KU = 0x08000000, // user protect key
|
||||
SSW_UU = 0x10000000, // user data mode
|
||||
SSW_K = 0x20000000, // protect key
|
||||
SSW_U = 0x40000000, // user mode
|
||||
|
||||
SSW_PL = 0x78000000 // protection level relevant bits
|
||||
};
|
||||
|
||||
enum exception_vectors : u16
|
||||
{
|
||||
// data memory trap group
|
||||
EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108,
|
||||
EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR = 0x110,
|
||||
EXCEPTION_D_ALIGNMENT_FAULT = 0x120,
|
||||
EXCEPTION_D_PAGE_FAULT = 0x128,
|
||||
EXCEPTION_D_READ_PROTECT_FAULT = 0x130,
|
||||
EXCEPTION_D_WRITE_PROTECT_FAULT = 0x138,
|
||||
|
||||
// instruction memory trap group
|
||||
EXCEPTION_I_CORRECTED_MEMORY_ERROR = 0x288,
|
||||
EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR = 0x290,
|
||||
EXCEPTION_I_ALIGNMENT_FAULT = 0x2a0,
|
||||
EXCEPTION_I_PAGE_FAULT = 0x2a8,
|
||||
EXCEPTION_I_EXECUTE_PROTECT_FAULT = 0x2b0,
|
||||
};
|
||||
|
||||
enum pdo_mask : u32
|
||||
{
|
||||
PDO_MASK = 0xfffff000
|
||||
@ -79,17 +51,7 @@ public:
|
||||
PTE_LOCK = 0x00000100 // page lock (software)
|
||||
};
|
||||
|
||||
enum pte_st_mask : u32
|
||||
{
|
||||
ST_0 = 0x00000000, // private, write-through, main memory space
|
||||
ST_1 = 0x00000200, // shared, write-through, main memory space
|
||||
ST_2 = 0x00000400, // private, copy-back, main memory space
|
||||
ST_3 = 0x00000600, // noncacheable, main memory space
|
||||
ST_4 = 0x00000800, // noncacheable, i/o space
|
||||
ST_5 = 0x00000a00, // noncacheable, boot space
|
||||
ST_6 = 0x00000c00, // cache purge
|
||||
ST_7 = 0x00000e00 // slave i/o
|
||||
};
|
||||
static const int PTE_ST_SHIFT = 9;
|
||||
|
||||
enum va_mask : u32
|
||||
{
|
||||
@ -98,10 +60,100 @@ public:
|
||||
VA_PTDI = 0xffc00000 // page table directory index
|
||||
};
|
||||
|
||||
enum system_tag_t : u8
|
||||
{
|
||||
ST0 = 0, // private, write-through, main memory space
|
||||
ST1 = 1, // shared, write-through, main memory space
|
||||
ST2 = 2, // private, copy-back, main memory space
|
||||
ST3 = 3, // noncacheable, main memory space
|
||||
ST4 = 4, // noncacheable, i/o space
|
||||
ST5 = 5, // noncacheable, boot space
|
||||
ST6 = 6, // cache purge
|
||||
ST7 = 7 // slave i/o
|
||||
};
|
||||
|
||||
virtual void map(address_map &map) = 0;
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
void set_spaces(std::vector<address_space *> spaces);
|
||||
|
||||
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, bool> load(const u32 ssw, const u32 address, U &&apply)
|
||||
{
|
||||
translated_t t = translate_address(ssw, address, access_size(sizeof(T)), READ);
|
||||
|
||||
if (t.space != nullptr)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1: apply(T(t.space->read_byte(t.address))); break;
|
||||
case 2: apply(T(t.space->read_word(t.address))); break;
|
||||
case 4: apply(T(t.space->read_dword(t.address))); break;
|
||||
case 8: apply(T(t.space->read_qword(t.address))); break;
|
||||
default: fatalerror("unhandled load size %d\n", access_size(sizeof(T)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, bool> store(const u32 ssw, const u32 address, U data)
|
||||
{
|
||||
translated_t t = translate_address(ssw, address, access_size(sizeof(T)), WRITE);
|
||||
|
||||
if (t.space != nullptr)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1: t.space->write_byte(t.address, T(data)); break;
|
||||
case 2: t.space->write_word(t.address, T(data)); break;
|
||||
case 4: t.space->write_dword(t.address, T(data)); break;
|
||||
case 8: t.space->write_qword(t.address, T(data)); break;
|
||||
default: fatalerror("unhandled store size %d\n", access_size(sizeof(T)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<T(T)>>::value, bool> modify(const u32 ssw, const u32 address, U &&apply)
|
||||
{
|
||||
translated_t t = translate_address(ssw, address, access_size(sizeof(T)), RMW);
|
||||
|
||||
if (t.space != nullptr)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 4: t.space->write_dword(t.address, apply(T(t.space->read_dword(t.address)))); break;
|
||||
default: fatalerror("unhandled modify size %d\n", access_size(sizeof(T)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, bool> fetch(const u32 ssw, const u32 address, U &&apply)
|
||||
{
|
||||
translated_t t = translate_address(ssw, address, access_size(sizeof(T)), EXECUTE);
|
||||
|
||||
if (t.space != nullptr)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 2: apply(T(t.space->read_word(t.address))); break;
|
||||
case 4: apply(T(t.space->read_dword_unaligned(t.address))); break;
|
||||
default: fatalerror("unhandled fetch size %d\n", access_size(sizeof(T)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
cammu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
@ -110,52 +162,55 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
//virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
|
||||
|
||||
enum access_t
|
||||
enum access_size : u8
|
||||
{
|
||||
ACCESS_R = 1,
|
||||
ACCESS_W = 2,
|
||||
ACCESS_X = 3
|
||||
BYTE = 1,
|
||||
WORD = 2,
|
||||
DWORD = 4,
|
||||
QWORD = 8
|
||||
};
|
||||
|
||||
address_space *translate_address(const offs_t virtual_address, const access_t mode, offs_t *physical_address);
|
||||
enum access_type : u8
|
||||
{
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
RMW = 3,
|
||||
EXECUTE = 4
|
||||
};
|
||||
|
||||
u32 get_pte(const u32 va, const bool user);
|
||||
private:
|
||||
// address translation
|
||||
struct translated_t
|
||||
{
|
||||
address_space *const space;
|
||||
const u32 address;
|
||||
};
|
||||
translated_t translate_address(const u32 ssw, const u32 virtual_address, const access_size size, const access_type mode);
|
||||
|
||||
virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const = 0;
|
||||
struct pte_t
|
||||
{
|
||||
const u32 entry;
|
||||
const u32 address;
|
||||
};
|
||||
pte_t get_pte(const u32 va, const bool user);
|
||||
|
||||
// helpers
|
||||
virtual bool get_access(const access_type mode, const u32 pte, const u32 ssw) const = 0;
|
||||
virtual bool get_alignment() const = 0;
|
||||
virtual u32 get_pdo(const bool user) const = 0;
|
||||
virtual address_space *get_ust_space() const = 0;
|
||||
virtual system_tag_t get_ust_space() const = 0;
|
||||
|
||||
virtual void set_fault_address(const u32 va) = 0;
|
||||
|
||||
address_space_config m_main_space_config;
|
||||
address_space_config m_io_space_config;
|
||||
address_space_config m_boot_space_config;
|
||||
|
||||
address_space *m_main_space;
|
||||
address_space *m_io_space;
|
||||
address_space *m_boot_space;
|
||||
|
||||
devcb_read32 m_ssw_func;
|
||||
devcb_write16 m_exception_func;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 va;
|
||||
u32 pte;
|
||||
}
|
||||
m_tlb[2];
|
||||
|
||||
private:
|
||||
address_space *m_space[8];
|
||||
};
|
||||
|
||||
class cammu_c4_device : public cammu_device
|
||||
{
|
||||
public:
|
||||
void set_cammu_id(const u32 cammu_id) { m_control = cammu_id; }
|
||||
|
||||
DECLARE_READ32_MEMBER(s_pdo_r) { return m_s_pdo; }
|
||||
DECLARE_WRITE32_MEMBER(s_pdo_w) { m_s_pdo = ((m_s_pdo & ~mem_mask) | (data & mem_mask)) & PDO_MASK; }
|
||||
DECLARE_READ32_MEMBER(u_pdo_r) { return m_u_pdo; }
|
||||
@ -180,11 +235,11 @@ public:
|
||||
DECLARE_WRITE32_MEMBER(fault_data_2_hi_w) { m_fault_data_2_hi = data; }
|
||||
|
||||
protected:
|
||||
cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u32 cammu_id);
|
||||
cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
virtual void device_start() override;
|
||||
|
||||
virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const override;
|
||||
virtual bool get_access(const access_type mode, const u32 pte, const u32 ssw) const override;
|
||||
virtual u32 get_pdo(const bool user) const override { return user ? m_u_pdo : m_s_pdo; }
|
||||
|
||||
virtual void set_fault_address(const u32 va) override { m_fault_address_1 = va; }
|
||||
@ -274,7 +329,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
|
||||
virtual bool get_alignment() const override { return (m_control & CNTL_ATD) == 0; }
|
||||
virtual address_space *get_ust_space() const override { return (m_control & CNTL_IOTS) ? m_io_space : m_main_space; }
|
||||
virtual system_tag_t get_ust_space() const override { return system_tag_t((m_control & (CNTL_IOTS | CNTL_UST)) >> 4); }
|
||||
|
||||
private:
|
||||
u32 m_ram_line;
|
||||
@ -333,9 +388,11 @@ public:
|
||||
CRR_OFF = 0x00700000, // refresh off
|
||||
};
|
||||
|
||||
// c4i cammu identification (rev 2 and rev 3 known to have existed)
|
||||
enum control_cid_mask : u32
|
||||
{
|
||||
CID_C4I = 0x02000000 // c4i cammu identification
|
||||
CID_C4IR0 = 0x00000000,
|
||||
CID_C4IR2 = 0x02000000
|
||||
};
|
||||
|
||||
virtual DECLARE_READ32_MEMBER(control_r) override { return m_control; }
|
||||
@ -374,7 +431,8 @@ protected:
|
||||
virtual void device_start() override;
|
||||
|
||||
virtual bool get_alignment() const override { return (m_control & CNTL_ATD) == 0; }
|
||||
virtual address_space *get_ust_space() const override;
|
||||
// FIXME: don't really know how unmapped mode works on c4i
|
||||
virtual system_tag_t get_ust_space() const override { return (m_control & UMM_IO) ? ST4 : ST3; }
|
||||
|
||||
private:
|
||||
u32 m_reset;
|
||||
@ -391,11 +449,11 @@ class cammu_c3_device : public cammu_device
|
||||
public:
|
||||
cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static void static_add_linked(device_t &device, const char *const tag);
|
||||
|
||||
virtual void map(address_map &map) override;
|
||||
virtual void map_global(address_map &map);
|
||||
|
||||
void add_linked(const char *const tag) { m_linked.push_back(downcast<cammu_c3_device *>(siblingdevice(tag))); }
|
||||
|
||||
enum control_mask : u32
|
||||
{
|
||||
CNTL_EP = 0x00000001, // enable prefetch
|
||||
@ -443,10 +501,10 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const override;
|
||||
virtual bool get_access(const access_type mode, const u32 pte, const u32 ssw) const override;
|
||||
virtual bool get_alignment() const override { return m_control & CNTL_ATE; }
|
||||
virtual u32 get_pdo(const bool user) const override { return user ? m_u_pdo : m_s_pdo; }
|
||||
virtual address_space *get_ust_space() const override { return m_main_space; }
|
||||
virtual system_tag_t get_ust_space() const override { return system_tag_t((m_control & CNTL_UST) >> 4); }
|
||||
|
||||
virtual void set_fault_address(const u32 va) override { m_fault = va; }
|
||||
|
||||
|
@ -124,6 +124,7 @@ ADDRESS_MAP_START(interpro_ioga_device::map)
|
||||
AM_RANGE(0x94, 0x97) AM_READ(error_address_r)
|
||||
AM_RANGE(0x98, 0x9b) AM_READ(error_businfo_r)
|
||||
AM_RANGE(0x9c, 0x9f) AM_READWRITE16(arbctl_r, arbctl_w, 0x0000ffff)
|
||||
//AM_RANGE(0x9c, 0x9f) AM_READWRITE16(?, ?, 0xffff0000) // ip2000 boot code writes 0x7f18
|
||||
AM_RANGE(0xa0, 0xa3) AM_READWRITE(timer2_count_r, timer2_count_w)
|
||||
AM_RANGE(0xa4, 0xa7) AM_READWRITE(timer2_value_r, timer2_value_w)
|
||||
AM_RANGE(0xa8, 0xab) AM_READWRITE(timer3_r, timer3_w)
|
||||
@ -507,48 +508,20 @@ WRITE16_MEMBER(interpro_ioga_device::icr_w)
|
||||
|
||||
LOGIRQ(offset, "irq: interrupt vector %d = 0x%04x (%s)\n", offset, data, machine().describe_context());
|
||||
|
||||
if (data & IRQ_PENDING)
|
||||
{
|
||||
// record interrupt pending forced
|
||||
m_hwint_forced |= 1 << offset;
|
||||
// store all bits except pending
|
||||
m_hwicr[offset] = (m_hwicr[offset] & IRQ_PENDING) | (data & ~IRQ_PENDING);
|
||||
|
||||
// store all bits except pending
|
||||
m_hwicr[offset] = (m_hwicr[offset] & IRQ_PENDING) | (data & ~IRQ_PENDING);
|
||||
|
||||
// FIXME: is it possible trigger a pending interrupt by unmasking it here?
|
||||
}
|
||||
else if (m_hwint_forced & (1 << offset))
|
||||
{
|
||||
// interrupt is being forced
|
||||
m_hwicr[offset] = data;
|
||||
|
||||
// clear forced flag
|
||||
m_hwint_forced &= ~(1 << offset);
|
||||
|
||||
// FIXME: in/ex
|
||||
LOGIRQ(offset, "irq: forcing interrupt vector %d\n", offset);
|
||||
set_int_line(INT_HARD_IN, offset, ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
// otherwise just store the value
|
||||
m_hwicr[offset] = data;
|
||||
// scan for pending interrupts
|
||||
m_interrupt_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(interpro_ioga_device::softint_w)
|
||||
{
|
||||
// check for forced interrupts
|
||||
const u8 forced = m_softint & ~data;
|
||||
|
||||
// store the written value
|
||||
m_softint = data;
|
||||
// FIXME: forced interrupt handling
|
||||
COMBINE_DATA(&m_softint);
|
||||
|
||||
// force interrupts if needed
|
||||
if (forced != 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (forced & (1 << i))
|
||||
set_int_line(INT_SOFT_LO, i, ASSERT_LINE);
|
||||
}
|
||||
m_interrupt_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(interpro_ioga_device::nmictrl_w)
|
||||
@ -569,15 +542,11 @@ WRITE8_MEMBER(interpro_ioga_device::nmictrl_w)
|
||||
|
||||
WRITE16_MEMBER(interpro_ioga_device::softint_vector_w)
|
||||
{
|
||||
// check for forced interrupt
|
||||
const bool forced = (m_swicr[offset] & IRQ_PENDING) && !(data & IRQ_PENDING);
|
||||
|
||||
// store the written value
|
||||
m_swicr[offset] = data;
|
||||
COMBINE_DATA(&m_swicr[offset]);
|
||||
|
||||
// force interrupt if needed
|
||||
if (forced)
|
||||
set_int_line(INT_SOFT_HI, offset, ASSERT_LINE);
|
||||
m_interrupt_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -599,43 +568,80 @@ TIMER_CALLBACK_MEMBER(interpro_ioga_device::dma)
|
||||
if ((m_arbctl & dma_channel.arb_mask) == 0)
|
||||
{
|
||||
// set bus wait flag and abort
|
||||
dma_channel.control |= DMA_CTRL_WAIT;
|
||||
//dma_channel.control |= DMA_CTRL_WAIT;
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
// clear bus wait flag
|
||||
dma_channel.control &= ~DMA_CTRL_WAIT;
|
||||
//else
|
||||
// // clear bus wait flag
|
||||
// dma_channel.control &= ~DMA_CTRL_WAIT;
|
||||
|
||||
//LOGMASKED(LOG_DMA, "dma: transfer %s device begun, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n",
|
||||
// translate address when DMA_CTRL_VIRTUAL is set
|
||||
// FIXME: what happens when we span a page?
|
||||
if (dma_channel.control & DMA_CTRL_VIRTUAL)
|
||||
{
|
||||
const u32 ptde = m_memory_space->read_dword(dma_channel.virtual_address);
|
||||
|
||||
if ((ptde & 0x1) == 0)
|
||||
{
|
||||
dma_channel.real_address = (ptde & ~0xfff) | (dma_channel.real_address & 0xfff);
|
||||
dma_channel.control &= ~DMA_CTRL_VIRTUAL;
|
||||
|
||||
LOGDMA(dma_channel.channel, "dma: translated virtual address 0x%08x\n", dma_channel.real_address);
|
||||
|
||||
// FIXME: what about protection levels and system tags?
|
||||
|
||||
// set referenced and dirty page table entry flags
|
||||
m_memory_space->write_dword(dma_channel.virtual_address, ptde | ((dma_channel.control & DMA_CTRL_WRITE) ? 0x2 : 0x6));
|
||||
}
|
||||
else
|
||||
{
|
||||
// page fault
|
||||
// FIXME: error status
|
||||
dma_channel.control |= DMA_CTRL_BERR | DMA_CTRL_ERR;
|
||||
LOGDMA(dma_channel.channel, "dma: page fault translating virtual address 0x%08x ptde 0x%08x\n", dma_channel.virtual_address, ptde);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//LOGDMA(dma_channel.channel, "dma: transfer %s device begun, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n",
|
||||
// (dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", dma_channel.channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count);
|
||||
|
||||
// transfer from the memory to device or device to memory
|
||||
while (dma_channel.transfer_count && dma_channel.drq_state)
|
||||
{
|
||||
// transfer from the memory to device or device to memory
|
||||
// TODO: implement virtual addressing when DMA_CTRL_VIRTUAL is set
|
||||
|
||||
if (dma_channel.control & DMA_CTRL_WRITE)
|
||||
dma_channel.device_w(m_memory_space->read_byte(dma_channel.real_address));
|
||||
else
|
||||
m_memory_space->write_byte(dma_channel.real_address, dma_channel.device_r());
|
||||
|
||||
// increment addresses and decrement count
|
||||
// increment address and decrement count
|
||||
dma_channel.real_address++;
|
||||
dma_channel.virtual_address++;
|
||||
dma_channel.transfer_count--;
|
||||
|
||||
// check for page wrap
|
||||
if (dma_channel.transfer_count && (dma_channel.real_address & 0xfff) == 0)
|
||||
{
|
||||
LOGDMA(dma_channel.channel, "dma: wrapped to next memory page\n");
|
||||
|
||||
dma_channel.virtual_address += 4;
|
||||
dma_channel.control |= DMA_CTRL_VIRTUAL;
|
||||
|
||||
m_dma_timer->adjust(attotime::zero);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the transfer is complete
|
||||
if (dma_channel.transfer_count == 0)
|
||||
{
|
||||
LOGMASKED(LOG_DMA, "dma: transfer %s device ended, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n",
|
||||
LOGDMA(dma_channel.channel, "dma: transfer %s device ended, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n",
|
||||
(dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", dma_channel.channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count);
|
||||
|
||||
if (dma_channel.channel == DMA_FLOPPY)
|
||||
{
|
||||
LOGMASKED(LOG_DMA | LOG_FLOPPY, "dma: asserting fdc terminal count line\n");
|
||||
LOGDMA(dma_channel.channel, "dma: asserting fdc terminal count line\n");
|
||||
|
||||
m_fdc_tc_func(ASSERT_LINE);
|
||||
m_fdc_tc_func(CLEAR_LINE);
|
||||
@ -725,9 +731,7 @@ void interpro_ioga_device::drq(int state, int channel)
|
||||
|
||||
// log every 256 bytes
|
||||
if ((dma_channel.transfer_count & 0xff) == 0)
|
||||
{
|
||||
LOGMASKED(LOG_DMA, "dma: drq for channel %d %s transfer_count 0x%08x\n", channel, state ? "asserted" : "deasserted", dma_channel.transfer_count);
|
||||
}
|
||||
LOGDMA(channel, "dma: drq for channel %d %s transfer_count 0x%08x\n", channel, state ? "asserted" : "deasserted", dma_channel.transfer_count);
|
||||
|
||||
if (state)
|
||||
m_dma_timer->adjust(attotime::zero);
|
||||
@ -764,28 +768,33 @@ void interpro_ioga_device::dma_w(address_space &space, offs_t offset, u32 data,
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
LOGMASKED(LOG_DMA, "dma: channel %d real address = 0x%08x (%s)\n", channel, data, machine().describe_context());
|
||||
dma_channel.real_address = data;
|
||||
LOGDMA(channel, "dma: channel %d real address 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
channel, data, mem_mask, machine().describe_context());
|
||||
COMBINE_DATA(&dma_channel.real_address);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
LOGMASKED(LOG_DMA, "dma: channel %d virtual address = 0x%08x (%s)\n", channel, data, machine().describe_context());
|
||||
dma_channel.virtual_address = data & ~0x3;
|
||||
LOGDMA(channel, "dma: channel %d virtual address = 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
channel, data, mem_mask, machine().describe_context());
|
||||
COMBINE_DATA(&dma_channel.virtual_address);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
LOGMASKED(LOG_DMA, "dma: channel %d transfer count = 0x%08x (%s)\n", channel, data, machine().describe_context());
|
||||
dma_channel.transfer_count = data;
|
||||
LOGDMA(channel, "dma: channel %d transfer count = 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
channel, data, mem_mask, machine().describe_context());
|
||||
COMBINE_DATA(&dma_channel.transfer_count);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
LOGMASKED(LOG_DMA, "dma: channel %d control = 0x%08x (%s)\n", channel, data, machine().describe_context());
|
||||
LOGDMA(channel, "dma: channel %d control = 0x%08x mem_mask 0x%08x (%s)\n",
|
||||
channel, data, mem_mask, machine().describe_context());
|
||||
|
||||
COMBINE_DATA(&dma_channel.control);
|
||||
// (7.0272) if bus error flag is set, clear existing bus error (otherwise retain existing state)
|
||||
if (data & DMA_CTRL_BERR)
|
||||
dma_channel.control = data & DMA_CTRL_WMASK;
|
||||
else
|
||||
dma_channel.control = (data & DMA_CTRL_WMASK) | (dma_channel.control & DMA_CTRL_BERR);
|
||||
//if (data & DMA_CTRL_BERR)
|
||||
// dma_channel.control = data & DMA_CTRL_WMASK;
|
||||
//else
|
||||
// dma_channel.control = (data & DMA_CTRL_WMASK) | (dma_channel.control & DMA_CTRL_BERR);
|
||||
|
||||
dma_channel.state = COMMAND;
|
||||
break;
|
||||
@ -1097,7 +1106,12 @@ READ32_MEMBER(interpro_ioga_device::mouse_status_r)
|
||||
|
||||
// clear xpos and ypos fields
|
||||
if (!machine().side_effects_disabled())
|
||||
m_mouse_status &= ~(MOUSE_XPOS | MOUSE_YPOS);
|
||||
{
|
||||
if (mem_mask & MOUSE_XPOS)
|
||||
m_mouse_status &= ~(MOUSE_XPOS);
|
||||
if (mem_mask & MOUSE_YPOS)
|
||||
m_mouse_status &= ~(MOUSE_YPOS);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1120,6 +1134,10 @@ INPUT_CHANGED_MEMBER(interpro_ioga_device::mouse_button)
|
||||
else
|
||||
m_mouse_status &= ~(field.mask() << 16);
|
||||
|
||||
// FIXME: this isn't right, but the rebuild code only
|
||||
// reads the button status if the x/y status is non-zero?
|
||||
m_mouse_status |= MOUSE_COUNTER;
|
||||
|
||||
set_int_line(INT_HARD_IN, IRQ_MOUSE, ASSERT_LINE);
|
||||
}
|
||||
|
||||
@ -1148,7 +1166,7 @@ INPUT_CHANGED_MEMBER(interpro_ioga_device::mouse_y)
|
||||
else if (delta < -0x80)
|
||||
delta += 0x100;
|
||||
|
||||
// set new x delta
|
||||
// set new y delta
|
||||
m_mouse_status &= ~MOUSE_YPOS;
|
||||
m_mouse_status |= ((delta << 0) & MOUSE_YPOS);
|
||||
|
||||
@ -1265,29 +1283,29 @@ WRITE32_MEMBER(sapphire_ioga_device::eth_control_w)
|
||||
}
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(sapphire_ioga_device::eth_w)
|
||||
WRITE16_MEMBER(sapphire_ioga_device::eth_w)
|
||||
{
|
||||
// top two bits give channel (0=A, 4=B, 8=C, f=?)
|
||||
const int channel = offset >> 28;
|
||||
u32 address = (offset << 2) & 0x3fffffff;
|
||||
const int channel = offset >> 29;
|
||||
u32 address = (offset << 1) & 0x3fffffff;
|
||||
|
||||
if ((m_eth_control & ETH_MAPEN) && (address & ETH_MAPPG) == (m_eth_mappg & ETH_MAPPG))
|
||||
{
|
||||
address &= ~(m_eth_mappg & ETH_MAPPG);
|
||||
address |= (m_eth_remap & ETH_REMAP_ADDR);
|
||||
|
||||
LOGMASKED(LOG_NETWORK, "eth_w address 0x%08x remapped 0x%08x\n", offset << 2, address);
|
||||
LOGMASKED(LOG_NETWORK, "eth_w address 0x%08x remapped 0x%08x\n", offset << 1, address);
|
||||
}
|
||||
|
||||
LOGMASKED(LOG_NETWORK, "eth_w channel %c address 0x%08x mask 0x%08x data 0x%08x\n", channel + 'A', address, mem_mask, data);
|
||||
m_memory_space->write_dword(address, data, mem_mask);
|
||||
LOGMASKED(LOG_NETWORK, "eth_w channel %c address 0x%08x mask 0x%08x data 0x%04x\n", channel + 'A', address, mem_mask, data);
|
||||
m_memory_space->write_word(address, data, mem_mask);
|
||||
}
|
||||
|
||||
READ32_MEMBER(sapphire_ioga_device::eth_r)
|
||||
READ16_MEMBER(sapphire_ioga_device::eth_r)
|
||||
{
|
||||
// top two bits give channel (0=A, 4=B, 8=C, f=?)
|
||||
const int channel = offset >> 28;
|
||||
u32 address = (offset << 2) & 0x3fffffff;
|
||||
const int channel = offset >> 29;
|
||||
u32 address = (offset << 1) & 0x3fffffff;
|
||||
|
||||
if ((m_eth_control & ETH_MAPEN) && (address & ETH_MAPPG) == (m_eth_mappg & ETH_MAPPG))
|
||||
{
|
||||
@ -1295,11 +1313,11 @@ READ32_MEMBER(sapphire_ioga_device::eth_r)
|
||||
address |= (m_eth_remap & ETH_REMAP_ADDR);
|
||||
address &= 0x3fffffff;
|
||||
|
||||
LOGMASKED(LOG_NETWORK, "eth_r address 0x%08x remapped 0x%08x\n", offset << 2, address);
|
||||
LOGMASKED(LOG_NETWORK, "eth_r address 0x%08x remapped 0x%08x\n", offset << 1, address);
|
||||
}
|
||||
|
||||
u32 data = m_memory_space->read_dword(address, mem_mask);
|
||||
LOGMASKED(LOG_NETWORK, "eth_r channel %c address 0x%08x mask 0x%08x data 0x%08x\n", channel + 'A', address, mem_mask, data);
|
||||
u16 data = m_memory_space->read_word(address, mem_mask);
|
||||
LOGMASKED(LOG_NETWORK, "eth_r channel %c address 0x%08x mask 0x%08x data 0x%04x\n", channel + 'A', address, mem_mask, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -196,10 +196,9 @@ public:
|
||||
DMA_CTRL_ERR = 0x00800000, // checked for in scsi isr
|
||||
|
||||
DMA_CTRL_BGR = 0x01000000, // cleared when command complete (maybe bus grant required?)
|
||||
DMA_CTRL_WAIT = 0x02000000, // waiting for bus grant
|
||||
DMA_CTRL_VIRTUAL = 0x02000000, // virtual address translation required
|
||||
DMA_CTRL_DOUBLE = 0x04000000, // double transfer size (double or quad quad)
|
||||
|
||||
DMA_CTRL_VIRTUAL = 0x20000000, // use virtual addressing
|
||||
DMA_CTRL_WRITE = 0x40000000, // memory to device transfer
|
||||
DMA_CTRL_QUAD = 0x80000000, // select quad transfer size (quad quad when combined with double)
|
||||
|
||||
@ -513,8 +512,8 @@ public:
|
||||
|
||||
virtual void map(address_map &map) override;
|
||||
|
||||
DECLARE_WRITE32_MEMBER(eth_w);
|
||||
DECLARE_READ32_MEMBER(eth_r);
|
||||
DECLARE_WRITE16_MEMBER(eth_w);
|
||||
DECLARE_READ16_MEMBER(eth_r);
|
||||
|
||||
protected:
|
||||
virtual TIMER_CALLBACK_MEMBER(eth_reset) override;
|
||||
|
Loading…
Reference in New Issue
Block a user