Previous 199869 Revisions Next

r25386 Saturday 21st September, 2013 at 22:35:53 UTC by Michael Zapf
New AM_(DEV)SETOFFSET feature for address maps.
[src/emu]addrmap.c addrmap.h memory.c memory.h

trunk/src/emu/memory.c
r25385r25386
178178        specify the share 'tag' will use its memory as backing for all
179179        future buckets that specify AM_SHARE with the same 'tag'.
180180
181    AM_SETOFFSET(setoffset)
182        Specifies a handler for a 'set address' operation. The intended use case
183        for this operation is to emulate a split-phase memory access: The caller
184        (usually a CPU) sets the address bus lines using set_address. Some
185        component may then react, for instance, by asserting a control line
186        like WAIT before delivering the data on the data bus. The data bits are
187        then sampled on the read operation or delivered on the write operation
188        that must be called subsequently.
189        It is not checked whether the address of the set_address operation
190        matches the address of the subsequent read/write operation.
191        The address map translates the address to a bucket and an offset,
192        hence the name of the macro. If no handler is specified for a bucket,
193        a set_address operation hitting that bucket returns silently.
194
195    AM_DEVSETOFFSET(tag, setoffset)
196        Specifies a handler for a set_address operation, bound to the device
197        specified by 'tag'.
198
199
181200***************************************************************************/
182201
183202#include <list>
r25385r25386
521540   legacy_info m_sublegacy_info[8];
522541};
523542
543// ======================> handler_entry_setoffset
544// a setoffset-access-specific extension of handler_entry
545class handler_entry_setoffset : public handler_entry
546{
547public:
548   // construction/destruction
549   handler_entry_setoffset()
550      : handler_entry(0, ENDIANNESS_LITTLE, NULL)
551   {
552   }
553
554   const char *name() const { return m_setoffset.name(); }
555   const char *subunit_name(int entry) const { return "no subunit"; }
556
557   // Call through only if the setoffset handler has been late-bound before
558   // (i.e. if it was declared in the address map)
559   void setoffset(address_space &space, offs_t offset) const { if (m_setoffset.has_object()) m_setoffset(space, offset); }
560
561   // configure delegate callbacks
562   void set_delegate(setoffset_delegate delegate, UINT64 mask = 0) { m_setoffset = delegate; }
563
564private:
565   setoffset_delegate         m_setoffset;
566   // We do not have subunits for setoffset
567   // Accordingly, we need not implement unused functions.
568   void remove_subunit(int entry) { }
569};
570
524571// ======================> handler_entry_proxy
525572
526573// A proxy class that contains an handler_entry_read or _write and forwards the setter calls
r25385r25386
823870   handler_entry_write *       m_handlers[TOTAL_MEMORY_BANKS];        // array of user-installed handlers
824871};
825872
873// ======================> address_table_setoffset
874// setoffset access-specific version of an address table
875class address_table_setoffset : public address_table
876{
877public:
878   // construction/destruction
879   address_table_setoffset(address_space &space, bool large)
880      : address_table(space, large)
881   {
882      // allocate handlers for each entry, prepopulating the bankptrs for banks
883      for (int entrynum = 0; entrynum < ARRAY_LENGTH(m_handlers); entrynum++)
884      {
885         m_handlers[entrynum] = auto_alloc(space.machine(), handler_entry_setoffset());
886      }
826887
888      // Watchpoints and unmap states do not make sense for setoffset
889      m_handlers[STATIC_NOP]->set_delegate(setoffset_delegate(FUNC(address_table_setoffset::nop_so), this));
890      m_handlers[STATIC_NOP]->configure(0, space.bytemask(), ~0);
891   }
892
893   ~address_table_setoffset()
894   {
895      for (int handnum = 0; handnum < ARRAY_LENGTH(m_handlers); handnum++)
896         auto_free(m_space.machine(), m_handlers[handnum]);
897   }
898
899   handler_entry &handler(UINT32 index) const {    assert(index < ARRAY_LENGTH(m_handlers));   return *m_handlers[index]; }
900   handler_entry_setoffset &handler_setoffset(UINT32 index) const { assert(index < ARRAY_LENGTH(m_handlers)); return *m_handlers[index]; }
901
902   // range getter
903   handler_entry_proxy<handler_entry_setoffset> handler_map_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT64 mask = 0) {
904      std::list<UINT32> entries;
905      setup_range(bytestart, byteend, bytemask, bytemirror, mask, entries);
906      std::list<handler_entry_setoffset *> handlers;
907      for (std::list<UINT32>::const_iterator i = entries.begin(); i != entries.end(); i++)
908         handlers.push_back(&handler_setoffset(*i));
909      return handler_entry_proxy<handler_entry_setoffset>(handlers, mask);
910   }
911
912private:
913   // internal handlers
914   // Setoffset does not allow for watchpoints, since we assume that a
915   // corresponding read/write operation will follow, and the watchpoint will
916   // apply for that operation
917   // For the same reason it does not make sense to put a warning into the log
918   // for unmapped locations, as this will be done by the read/write operation
919   void nop_so(address_space &space, offs_t offset)
920   {
921   }
922
923   // internal state
924   handler_entry_setoffset *m_handlers[TOTAL_MEMORY_BANKS];        // array of user-installed handlers
925};
926
927
827928// ======================> address_space_specific
828929
829930// this is a derived class of address_space with specific width, endianness, and table size
r25385r25386
840941   // helpers to simplify core code
841942   UINT32 read_lookup(offs_t byteaddress) const { return _Large ? m_read.lookup_live_large(byteaddress) : m_read.lookup_live_small(byteaddress); }
842943   UINT32 write_lookup(offs_t byteaddress) const { return _Large ? m_write.lookup_live_large(byteaddress) : m_write.lookup_live_small(byteaddress); }
944   UINT32 setoffset_lookup(offs_t byteaddress) const { return _Large ? m_setoffset.lookup_live_large(byteaddress) : m_setoffset.lookup_live_small(byteaddress); }
843945
844946public:
845947   // construction/destruction
846948   address_space_specific(memory_manager &manager, device_memory_interface &memory, address_spacenum spacenum)
847949      : address_space(manager, memory, spacenum, _Large),
848950         m_read(*this, _Large),
849         m_write(*this, _Large)
951         m_write(*this, _Large),
952         m_setoffset(*this, _Large)
850953   {
851954#if (TEST_HANDLER)
852955      // test code to verify the read/write handlers are touching the correct bits
r25385r25386
9881091   // accessors
9891092   virtual address_table_read &read() { return m_read; }
9901093   virtual address_table_write &write() { return m_write; }
1094   virtual address_table_setoffset &setoffset() { return m_setoffset; }
9911095
9921096   // watchpoint control
9931097   virtual void enable_read_watchpoints(bool enable = true) { m_read.enable_watchpoints(enable); }
r25385r25386
13851489      }
13861490   }
13871491
1492   // Allows to announce a pending read or write operation on this address.
1493   // The user of the address_space calls a set_address operation which leads
1494   // to some particular set_offset operation for an entry in the address map.
1495   void set_address(offs_t address)
1496   {
1497      offs_t byteaddress = address & m_bytemask;
1498      UINT32 entry = setoffset_lookup(byteaddress);
1499      const handler_entry_setoffset &handler = m_setoffset.handler_setoffset(entry);
1500
1501      offs_t offset = handler.byteoffset(byteaddress);
1502      handler.setoffset(*this, offset / sizeof(_NativeType));
1503   }
1504
13881505   // virtual access to these functions
13891506   UINT8 read_byte(offs_t address) { return (NATIVE_BITS == 8) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT8, true>(address, 0xff); }
13901507   UINT16 read_word(offs_t address) { return (NATIVE_BITS == 16) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT16, true>(address, 0xffff); }
r25385r25386
14321549
14331550   address_table_read      m_read;             // memory read lookup table
14341551   address_table_write     m_write;            // memory write lookup table
1552   address_table_setoffset m_setoffset;        // memory setoffset lookup table
14351553};
14361554
14371555typedef address_space_specific<UINT8,  ENDIANNESS_LITTLE, false> address_space_8le_small;
r25385r25386
18902008      // map both read and write halves
18912009      populate_map_entry(*entry, ROW_READ);
18922010      populate_map_entry(*entry, ROW_WRITE);
2011      populate_map_entry_setoffset(*entry);
18932012   }
18942013}
18952014
r25385r25386
19842103   }
19852104}
19862105
2106//-------------------------------------------------
2107//  populate_map_entry_setoffset - special case for setoffset
2108//-------------------------------------------------
19872109
2110void address_space::populate_map_entry_setoffset(const address_map_entry &entry)
2111{
2112   install_setoffset_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask,
2113      entry.m_addrmirror, setoffset_delegate(entry.m_soproto, *entry.m_setoffsethd.m_devbase), entry.m_setoffsethd.m_mask);
2114}
2115
19882116//-------------------------------------------------
19892117//  allocate_memory - determine all neighboring
19902118//  address ranges and allocate memory to back
r25385r25386
26412769}
26422770
26432771
2772//-----------------------------------------------------------------------
2773//  install_setoffset_handler - install set_offset delegate handlers for the space
2774//-----------------------------------------------------------------------
26442775
2776void address_space::install_setoffset_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, setoffset_delegate handler, UINT64 unitmask)
2777{
2778   VPRINTF(("address_space::install_setoffset_handler(%s-%s mask=%s mirror=%s, %s, %s)\n",
2779            core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
2780            core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
2781            handler.name(), core_i64_hex_format(unitmask, data_width() / 4)));
2782
2783   setoffset().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
2784}
2785
26452786//**************************************************************************
26462787//  MEMORY MAPPING HELPERS
26472788//**************************************************************************
trunk/src/emu/memory.h
r25385r25386
101101class address_table;
102102class address_table_read;
103103class address_table_write;
104class address_table_setoffset;
104105
105106
106107// offsets and addresses are 32-bit (for now...)
r25385r25386
178179typedef device_delegate<void (address_space &, offs_t, UINT32, UINT32)> write32_delegate;
179180typedef device_delegate<void (address_space &, offs_t, UINT64, UINT64)> write64_delegate;
180181
182// ======================> setoffset_delegate
181183
184typedef device_delegate<void (address_space &, offs_t)> setoffset_delegate;
185
186
182187// ======================> direct_read_data
183188
184189// direct_read_data contains state data for direct read access
r25385r25386
304309   friend class address_table;
305310   friend class address_table_read;
306311   friend class address_table_write;
312   friend class address_table_setoffset;
307313   friend class direct_read_data;
308314   friend class simple_list<address_space>;
309315   friend resource_pool_object<address_space>::~resource_pool_object();
r25385r25386
387393   virtual void write_qword_unaligned(offs_t byteaddress, UINT64 data) = 0;
388394   virtual void write_qword_unaligned(offs_t byteaddress, UINT64 data, UINT64 mask) = 0;
389395
396   // Set address. This will invoke setoffset handlers for the respective entries.
397   virtual void set_address(offs_t byteaddress) = 0;
398
390399   // address-to-byte conversion helpers
391400   offs_t address_to_byte(offs_t address) const { return m_config.addr2byte(address); }
392401   offs_t address_to_byte_end(offs_t address) const { return m_config.addr2byte_end(address); }
r25385r25386
446455
447456   void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_delegate &map, int bits = 0, UINT64 unitmask = 0);
448457
458   // install setoffset handler
459   void install_setoffset_handler(offs_t addrstart, offs_t addrend, setoffset_delegate sohandler, UINT64 unitmask = 0) { return install_setoffset_handler(addrstart, addrend, 0, 0, sohandler, unitmask); }
460   void install_setoffset_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, setoffset_delegate sohandler, UINT64 unitmask = 0);
461
449462   // install new-style delegate handlers (short form)
450463   UINT8 *install_read_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
451464   UINT8 *install_write_handler(offs_t addrstart, offs_t addrend, write8_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
r25385r25386
540553   // internal helpers
541554   virtual address_table_read &read() = 0;
542555   virtual address_table_write &write() = 0;
556   virtual address_table_setoffset &setoffset() = 0;
557
543558   void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite);
559   void populate_map_entry_setoffset(const address_map_entry &entry);
544560   void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, bool quiet);
545561   void *install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, void *baseptr);
546562   void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag);
r25385r25386
940956#define DECLARE_READ64_MEMBER(name)     UINT64 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff))
941957#define DECLARE_WRITE64_MEMBER(name)    void   name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff))
942958
959#define SETOFFSET_MEMBER(name)          void  name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset)
960#define DECLARE_SETOFFSET_MEMBER(name)      void  name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset)
943961
944962// device delegate macros
945963#define READ8_DELEGATE(_class, _member)                     read8_delegate(FUNC(_class::_member), this)
trunk/src/emu/addrmap.c
r25385r25386
473473
474474
475475//-------------------------------------------------
476//  set_handler - handler setter for setoffset
477//-------------------------------------------------
478
479void address_map_entry::set_handler(device_t &device, setoffset_delegate func)
480{
481   assert(!func.isnull());
482   m_setoffsethd.m_type = AMH_DEVICE_DELEGATE;
483   m_setoffsethd.m_bits = 0;
484   m_setoffsethd.m_mask = 0;
485   m_setoffsethd.m_name = func.name();
486   m_setoffsethd.m_devbase = &device;
487   m_soproto = func;
488}
489
490//-------------------------------------------------
476491//  unitmask_is_appropriate - verify that the
477492//  provided unitmask is valid and expected
478493//-------------------------------------------------
r25385r25386
809824            subentry->m_addrmirror |= entry->m_addrmirror;
810825
811826            // Twiddle the unitmask on the data accessors that need it
812            for (int data_entry = 0; data_entry < 2; data_entry++)
827            for (int data_entry = 0; data_entry < 3; data_entry++)
813828            {
814               map_handler_data &mdata = data_entry ? subentry->m_write : subentry->m_read;
829               map_handler_data &mdata = (data_entry==0)? subentry->m_read : ((data_entry==1)? subentry->m_write : subentry->m_setoffsethd);
815830
816831               if (mdata.m_type == AMH_NONE)
817832                  continue;
trunk/src/emu/addrmap.h
r25385r25386
127127   void set_write_bank(device_t &device, const char *tag);
128128   void set_readwrite_bank(device_t &device, const char *tag);
129129
130   // set offset handler (only one version, since there is no data width to consider)
131   void set_handler(device_t &device, setoffset_delegate func);
132
130133   // submap referencing
131134   void set_submap(device_t &device, const char *tag, address_map_delegate func, int bits, UINT64 mask);
132135
r25385r25386
142145   offs_t                  m_addrmask;             // mask bits
143146   map_handler_data        m_read;                 // data for read handler
144147   map_handler_data        m_write;                // data for write handler
148   map_handler_data        m_setoffsethd;          // data for setoffset handler
145149   const char *            m_share;                // tag of a shared memory block
146150   const char *            m_region;               // tag of region containing the memory backing this entry
147151   offs_t                  m_rgnoffs;              // offset within the region
r25385r25386
164168   write32_space_func      m_wspace32;             // 32-bit legacy address space handler
165169   write64_space_func      m_wspace64;             // 64-bit legacy address space handler
166170
171   setoffset_delegate       m_soproto;              // set offset proto-delegate
167172   address_map_delegate    m_submap_delegate;
168173   int                     m_submap_bits;
169174
r25385r25386
495500#define AM_READWRITE32(_rhandler, _whandler, _unitmask) \
496501   curentry->set_handler(device, read32_delegate(&drivdata_class::_rhandler, "driver_data::" #_rhandler, DEVICE_SELF, (drivdata_class *)0), write32_delegate(&drivdata_class::_whandler, "driver_data::" #_whandler, DEVICE_SELF, (drivdata_class *)0), _unitmask);
497502
503// driver set offset. Upcast to base class because there are no data width variants,
504// and the compiler complains if we don't do it explicitly
505#define AM_SETOFFSET(_handler) \
506   ((address_map_entry*)curentry)->set_handler(device, setoffset_delegate(&drivdata_class::_handler, "driver_data::" #_handler, DEVICE_SELF, (drivdata_class *)0));
507
498508// device reads
499509#define AM_DEVREAD(_tag, _class, _handler) \
500510   curentry->set_handler(device, read_delegate(&_class::_handler, #_class "::" #_handler, _tag, (_class *)0));
r25385r25386
525535#define AM_DEVREADWRITE32(_tag, _class, _rhandler, _whandler, _unitmask) \
526536   curentry->set_handler(device, read32_delegate(&_class::_rhandler, #_class "::" #_rhandler, _tag, (_class *)0), write32_delegate(&_class::_whandler, #_class "::" #_whandler, _tag, (_class *)0), _unitmask);
527537
538// device set offset
539#define AM_DEVSETOFFSET(_tag, _class, _handler) \
540   ((address_map_entry*)curentry)->set_handler(device, setoffset_delegate(&_class::_handler, #_class "::" #_handler, _tag, (_class *)0));
541
542
528543// device mapping
529544#define AM_DEVICE(_tag, _class, _handler) \
530545   curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 0, 0);

Previous 199869 Revisions Next


© 1997-2024 The MAME Team