summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/devfind.h
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2020-11-02 12:11:43 +0100
committer Olivier Galibert <galibert@pobox.com>2020-11-02 12:12:11 +0100
commitb8c338858a101d14308c64c87b0f714db4f05326 (patch)
treea34dca21d603b98f5450d31868ce33a7e4c103b0 /src/emu/devfind.h
parentf4172ded3ec6f3b877ab813f6453d6d1907c1c00 (diff)
emumem: Simplify memory management. [O. Galibert]
API impact: - install_ram/rom/writeonly now requires a non-null pointer. If you want automatically managed ram, add it to a memory map, not in machine_start - install_*_bank now requires a memory_bank *, not a string - one can create memory banks outside of memory maps with memory_bank_creator - one can create memory shares outside of memory maps with memory_share_creator Memory maps impact: - ram ranges with overlapping addresses are not shared anymore. Use .share() - ram ranges touching each other are not merged anymore. Stay in your range Extra note: - there is no need to create a bank just to dynamically map some memory/rom. Just use install_rom/ram/writeonly
Diffstat (limited to 'src/emu/devfind.h')
-rw-r--r--src/emu/devfind.h124
1 files changed, 94 insertions, 30 deletions
diff --git a/src/emu/devfind.h b/src/emu/devfind.h
index 958ae16c3bc..d9e2e95df21 100644
--- a/src/emu/devfind.h
+++ b/src/emu/devfind.h
@@ -356,7 +356,7 @@ protected:
/// it is optional.
/// \return True if the region is optional, or if the region is
/// required and a matching region is found, or false otherwise.
- bool validate_memregion(size_t bytes, bool required) const;
+ bool validate_memregion(bool required) const;
/// \brief Find a memory share
///
@@ -753,6 +753,94 @@ template <unsigned Count, bool Required> using memory_bank_array_finder = object
template <unsigned Count> using optional_memory_bank_array = memory_bank_array_finder<Count, false>;
template <unsigned Count> using required_memory_bank_array = memory_bank_array_finder<Count, true>;
+/// \brief Memory bank creator
+///
+/// Creates a memory bank or picks up an existing one.
+class memory_bank_creator : finder_base
+{
+public:
+ memory_bank_creator(device_t &base, char const *tag) : finder_base(base, tag) { }
+ virtual ~memory_bank_creator() = default;
+
+ /// \brief Get pointer to target bank object
+ /// \return Pointer to target bank object if found, or nullptr otherwise.
+ memory_bank *target() const { return m_target; }
+
+ /// \brief Cast-to-pointer operator
+ ///
+ /// Allows implicit casting to a pointer to the target bank object.
+ /// \return Pointer to target bank object
+ operator memory_bank *() const { return m_target; }
+
+ /// \brief Pointer member access operator
+ ///
+ /// Allows pointer-member-style access to members of the target
+ /// bank object.
+ /// \return Pointer to target bank object
+ memory_bank *operator->() const { return m_target; }
+
+protected:
+ virtual bool findit(validity_checker *valid) override;
+ virtual void end_configuration() override;
+
+ /// \brief Pointer to target object
+ ///
+ /// Pointer to target object, or nullptr if the creation has not been
+ /// attempted yet.
+ memory_bank *m_target = nullptr;
+};
+
+template <unsigned Count> using memory_bank_array_creator = object_array_finder<memory_bank_creator, Count>;
+
+/// \brief Memory share creator
+///
+/// Creates a memory share or picks up an existing one.
+template<typename uX> class memory_share_creator : finder_base
+{
+public:
+ memory_share_creator(device_t &base, char const *tag, size_t bytes, endianness_t endianness);
+ virtual ~memory_share_creator() = default;
+
+ /// \brief Get pointer to the share object
+ /// \return Pointer to share object.
+ memory_share *share() const { return m_target; }
+
+ /// \brief Get pointer to the share object backing ram
+ /// \return Pointer to the ram.
+ uX *ptr() const { return reinterpret_cast<uX *>(m_target->ptr()); }
+
+ /// \brief Cast-to-pointer operator
+ ///
+ /// Allows implicit casting to a pointer to the target bank object.
+ /// \return Pointer to target bank object
+ operator uX *() const { return reinterpret_cast<uX *>(m_target->ptr()); }
+
+ /// \brief Pointer member access operator
+ ///
+ /// Allows pointer-member-style access to members of the target
+ /// bank object.
+ /// \return Pointer to target bank object
+ memory_share *operator->() const { return m_target; }
+
+ size_t bytes() const { return m_target->bytes(); }
+ endianness_t endianness() const { return m_target->endianness(); }
+ u8 bitwidth() const { return m_target->bitwidth(); }
+ u8 bytewidth() const { return m_target->bytewidth(); }
+
+protected:
+ virtual bool findit(validity_checker *valid) override;
+ virtual void end_configuration() override;
+
+ /// \brief Pointer to target object
+ ///
+ /// Pointer to target object, or nullptr if the creation has not been
+ /// attempted yet.
+ memory_share *m_target = nullptr;
+
+ const u8 m_width; // width of the shared region in bits
+ const size_t m_bytes; // size of the shared region in bytes
+ const endianness_t m_endianness; // endianness of the memory
+};
/// \brief I/O port finder template
///
@@ -939,9 +1027,8 @@ public:
/// pointer remains valid until resolution time.
/// \param [in] length Desired memory region length in units of the
/// size of the element type, or zero to match any region length.
- region_ptr_finder(device_t &base, char const *tag, size_t length = 0)
+ region_ptr_finder(device_t &base, char const *tag)
: object_finder_base<PointerType, Required>(base, tag)
- , m_desired_length(length)
, m_length(0)
{
}
@@ -990,21 +1077,15 @@ private:
virtual bool findit(validity_checker *valid) override
{
if (valid)
- return this->validate_memregion(sizeof(PointerType) * m_desired_length, Required);
+ return this->validate_memregion(Required);
assert(!this->m_resolved);
this->m_resolved = true;
- m_length = m_desired_length;
this->m_target = reinterpret_cast<PointerType *>(this->find_memregion(sizeof(PointerType), m_length, Required));
return this->report_missing("memory region");
}
- /// \brief Desired region length
- ///
- /// Desired region length in units of elements.
- size_t const m_desired_length;
-
- /// \brief Matched region length
+ /// \brief Region length
///
/// Actual length of the region that was found in units of
/// elements, or zero if no matching region has been found.
@@ -1043,11 +1124,9 @@ class shared_ptr_finder : public object_finder_base<PointerType, Required>
{
public:
// construction/destruction
- shared_ptr_finder(device_t &base, char const *tag, u8 width = sizeof(PointerType) * 8)
+ shared_ptr_finder(device_t &base, char const *tag)
: object_finder_base<PointerType, Required>(base, tag)
- , m_width(width)
, m_bytes(0)
- , m_allocated(0)
{
}
@@ -1058,19 +1137,6 @@ public:
u32 bytes() const { return m_bytes; }
u32 mask() const { return m_bytes - 1; } // FIXME: wrong when sizeof(PointerType) != 1
- // setter for setting the object
- void set_target(PointerType *target, size_t bytes) { this->m_target = target; m_bytes = bytes; }
-
- // dynamic allocation of a shared pointer
- void allocate(u32 entries)
- {
- assert(!m_allocated);
- m_allocated = std::make_unique<PointerType []>(entries);
- this->m_target = m_allocated.get();
- m_bytes = entries * sizeof(PointerType);
- this->m_base.get().save_pointer(m_allocated, this->m_tag, entries);
- }
-
private:
// finder
virtual bool findit(validity_checker *valid) override
@@ -1080,14 +1146,12 @@ private:
assert(!this->m_resolved);
this->m_resolved = true;
- this->m_target = reinterpret_cast<PointerType *>(this->find_memshare(m_width, m_bytes, Required));
+ this->m_target = reinterpret_cast<PointerType *>(this->find_memshare(sizeof(PointerType)*8, m_bytes, Required));
return this->report_missing("shared pointer");
}
// internal state
- u8 const m_width;
size_t m_bytes;
- std::unique_ptr<PointerType []> m_allocated;
};
template <typename PointerType> using optional_shared_ptr = shared_ptr_finder<PointerType, false>;