The device_memory_interface

1. Capabilities

The device memory interface provides devices with the capability of creating address spaces, to which address maps can be associated. It’s used for any device that provides a (logically) address/data bus other devices can be connected to. It’s mainly, but not only, cpus.

The interface allows for an unlimited set of address spaces, numbered with small positive values. The IDs should stay small because they index vectors to keep the lookup fast. Spaces number 0-3 have an associated constant name:

ID Name
0 AS_PROGRAM
1 AS_DATA
2 AS_IO
3 AS_OPCODES

Spaces 0 and 3, e.g. AS_PROGRAM and AS_OPCODE, are special for the debugger and some CPUs. AS_PROGRAM is use by the debugger and the cpus as the space from with the cpu reads its instructions for the disassembler. When present, AS_OPCODE is used by the debugger and some cpus to read the opcode part of the instruction. What opcode means is device-dependant, for instance for the z80 it’s the initial byte(s) which are read with the M1 signal asserted. For the 68000 is means every instruction word plus the PC-relative accesses. The main, but not only, use of AS_OPCODE is to implement hardware decrypting instructions separately from the data.

2. Setup

std::vector<std::pair<int, const address_space_config >>**memory_space_config*(int spacenum) const

The device must override that method to provide a vector of pairs comprising of a space number and its associated address_space_config describing its configuration. Some examples to look up when needed: * Standard two-space vector: v60_device * Conditional AS_OPCODE: z80_device * Inherit config and add a space: m6801_device * Inherit config and patch a space: tmpz84c011_device

bool has_configured_map() const
bool has_configured_map(int index) const

The has_configured_map method allows to test in the memory_space_config method whether an address_map has been associated with a given space. That allows to implement optional memory spaces, such as AS_OPCODES in certain cpu cores. The parameterless version tests for space 0.

3. Associating maps to spaces

Associating maps to spaces is done at the machine config level, after the device declaration.

MCFG_DEVICE_ADDRESS_MAP(_space, _map)
MCFG_DEVICE_PROGRAM_MAP(_map)
MCFG_DEVICE_DATA_MAP(_map)
MCFG_DEVICE_IO_MAP(_map)
MCFG_DEVICE_DECRYPTED_OPCODES_MAP(_map)

The generic macro and the four specific ones associate a map to a given space. Address maps associated to non-existing spaces are ignored (no warning given). devcpu.h defines MCFG_CPU_*_MAP aliases to the specific macros.

MCFG_DEVICE_REMOVE_ADDRESS_MAP(_space)

That macro removes a memory map associated to a given space. Useful when removing a map for an optional space in a machine config derivative.

4. Accessing the spaces

address_space &space() const
address_space &space(int index) const

Returns a given address space post-initialization. The parameterless version tests for AS_PROGRAM/AS_0. Aborts if the space doesn’t exist.

bool has_space() const
bool has_space(int index) const

Indicates whether a given space actually exists. The parameterless version tests for AS_PROGRAM/AS_0.

5. MMU support for disassembler

bool translate(int spacenum, int intention, offs_t &address)

Does a logical to physical address translation through the device’s MMU. spacenum gives the space number, intention the type of the future access (TRANSLATE_(READ|WRITE|FETCH)(|_USER|_DEBUG)) and address is an inout parameter with the address to translate and its translated version. Should return true if the translation went correctly, false if the address is unmapped.

Note that for some historical reason the device itself must override the virtual method memory_translate with the same signature.