OSDN Git Service

[VM][NEWDEV] .
authorK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 24 Apr 2019 10:03:53 +0000 (19:03 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Wed, 24 Apr 2019 10:03:53 +0000 (19:03 +0900)
source/src/vm/libcpu_newdev/device.h
source/src/vm/libcpu_newdev/memcache/memcache.h

index b05e670..31e2085 100644 (file)
 #define MAX_OUTPUT     16
 
 // common signal id
-#define SIG_CPU_IRQ            101
-#define SIG_CPU_FIRQ           102
-#define SIG_CPU_NMI            103
-#define SIG_CPU_BUSREQ         104
-#define SIG_CPU_DEBUG          105
+#define SIG_CPU_IRQ                            101
+#define SIG_CPU_FIRQ                   102
+#define SIG_CPU_NMI                            103
+#define SIG_CPU_BUSREQ                 104
+#define SIG_CPU_HALTREQ                        105
+#define SIG_CPU_DEBUG                  106
+#define SIG_CPU_ADDRESS_DIRTY  107
 
 #define SIG_PRINTER_DATA       201
 #define SIG_PRINTER_STROBE     202
index c3b861e..d9f2363 100644 (file)
 ***************************************************************************/
 
 #pragma once
+#include "../../device.h"
 
-//#ifndef __EMU_H__
-//#error Dont include this file directly; include emu.h instead.
-//#endif
-
-#ifndef MAME_EMU_EMUMEM_H
-#define MAME_EMU_EMUMEM_H
-
-#include <type_traits>
-
-using s8 = std::int8_t;
-using u8 = std::uint8_t;
-using s16 = std::int16_t;
-using u16 = std::uint16_t;
-using s32 = std::int32_t;
-using u32 = std::uint32_t;
-using s64 = std::int64_t;
-using u64 = std::uint64_t;
-
-//**************************************************************************
-//  CONSTANTS
-//**************************************************************************
-
-// address space names for common use
-constexpr int AS_PROGRAM = 0; // program address space
-constexpr int AS_DATA    = 1; // data address space
-constexpr int AS_IO      = 2; // I/O address space
-constexpr int AS_OPCODES = 3; // (decrypted) opcodes, when separate from data accesses
-
-// read or write constants
-enum class read_or_write
-{
-       READ = 1,
-       WRITE = 2,
-       READWRITE = 3
-};
-
-
-
-//**************************************************************************
-//  TYPE DEFINITIONS
-//**************************************************************************
-
-// offsets and addresses are 32-bit (for now...)
-using offs_t = u32;
-
-// address map constructors are delegates that build up an address_map
-using address_map_constructor = named_delegate<void (address_map &)>;
-
-// struct with function pointers for accessors; use is generally discouraged unless necessary
-struct data_accessors
-{
-       u8      (*read_byte)(address_space &space, offs_t address);
-       u16     (*read_word)(address_space &space, offs_t address);
-       u16     (*read_word_masked)(address_space &space, offs_t address, u16 mask);
-       u32     (*read_dword)(address_space &space, offs_t address);
-       u32     (*read_dword_masked)(address_space &space, offs_t address, u32 mask);
-       u64     (*read_qword)(address_space &space, offs_t address);
-       u64     (*read_qword_masked)(address_space &space, offs_t address, u64 mask);
-
-       void    (*write_byte)(address_space &space, offs_t address, u8 data);
-       void    (*write_word)(address_space &space, offs_t address, u16 data);
-       void    (*write_word_masked)(address_space &space, offs_t address, u16 data, u16 mask);
-       void    (*write_dword)(address_space &space, offs_t address, u32 data);
-       void    (*write_dword_masked)(address_space &space, offs_t address, u32 data, u32 mask);
-       void    (*write_qword)(address_space &space, offs_t address, u64 data);
-       void    (*write_qword_masked)(address_space &space, offs_t address, u64 data, u64 mask);
-};
-
-
-// =====================-> The root class of all handlers
-
-// Handlers the refcounting as part of the interface
-
-class handler_entry
-{
-       DISABLE_COPYING(handler_entry);
-
-       template<int Width, int AddrShift, endianness_t Endian> friend class address_space_specific;
-
-public:
-       // Typing flags
-       static constexpr u32 F_DISPATCH    = 0x00000001; // handler that forwards the access to other handlers
-       static constexpr u32 F_UNITS       = 0x00000002; // handler that merges/splits an access among multiple handlers (unitmask support)
-       static constexpr u32 F_PASSTHROUGH = 0x00000004; // handler that passes through the request to another handler
-
-       // Start/end of range flags
-       static constexpr u8 START = 1;
-       static constexpr u8 END   = 2;
-
-       // Intermediary structure for reference count checking
-       class reflist {
-       public:
-               void add(const handler_entry *entry);
-
-               void propagate();
-               void check();
-
-       private:
-               std::unordered_map<const handler_entry *, u32> refcounts;
-               std::unordered_set<const handler_entry *> seen;
-               std::unordered_set<const handler_entry *> todo;
-       };
-
-       handler_entry(address_space *space, u32 flags) { m_space = space; m_refcount = 1; m_flags = flags; }
-       virtual ~handler_entry() {}
-
-       inline void ref(int count = 1) const { m_refcount += count; }
-       inline void unref(int count = 1) const { m_refcount -= count; if(!m_refcount) delete this; }
-       inline u32 flags() const { return m_flags; }
-
-       inline bool is_dispatch() const { return m_flags & F_DISPATCH; }
-       inline bool is_units() const { return m_flags & F_UNITS; }
-       inline bool is_passthrough() const { return m_flags & F_PASSTHROUGH; }
-
-       virtual void dump_map(std::vector<memory_entry> &map) const;
-
-       virtual std::string name() const = 0;
-       virtual void enumerate_references(handler_entry::reflist &refs) const;
-       u32 get_refcount() const { return m_refcount; }
-
-protected:
-       // Address range storage
-       struct range {
-               offs_t start;
-               offs_t end;
-
-               inline void set(offs_t _start, offs_t _end) {
-                       start = _start;
-                       end = _end;
-               }
-
-               inline void intersect(offs_t _start, offs_t _end) {
-                       if(_start > start)
-                               start = _start;
-                       if(_end < end)
-                               end = _end;
-               }
-       };
-
-       address_space *m_space;
-       mutable u32 m_refcount;
-       u32 m_flags;
-};
-
-template<int Width, int AddrShift, int Endian> class memory_access_cache
-{
-       //using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
-       static constexpr u32 NATIVE_BYTES = 1 << Width;
-       static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
-
-public:
-       // construction/destruction
-       memory_access_cache(address_space &space,
-                                               handler_entry_read <Width, AddrShift, Endian> *root_read,
-                                               handler_entry_write<Width, AddrShift, Endian> *root_write);
-
-       ~memory_access_cache();
-
-       // getters
-       address_space &space() const { return m_space; }
-
-       // see if an address is within bounds, update it if not
-       void check_address_r(offs_t address) {
-               if(address >= m_addrstart_r && address <= m_addrend_r)
-                       return;
-               m_root_read->lookup(address, m_addrstart_r, m_addrend_r, m_cache_r);
-       }
-
-       void check_address_w(offs_t address) {
-               if(address >= m_addrstart_w && address <= m_addrend_w)
-                       return;
-               m_root_write->lookup(address, m_addrstart_w, m_addrend_w, m_cache_w);
-       }
-
-       // accessor methods
-
-       void *read_ptr(offs_t address) {
-               check_address_r(address);
-               return m_cache_r->get_ptr(address);
-       }
-
-       u8 read_data8(offs_t address) { address &= m_addrmask; return Width == 0 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xff); }
-       u16 read_data16(offs_t address) { address &= m_addrmask; return Width == 1 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
-       u16 read_data16(offs_t address, u16 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-       u16 read_data16_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
-       u16 read_data16_unaligned(offs_t address, u16 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-       u32 read_data32(offs_t address) { address &= m_addrmask; return Width == 2 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
-       u32 read_data32(offs_t address, u32 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-       u32 read_data32_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
-       u32 read_data32_unaligned(offs_t address, u32 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-       u64 read_data64(offs_t address) { address &= m_addrmask; return Width == 3 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
-       u64 read_data64(offs_t address, u64 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-       u64 read_data64_unaligned(offs_t address) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
-       u64 read_data64_unaligned(offs_t address, u64 mask) { address &= m_addrmask; return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-
-       void write_data8(offs_t address, u8 data) { address &= m_addrmask; if (Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xff); }
-       void write_data16(offs_t address, u16 data) { address &= m_addrmask; if (Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
-       void write_data16(offs_t address, u16 data, u16 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-       void write_data16_unaligned(offs_t address, u16 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
-       void write_data16_unaligned(offs_t address, u16 data, u16 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-       void write_data32(offs_t address, u32 data) { address &= m_addrmask; if (Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
-       void write_data32(offs_t address, u32 data, u32 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-       void write_data32_unaligned(offs_t address, u32 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
-       void write_data32_unaligned(offs_t address, u32 data, u32 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-       void write_data64(offs_t address, u64 data) { address &= m_addrmask; if (Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
-       void write_data64(offs_t address, u64 data, u64 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-       void write_data64_unaligned(offs_t address, u64 data) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
-       void write_data64_unaligned(offs_t address, u64 data, u64 mask) { address &= m_addrmask; memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-
-private:
-       address_space &             m_space;
-
-       //int                         m_notifier_id;             // id to remove the notifier on destruction
-
-       offs_t                      m_addrmask;                // address mask
-       offs_t                      m_addrstart_r;             // minimum valid address for reading
-       offs_t                      m_addrend_r;               // maximum valid address for reading
-       offs_t                      m_addrstart_w;             // minimum valid address for writing
-       offs_t                      m_addrend_w;               // maximum valid address for writing
-       handler_entry_read<Width, AddrShift, Endian> *m_cache_r;   // read cache
-       handler_entry_write<Width, AddrShift, Endian> *m_cache_w;  // write cache
-
-       handler_entry_read <Width, AddrShift, Endian> *m_root_read;  // decode tree roots
-       handler_entry_write<Width, AddrShift, Endian> *m_root_write;
-
-       uint8_t  read_native(offs_t address, uint8_t mask = 0xff);
-       uint16_t read_native(offs_t address, uint16_t mask = 0xffff);
-       uint32_t read_native(offs_t address, uint32_t mask = 0xffffffff);
-       uint64_t read_native(offs_t address, uint64_t mask = 0xffffffffffffffff);
-       
-       void write_native(offs_t address, uint8_t data, uint8_t mask = 0xff);
-       void write_native(offs_t address, uint16_t data, uint16_t mask = 0xffff);
-       void write_native(offs_t address, uint32_t data, uint32_t mask = 0xffffffff);
-       void write_native(offs_t address, uint64_t data, uint64_t mask = 0xffffffffffffffff);
+enum {
+       CACHE_LINE_NOCACHE = 0,
+       CACHE_LINE_READ = 1,
+       CACHE_LINE_WRITE = 2,
+       CACHE_LINE_READ_WRITE =3
 };
 
 class DEVICE;
@@ -256,11 +28,12 @@ private:
        bool enabled;
        uint32_t start_addr;
        uint32_t end_addr;
+       int access_type;
        uint8_t *cache_data;
        bool *is_exists;
        bool is_little_endian;
 public:
-       cache_line(uint32_t start, uint32_t line_size,  int prefetch_size = -1)
+       cache_line(uint32_t start, uint32_t line_size, DEVICE* dev = NULL, int type = CACHE_LINE_READ_WRITE,  int prefetch_size = -1)
        {
                prefetch_enabled = (prefetch_size > 0) ? true : false;
                prefetch_block_size = prefetch_size;
@@ -269,7 +42,8 @@ public:
                is_exists = nullptr;
                start_addr = start;
                end_addr = start_addr;
-               d_device = NULL;
+               access_type = type;
+               d_device = dev;
                if(line_size > 0) {
                        cache_data = new uint8_t[line_size];
                        is_exists   = new bool[line_size];
@@ -341,6 +115,10 @@ public:
                }
                return false;
        }
+       int set_prefetch_block_size(int bytes)
+       {
+               prefetch_block_size = bytes;
+       }
        bool request_prefetch(uint32_t start)
        {
                if(prefetch_block_size <= 0) return false;
@@ -396,11 +174,32 @@ public:
                }
                return true;
        }
-       uint32_t read_data8w(uint32_t addr, int* wait, bool *is_hit)
+       void clear_all()
+       {
+               if(end_addr < start_addr) return;
+               uint32_t _size = end_addr - start_addr + 1;
+               memset(cache_data, 0x00, _size * sizeof(uint8_t));
+               for(uint32\t i = 0; i < _size; i++) {
+                       is_exists[i] = false;
+               }
+       }
+       void change_access_mode(int new_mode)
+       {
+               int old_mode = access_type;
+               if((old_mode & 3) == (new_mode & 3)) return;
+               if((old_mode & CACHE_LINE_READ) != (new_mode & CACHE_LINE_READ)) { // Discard cache.
+                       clear_all();
+               }
+               access_type = new_mode;
+       }
+       inline uint32_t read_data8w(uint32_t addr, int* wait)
        {
+               if((access_type & CACHE_LINE_READ) == 0) {
+                       is_exists[addr - start_addr] = false;
+                       return d_device->read_data8w(addr, wait);
+               }
                if(cache_hit(addr)) {
                        if(wait != nullptr) *wait = 0;
-                       if(is_hit != nullptr) *is_hit = true;
                        return (uint32_t)(cache_data[addr - start_addr]);
                }
                
@@ -409,69 +208,80 @@ public:
                                uint32_t data = d_device->read_data8w(addr, wait);
                                cache_data[addr - start_addr] = (uint8_t)data;
                                is_exists[addr - start_addr] = true;
-                               if(is_hit != nullptr) *is_hit = true;
                                return data;
                        } else {
-                               cache_data[addr - start_addr] = (uint8_t)0x00;
+                               cache_data[addr - start_addr] = (uint8_t)0xff;
                                is_exists[addr - start_addr] = false;
-                               if(is_hit != nullptr) *is_hit = true;
                                return 0xff;
                        }
                }
-               if(is_hit != nullptr) *is_hit = false;
                return 0xff;
        }
        // ToDo: endian
-       uint32_t read_data16w(uint32_t addr, int* wait, bool *is_hit)
+       uint32_t read_data16w(uint32_t addr, int* wait)
        {
                pair16_t n;
+               if((access_type & CACHE_LINE_READ) == 0) {
+                       //is_exists[addr - start_addr] = false;
+                       //is_exists[addr - start_addr + 1] = false;
+                       return d_device->read_data16w(addr, wait);
+               }
                if(cache_hit_range(addr, 2)) {
+                       if(wait != nullptr) *wait = 0;
                        n.b.l =  cache_data[addr - start_addr + 0];
                        n.b.h =  cache_data[addr - start_addr + 1];
-                       if(is_hit != NULL) *is_hit = true;
                        return (uint32_t)(n.w);
                } else {
-                       bool bl, bh;
-                       n.b.l = read_data8w(addr + 0, wait, &bl);
-                       n.b.h = read_data8w(addr + 0, wait, &bh);
-                       if(is_hit != NULL) *is_hit = (bl & bh);
-                       if((bl) && (bh)) return (uint32_t)(n.w);
+                       n.b.l = read_data8w(addr + 0, wait);
+                       n.b.h = read_data8w(addr + 0, wait);
+                       return (uint32_t)(n.w);
                }
                return 0xffff;
        }                       
-       uint32_t read_data32w(uint32_t addr, int* wait, bool *is_hit)
+       uint32_t read_data32w(uint32_t addr, int* wait)
        {
                pair32_t n;
+               if((access_type & CACHE_LINE_READ) == 0) {
+                       return d_device->read_data32w(addr, wait);
+               }
                if(cache_hit_range(addr, 4)) {
+                       if(wait != nullptr) *wait = 0;
                        n.b.l  =  cache_data[addr - start_addr + 0];
                        n.b.h  =  cache_data[addr - start_addr + 1];
                        n.b.h2 =  cache_data[addr - start_addr + 2];
                        n.b.h3 =  cache_data[addr - start_addr + 3];
-                       if(is_hit != NULL) *is_hit = true;
                        return n.d;
                } else {
-                       bool bl, bh, bh2, bh3;
-                       n.b.l  = read_data8w(addr + 0, wait, &bl);
-                       n.b.h  = read_data8w(addr + 1, wait, &bh);
-                       n.b.h2 = read_data8w(addr + 2, wait, &bh2);
-                       n.b.h2 = read_data8w(addr + 2, wait, &bh3);
-                       if(is_hit != NULL) *is_hit = (bl & bh & bh2 & bh3);
-                       if((bl) && (bh) && (bh2) && (bh3)) {
-                               return n.d;
-                       }
+                       n.b.l  = read_data8w(addr + 0, wait);
+                       n.b.h  = read_data8w(addr + 1, wait);
+                       n.b.h2 = read_data8w(addr + 2, wait);
+                       n.b.h3 = read_data8w(addr + 3, wait);
+                       return n.d;
                }
                return 0xffffffff;
        }                       
-       void write_data8w(uint32_t addr, uint32_t data, int* wait)
+       inline void write_data8w(uint32_t addr, uint32_t data, int* wait)
        {
                if(region_check(addr)) {
-                       if(d_device != NULL) {
-                               d_device->write_data8w(addr, wait);
-                               cache_data[addr - start_addr] = (uint8_t)data;
-                               is_exists[addr - start_addr] = true;
-                       } else {
-                               if(wait != nullptr) *wait = 0;
-                               cache_data[addr - start_addr] = (uint8_t)0xff;
+                       if((access_type & CACHE_TYPE_WRITE) != 0) {
+                               if(d_device != NULL) {
+                                       d_device->write_data8w(addr, data, wait);
+                               } else {
+                                       if(wait != nullptr) *wait = 0;
+                                       data = 0xff;
+                               }
+                               if((access_type & CACHE_LINE_READ) != 0) {
+                                       cache_data[addr - start_addr] = (uint8_t)data;
+                                       is_exists[addr - start_addr] = true;
+                               }
+                       } else if((access_type & CACHE_TYPE_READ) != 0) { // read Only
+                               if(is_exists[addr - start_addr]) return;
+                               if(d_device != NULL) {
+                                       cache_data[addr - start_addr] = d_device->read_data8w(addr, wait);
+                               } else {
+                                       if(wait != nullptr) *wait = 0;
+                                       cache_data[addr - start_addr] = 0xff;
+                               }
                                is_exists[addr - start_addr] = true;
                        }
                }