Merge pull request #509 from ajrhacker/master

Refactoring memory map validity checking [ARJ]
This commit is contained in:
Miodrag Milanović 2015-12-20 09:41:44 +01:00
commit 7e4ff974ac
8 changed files with 181 additions and 140 deletions

View File

@ -359,7 +359,7 @@
if #cfg.forcedincludes > 0 then
_p(' FORCE_INCLUDE += -include %s'
,premake.esc(table.concat(cfg.forcedincludes, ";")))
,_MAKE.esc(table.concat(cfg.forcedincludes, ";")))
end
_p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), " "))

View File

@ -197,7 +197,7 @@ const char* builtin_scripts[] = {
"NT = @')\n_p('endif')\n_p('')\n_p('SHELLTYPE := msdos')\n_p('ifeq (,$(ComSpec)$(COMSPEC))')\n_p(' SHELLTYPE := posix')\n_p('endif')\n_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')\n_p(' SHELLTYPE := posix')\n_p('endif')\n_p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))')\n_p(' SHELLTYPE := posix')\n_p('endif')\n_p('')\n_p('ifeq (posix,$(SHELLTYPE))')\n_p(' MKDIR = $(SILENT) mkdir -p \"$(1)\"')\n_p(' COPY = $(SILENT) cp -fR \"$(1)\" \"$(2)\"')\n_p(' RM= $(SILENT) rm -f \"$(1)\"')\n_p('else')\n_p(' MKDIR = $(SILENT) mkdir \"$(subst /,\\\\\\\\,$(1))\" 2> nul || exit 0')\n_p(' COPY = $(SILENT) copy /Y \"$(subst /,\\\\\\\\,$(1))\" \"$(subst /,\\\\\\\\,$(2))\"')\n_p(' RM = $(SILENT) del /F \"$(subst /,\\\\\\\\,$(1))\" 2> nul || exit 0')\n_p('endif')\n_p('')\n_p('CC = %s', cc.cc)\n_p('CXX = %s', cc.cxx)\n_p('AR = %s', cc.ar)\n_p('')\n_p('ifndef RESCOMP')\n_p(' ifdef WINDRES')\n_p(' RESCOMP = $(WINDRES)')\n_p(' else')\n_p(' RESCOMP = windres')\n_p(' endif')\n_p('endif')\n_p('')\nend\nfunction pr"
"emake.gmake_cpp_config(prj, cfg, cc)\n_p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname))\ncpp.platformtools(cfg, cc)\n_p(' ' .. (table.contains(premake.make.override,\"OBJDIR\") and \"override \" or \"\") .. 'OBJDIR = %s', _MAKE.esc(cfg.objectsdir))\n_p(' ' .. (table.contains(premake.make.override,\"TARGETDIR\") and \"override \" or \"\") .. 'TARGETDIR = %s', _MAKE.esc(cfg.buildtarget.directory))\n_p(' ' .. (table.contains(premake.make.override,\"TARGET\") and \"override \" or \"\") .. 'TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name))\n_p(' DEFINES +=%s', make.list(cc.getdefines(cfg.defines)))\n_p(' INCLUDES +=%s', make.list(cc.getincludedirs(cfg.includedirs)))\ncpp.pchconfig(cfg)\ncpp.flags(cfg, cc)\ncpp.linker(prj, cfg, cc)\n_p(' OBJECTS := \\\\')\nfor _, file in ipairs(prj.files) do\nif path.iscppfile(file) then\nif not table.icontains(cfg.excludes, file) then\n_p('\\t$(OBJDIR)/%s.o \\\\'\n, _MAKE.esc(path.trimdots(path.removeext(file)))\n)\nend\nend\nend\n_p('')\n_p(' d"
"efine PREBUILDCMDS')\nif #cfg.prebuildcommands > 0 then\n_p('\\t@echo Running pre-build commands')\n_p('\\t%s', table.implode(cfg.prebuildcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\n_p(' define PRELINKCMDS')\nif #cfg.prelinkcommands > 0 then\n_p('\\t@echo Running pre-link commands')\n_p('\\t%s', table.implode(cfg.prelinkcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\n_p(' define POSTBUILDCMDS')\nif #cfg.postbuildcommands > 0 then\n_p('\\t@echo Running post-build commands')\n_p('\\t%s', table.implode(cfg.postbuildcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\nmake.settings(cfg, cc)\n_p('endif')\n_p('')\nend\nfunction cpp.platformtools(cfg, cc)\nlocal platform = cc.platforms[cfg.platform]\nif platform.cc then\n_p(' CC = %s', platform.cc)\nend\nif platform.cxx then\n_p(' CXX = %s', platform.cxx)\nend\nif platform.ar then\n_p(' AR = %s', platform.ar)\nend\nend\nfunction cpp.flags(cfg, cc)\nif cfg.pchheader and not cfg.flags.NoPCH then\n_p(' FORCE_INCLUDE +="
"-include $(OBJDIR)/$(notdir $(PCH))')\nend\nif #cfg.forcedincludes > 0 then\n_p(' FORCE_INCLUDE += -include %s'\n,premake.esc(table.concat(cfg.forcedincludes, \";\")))\nend\n_p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), \" \"))\n_p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c)))\n_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp)))\n_p(' ALL_OBJCFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_objc)))\n_p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s',\n make.list(table.join(cc.getdefines(cfg.resdefines),\n cc.getincludedirs(cfg.resincludedirs), cfg.resoptions)))\nend\nfunction cpp.linker(prj, cfg"
"-include $(OBJDIR)/$(notdir $(PCH))')\nend\nif #cfg.forcedincludes > 0 then\n_p(' FORCE_INCLUDE += -include %s'\n,_MAKE.esc(table.concat(cfg.forcedincludes, \";\")))\nend\n_p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), \" \"))\n_p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c)))\n_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp)))\n_p(' ALL_OBJCFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_objc)))\n_p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s',\n make.list(table.join(cc.getdefines(cfg.resdefines),\n cc.getincludedirs(cfg.resincludedirs), cfg.resoptions)))\nend\nfunction cpp.linker(prj, cfg"
", cc)\n_p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(table.join(cc.getlibdirflags(cfg), cc.getldflags(cfg), cfg.linkoptions)))\n_p(' LDDEPS +=%s', make.list(_MAKE.esc(premake.getlinks(cfg, \"siblings\", \"fullpath\"))))\n_p(' LIBS += $(LDDEPS)%s', make.list(cc.getlinkflags(cfg)))\nif cfg.kind == \"StaticLib\" then\nif cfg.platform:startswith(\"Universal\") then\n_p(' LINKCMD = libtool -o $(TARGET)')\nelse\nif (not prj.options.ArchiveSplit) then\nif cc.llvm then\n_p(' LINKCMD = $(AR) rcs $(TARGET)')\nelse\n_p(' LINKCMD = $(AR) -rcs $(TARGET)')\nend\nelse\nif cc.llvm then\n_p(' LINKCMD = $(AR) qc $(TARGET)')\n_p(' LINKCMD_NDX= $(AR) cs $(TARGET)')\nelse\n_p(' LINKCMD = $(AR) -qc $(TARGET)')\n_p(' LINKCMD_NDX= $(AR) -cs $(TARGET)')\nend\nend\nend\nelse\nlocal tool = iif(cfg.language == \"C\", \"CC\", \"CXX\")\n_p(' LINKCMD = $(%s) -o $(TARGET) $(OBJECTS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) $(LIBS)', tool)\nend\nend\nfunction cpp.pchconfig(cfg)\nif not cfg.pchheader or cfg.fla"
"gs.NoPCH then\nreturn\nend\nlocal pch = cfg.pchheader\nfor _, incdir in ipairs(cfg.includedirs) do\nlocal abspath = path.getabsolute(path.join(cfg.project.location, incdir))\nlocal testname = path.join(abspath, pch)\nif os.isfile(testname) then\npch = path.getrelative(cfg.location, testname)\nbreak\nend\nend\n_p(' PCH = %s', _MAKE.esc(pch))\n_p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch')\nend\nfunction cpp.pchrules(prj)\n_p('ifneq (,$(PCH))')\n_p('$(GCH): $(PCH)')\n_p('\\t@echo $(notdir $<)')\nlocal cmd = iif(prj.language == \"C\", \"$(CC) -x c-header $(ALL_CFLAGS)\", \"$(CXX) -x c++-header $(ALL_CXXFLAGS)\")\n_p('\\t$(SILENT) %s -MMD -MP $(DEFINES) $(INCLUDES) -o \"$@\" -MF \"$(@:%%.gch=%%.d)\" -c \"$<\"', cmd)\n_p('endif')\n_p('')\nend\nfunction cpp.fileRules(prj)\nfor _, file in ipairs(prj.files or {}) do\nif path.iscppfile(file) then\n_p('$(OBJDIR)/%s.o: %s'\n, _MAKE.esc(path.trimdots(path.removeext(file)))\n, _MAKE.esc(file)\n)\nif (path.isobjcfile(file) and prj.msgcompile_objc) then\n_p('\\t"
"@echo ' .. prj.msgcompile_objc)\nelseif prj.msgcompile then\n_p('\\t@echo ' .. prj.msgcompile)\nelse\n_p('\\t@echo $(notdir $<)')\nend\nif (path.isobjcfile(file)) then\n_p('\\t$(SILENT) $(CXX) $(ALL_OBJCFLAGS) $(FORCE_INCLUDE) -o \"$@\" -MF $(@:%%.o=%%.d) -c \"$<\"')\nelse\ncpp.buildcommand(path.iscfile(file) and not prj.options.ForceCPP, \"o\")\nend\nfor _, task in ipairs(prj.postcompiletasks or {}) do\n_p('\\t$(SILENT) %s', task)\n_p('')\nend\n_p('')\nelseif (path.getextension(file) == \".rc\") then\n_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))\nif prj.msgresource then\n_p('\\t@echo ' .. prj.msgresource)\nelse\n_p('\\t@echo $(notdir $<)')\nend\n_p('\\t$(SILENT) $(RESCOMP) $< -O coff -o \"$@\" $(ALL_RESFLAGS)')\n_p('')\nend\nend\nend\nfunction cpp.dependencyRules(prj)\nfor _, dependency in ipairs(prj.dependency or {}) do\nfor _, dep in ipairs(dependency or {}) do\nif (dep[3]==nil or dep[3]==false) then\n_p('$(OBJDIR)/%s.o: %s'\n, _MAKE.esc(path.trimdots(path.removeext(path.ge"

View File

@ -9,7 +9,6 @@ newoption {
premake.check_paths = true
premake.make.override = { "TARGET" }
MAME_DIR = (path.getabsolute("..") .. "/")
MAME_DIR = string.gsub(MAME_DIR, "(%s)", "\\%1")
local MAME_BUILD_DIR = (MAME_DIR .. _OPTIONS["build-dir"] .. "/")
local naclToolchain = ""
@ -527,9 +526,9 @@ if (_OPTIONS["SOURCES"] == nil) then
end
dofile (path.join("target", _OPTIONS["target"],_OPTIONS["subtarget"] .. ".lua"))
else
OUT_STR = os.outputof( PYTHON .. " " .. MAME_DIR .. "scripts/build/makedep.py " .. MAME_DIR .. " " .. _OPTIONS["SOURCES"] .. " target " .. _OPTIONS["subtarget"])
OUT_STR = os.outputof( PYTHON .. " " .. _MAKE.esc(MAME_DIR) .. "scripts/build/makedep.py " .. _MAKE.esc(MAME_DIR) .. " " .. _OPTIONS["SOURCES"] .. " target " .. _OPTIONS["subtarget"])
load(OUT_STR)()
os.outputof( PYTHON .. " " .. MAME_DIR .. "scripts/build/makedep.py " .. MAME_DIR .. " " .. _OPTIONS["SOURCES"] .. " drivers " .. _OPTIONS["subtarget"] .. " > ".. GEN_DIR .. _OPTIONS["target"] .. "/" .. _OPTIONS["subtarget"].."/drivlist.cpp")
os.outputof( PYTHON .. " " .. _MAKE.esc(MAME_DIR) .. "scripts/build/makedep.py " .. _MAKE.esc(MAME_DIR) .. " " .. _OPTIONS["SOURCES"] .. " drivers " .. _OPTIONS["subtarget"] .. " > " .. _MAKE.esc(GEN_DIR) .. _OPTIONS["target"] .. "/" .. _OPTIONS["subtarget"] .. "/drivlist.cpp")
end
configuration { "gmake" }
flags {

View File

@ -88,7 +88,7 @@ end
targetextension ".bc"
if os.getenv("EMSCRIPTEN") then
postbuildcommands {
os.getenv("EMSCRIPTEN") .. "/emcc -O3 -s DISABLE_EXCEPTION_CATCHING=2 -s USE_SDL=2 --memory-init-file 0 -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_MEMORY=268435456 -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\"]' -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__Z14js_get_machinev', '__Z9js_get_uiv', '__Z12js_get_soundv', '__ZN10ui_manager12set_show_fpsEb', '__ZNK10ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio']\" $(TARGET) -o " .. MAME_DIR .. _OPTIONS["target"] .. _OPTIONS["subtarget"] .. ".js --post-js " .. MAME_DIR .. "src/osd/sdl/emscripten_post.js",
os.getenv("EMSCRIPTEN") .. "/emcc -O3 -s DISABLE_EXCEPTION_CATCHING=2 -s USE_SDL=2 --memory-init-file 0 -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_MEMORY=268435456 -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\"]' -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__Z14js_get_machinev', '__Z9js_get_uiv', '__Z12js_get_soundv', '__ZN10ui_manager12set_show_fpsEb', '__ZNK10ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio']\" $(TARGET) -o " .. _MAKE.esc(MAME_DIR) .. _OPTIONS["target"] .. _OPTIONS["subtarget"] .. ".js --post-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/sdl/emscripten_post.js",
}
end
@ -197,13 +197,13 @@ end
if _OPTIONS["targetos"]=="macosx" and (not override_resources) then
linkoptions {
"-sectcreate __TEXT __info_plist " .. GEN_DIR .. "/resource/" .. _subtarget .. "-Info.plist"
"-sectcreate __TEXT __info_plist " .. _MAKE.esc(GEN_DIR) .. "resource/" .. _subtarget .. "-Info.plist"
}
custombuildtask {
{ MAME_DIR .. "src/version.cpp" , GEN_DIR .. "/resource/" .. _subtarget .. "-Info.plist", { MAME_DIR .. "scripts/build/verinfo.py" }, {"@echo Emitting " .. _subtarget .. "-Info.plist" .. "...", PYTHON .. " $(1) -p -b " .. _subtarget .. " $(<) > $(@)" }},
{ MAME_DIR .. "src/version.cpp" , GEN_DIR .. "resource/" .. _subtarget .. "-Info.plist", { MAME_DIR .. "scripts/build/verinfo.py" }, {"@echo Emitting " .. _subtarget .. "-Info.plist" .. "...", PYTHON .. " $(1) -p -b " .. _subtarget .. " $(<) > $(@)" }},
}
dependency {
{ "$(TARGET)" , GEN_DIR .. "/resource/" .. _subtarget .. "-Info.plist", true },
{ "$(TARGET)" , GEN_DIR .. "resource/" .. _subtarget .. "-Info.plist", true },
}
end
@ -219,7 +219,7 @@ end
rcfile,
}
dependency {
{ "$(OBJDIR)/".._subtarget ..".res" , GEN_DIR .. "/resource/" .. rctarget .. "vers.rc", true },
{ "$(OBJDIR)/".._subtarget ..".res" , GEN_DIR .. "resource/" .. rctarget .. "vers.rc", true },
}
else
rctarget = "mame"
@ -227,7 +227,7 @@ end
MAME_DIR .. "src/mame/osd/windows/mame/mame.rc",
}
dependency {
{ "$(OBJDIR)/mame.res" , GEN_DIR .. "/resource/" .. rctarget .. "vers.rc", true },
{ "$(OBJDIR)/mame.res" , GEN_DIR .. "resource/" .. rctarget .. "vers.rc", true },
}
end
end
@ -261,14 +261,14 @@ if _OPTIONS["FORCE_VERSION_COMPILE"]=="1" then
end
configuration { "mingw*" }
custombuildtask {
{ MAME_DIR .. "src/version.cpp" , GEN_DIR .. "/resource/" .. rctarget .. "vers.rc", { MAME_DIR .. "scripts/build/verinfo.py" }, {"@echo Emitting " .. rctarget .. "vers.rc" .. "...", PYTHON .. " $(1) -r -b " .. rctarget .. " $(<) > $(@)" }},
{ MAME_DIR .. "src/version.cpp" , GEN_DIR .. "resource/" .. rctarget .. "vers.rc", { MAME_DIR .. "scripts/build/verinfo.py" }, {"@echo Emitting " .. rctarget .. "vers.rc" .. "...", PYTHON .. " $(1) -r -b " .. rctarget .. " $(<) > $(@)" }},
}
configuration { "vs*" }
prebuildcommands {
"mkdir " .. path.translate(GEN_DIR .. "/resource/","\\") .. " 2>NUL",
"mkdir " .. path.translate(GEN_DIR .. "resource/","\\") .. " 2>NUL",
"@echo Emitting ".. rctarget .. "vers.rc...",
PYTHON .. " " .. path.translate(MAME_DIR .. "scripts/build/verinfo.py","\\") .. " -r -b " .. rctarget .. " " .. path.translate(MAME_DIR .. "src/version.cpp","\\") .. " > " .. path.translate(GEN_DIR .. "/resource/" .. rctarget .. "vers.rc", "\\") ,
PYTHON .. " " .. path.translate(MAME_DIR .. "scripts/build/verinfo.py","\\") .. " -r -b " .. rctarget .. " " .. path.translate(MAME_DIR .. "src/version.cpp","\\") .. " > " .. path.translate(GEN_DIR .. "resource/" .. rctarget .. "vers.rc", "\\") ,
}

View File

@ -9,6 +9,15 @@
***************************************************************************/
#include "emu.h"
#include "validity.h"
//**************************************************************************
// PARAMETERS
//**************************************************************************
#define DETECT_OVERLAPPING_MEMORY (0)
//**************************************************************************
@ -332,7 +341,7 @@ address_map::address_map(device_t &device, address_spacenum spacenum)
// and then the configuration for the current address space
const address_space_config *spaceconfig = memintf->space_config(spacenum);
if (!device.interface(memintf))
if (spaceconfig == nullptr)
throw emu_fatalerror("No memory address space configuration found for device '%s', space %d\n", device.tag(), spacenum);
// construct the internal device map (first so it takes priority)
@ -614,3 +623,145 @@ void address_map::uplift_submaps(running_machine &machine, device_t &device, dev
}
}
}
//-------------------------------------------------
// map_validity_check - perform validity checks on
// one of the device's address maps
//-------------------------------------------------
void address_map::map_validity_check(validity_checker &valid, const device_t &device, address_spacenum spacenum) const
{
// it's safe to assume here that the device has a memory interface and a config for this space
const address_space_config &spaceconfig = *device.memory().space_config(spacenum);
int datawidth = spaceconfig.m_databus_width;
int alignunit = datawidth / 8;
bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true;
// if this is an empty map, just ignore it
if (m_entrylist.first() == nullptr)
return;
// validate the global map parameters
if (m_spacenum != spacenum)
osd_printf_error("Space %d has address space %d handlers!\n", spacenum, m_spacenum);
if (m_databits != datawidth)
osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig.m_name, datawidth, m_databits);
// loop over entries and look for errors
for (address_map_entry *entry = m_entrylist.first(); entry != nullptr; entry = entry->next())
{
UINT32 bytestart = spaceconfig.addr2byte(entry->m_addrstart);
UINT32 byteend = spaceconfig.addr2byte_end(entry->m_addrend);
// look for overlapping entries
if (!detected_overlap)
{
for (address_map_entry *scan = m_entrylist.first(); scan != entry; scan = scan->next())
if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart &&
((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) ||
(entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE)))
{
osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig.m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type);
detected_overlap = true;
break;
}
}
// look for inverted start/end pairs
if (byteend < bytestart)
osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig.m_name, entry->m_addrstart, entry->m_addrend);
// look for misaligned entries
if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig.m_name, entry->m_addrstart, entry->m_addrend, alignunit);
// if this is a program space, auto-assign implicit ROM entries
if (entry->m_read.m_type == AMH_ROM && entry->m_region == nullptr)
{
entry->m_region = device.tag();
entry->m_rgnoffs = entry->m_addrstart;
}
// if this entry references a memory region, validate it
if (entry->m_region != nullptr && entry->m_share == nullptr)
{
// make sure we can resolve the full path to the region
bool found = false;
std::string entry_region = entry->m_devbase.subtag(entry->m_region);
// look for the region
device_iterator deviter(device.mconfig().root_device());
for (device_t *dev = deviter.first(); dev != nullptr; dev = deviter.next())
for (const rom_entry *romp = rom_first_region(*dev); romp != nullptr && !found; romp = rom_next_region(romp))
{
if (rom_region_name(*dev, romp) == entry_region)
{
// verify the address range is within the region's bounds
offs_t length = ROMREGION_GETLENGTH(romp);
if (entry->m_rgnoffs + (byteend - bytestart + 1) > length)
osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig.m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length);
found = true;
}
}
// error if not found
if (!found)
osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig.m_name, entry->m_addrstart, entry->m_addrend, entry->m_region);
}
// make sure all devices exist
if (entry->m_read.m_type == AMH_DEVICE_DELEGATE)
{
// extract the device tag from the proto-delegate
const char *devtag = nullptr;
switch (entry->m_read.m_bits)
{
case 8: devtag = entry->m_rproto8.device_name(); break;
case 16: devtag = entry->m_rproto16.device_name(); break;
case 32: devtag = entry->m_rproto32.device_name(); break;
case 64: devtag = entry->m_rproto64.device_name(); break;
}
if (entry->m_devbase.subdevice(devtag) == nullptr)
osd_printf_error("%s space memory map entry reads from nonexistant device '%s'\n", spaceconfig.m_name,
devtag != nullptr ? devtag : "<unspecified>");
}
if (entry->m_write.m_type == AMH_DEVICE_DELEGATE)
{
// extract the device tag from the proto-delegate
const char *devtag = nullptr;
switch (entry->m_write.m_bits)
{
case 8: devtag = entry->m_wproto8.device_name(); break;
case 16: devtag = entry->m_wproto16.device_name(); break;
case 32: devtag = entry->m_wproto32.device_name(); break;
case 64: devtag = entry->m_wproto64.device_name(); break;
}
if (entry->m_devbase.subdevice(devtag) == nullptr)
osd_printf_error("%s space memory map entry writes to nonexistant device '%s'\n", spaceconfig.m_name,
devtag != nullptr ? devtag : "<unspecified>");
}
if (entry->m_setoffsethd.m_type == AMH_DEVICE_DELEGATE)
{
// extract the device tag from the proto-delegate
const char *devtag = entry->m_soproto.device_name();
if (entry->m_devbase.subdevice(devtag) == nullptr)
osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig.m_name,
devtag != nullptr ? devtag : "<unspecified>");
}
// make sure ports exist
// if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) ||
// (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL))
// osd_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig.m_name, entry->m_read.m_tag);
// validate bank and share tags
if (entry->m_read.m_type == AMH_BANK)
valid.validate_tag(entry->m_read.m_tag);
if (entry->m_write.m_type == AMH_BANK)
valid.validate_tag(entry->m_write.m_tag);
if (entry->m_share != nullptr)
valid.validate_tag(entry->m_share);
}
}

View File

@ -43,6 +43,10 @@ enum map_handler_type
// TYPE DEFINITIONS
//**************************************************************************
// forward declarations
class validity_checker;
// address map handler data
class map_handler_data
{
@ -289,6 +293,7 @@ public:
simple_list<address_map_entry> m_entrylist; // list of entries
void uplift_submaps(running_machine &machine, device_t &device, device_t &owner, endianness_t endian);
void map_validity_check(validity_checker &valid, const device_t &device, address_spacenum spacenum) const;
};
@ -309,6 +314,7 @@ void ADDRESS_MAP_NAME(_name)(address_map &map, device_t &device) \
typedef write##_bits##_delegate write_delegate ATTR_UNUSED; \
address_map_entry##_bits *curentry = NULL; \
(void)curentry; \
assert(&device != nullptr); \
map.configure(_space, _bits); \
typedef _class drivdata_class ATTR_UNUSED;
#define DEVICE_ADDRESS_MAP_START(_name, _bits, _class) \
@ -318,6 +324,7 @@ void _class :: _name(::address_map &map, device_t &device) \
typedef write##_bits##_delegate write_delegate ATTR_UNUSED; \
address_map_entry##_bits *curentry = NULL; \
(void)curentry; \
assert(&device != nullptr); \
map.configure(AS_PROGRAM, _bits); \
typedef _class drivdata_class ATTR_UNUSED;
#define ADDRESS_MAP_END \

View File

@ -74,7 +74,10 @@ public:
device_delegate(const thistype &src, device_t &search_root) : basetype(src), device_delegate_helper(src.m_device_name) { bind_relative_to(search_root); }
// perform the binding
void bind_relative_to(device_t &search_root) { if (!basetype::isnull()) basetype::late_bind(bound_object(search_root)); }
void bind_relative_to(device_t &search_root) { assert(&search_root != nullptr); if (!basetype::isnull()) basetype::late_bind(bound_object(search_root)); }
// getter (for validation purposes)
const char *device_name() const { return m_device_name; }
};

View File

@ -12,14 +12,6 @@
#include "validity.h"
//**************************************************************************
// PARAMETERS
//**************************************************************************
#define DETECT_OVERLAPPING_MEMORY (0)
//**************************************************************************
// CONSTANTS
//**************************************************************************
@ -238,127 +230,16 @@ bool device_memory_interface::memory_readop(offs_t offset, int size, UINT64 &val
void device_memory_interface::interface_validity_check(validity_checker &valid) const
{
bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true;
// loop over all address spaces
for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; ++spacenum)
{
const address_space_config *spaceconfig = space_config(spacenum);
if (spaceconfig != nullptr)
if (space_config(spacenum) != nullptr)
{
int datawidth = spaceconfig->m_databus_width;
int alignunit = datawidth / 8;
// construct the map
::address_map addrmap(const_cast<device_t &>(device()), spacenum);
// construct the maps
auto map = global_alloc(::address_map(const_cast<device_t &>(device()), spacenum));
// if this is an empty map, just skip it
if (map->m_entrylist.first() == nullptr)
{
global_free(map);
continue;
}
// validate the global map parameters
if (map->m_spacenum != spacenum)
osd_printf_error("Space %d has address space %d handlers!\n", spacenum, map->m_spacenum);
if (map->m_databits != datawidth)
osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig->m_name, datawidth, map->m_databits);
// loop over entries and look for errors
for (address_map_entry *entry = map->m_entrylist.first(); entry != nullptr; entry = entry->next())
{
UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart);
UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend);
// look for overlapping entries
if (!detected_overlap)
{
address_map_entry *scan;
for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next())
if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart &&
((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) ||
(entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE)))
{
osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type);
detected_overlap = true;
break;
}
}
// look for inverted start/end pairs
if (byteend < bytestart)
osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend);
// look for misaligned entries
if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit);
// if this is a program space, auto-assign implicit ROM entries
if (entry->m_read.m_type == AMH_ROM && entry->m_region == nullptr)
{
entry->m_region = device().tag();
entry->m_rgnoffs = entry->m_addrstart;
}
// if this entry references a memory region, validate it
if (entry->m_region != nullptr && entry->m_share == nullptr)
{
// make sure we can resolve the full path to the region
bool found = false;
std::string entry_region = entry->m_devbase.subtag(entry->m_region);
// look for the region
device_iterator deviter(device().mconfig().root_device());
for (device_t *device = deviter.first(); device != nullptr; device = deviter.next())
for (const rom_entry *romp = rom_first_region(*device); romp != nullptr && !found; romp = rom_next_region(romp))
{
if (rom_region_name(*device, romp) == entry_region)
{
// verify the address range is within the region's bounds
offs_t length = ROMREGION_GETLENGTH(romp);
if (entry->m_rgnoffs + (byteend - bytestart + 1) > length)
osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length);
found = true;
}
}
// error if not found
if (!found)
osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region);
}
// make sure all devices exist
// FIXME: This doesn't work! AMH_DEVICE_DELEGATE entries don't even set m_tag, the device tag is inside the proto-delegate
if (entry->m_read.m_type == AMH_DEVICE_DELEGATE && entry->m_read.m_tag != nullptr)
{
std::string temp(entry->m_read.m_tag);
if (device().siblingdevice(temp.c_str()) == nullptr)
osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_read.m_tag);
}
if (entry->m_write.m_type == AMH_DEVICE_DELEGATE && entry->m_write.m_tag != nullptr)
{
std::string temp(entry->m_write.m_tag);
if (device().siblingdevice(temp.c_str()) == nullptr)
osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_write.m_tag);
}
// make sure ports exist
// if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) ||
// (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL))
// osd_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig->m_name, entry->m_read.m_tag);
// validate bank and share tags
if (entry->m_read.m_type == AMH_BANK)
valid.validate_tag(entry->m_read.m_tag);
if (entry->m_write.m_type == AMH_BANK)
valid.validate_tag(entry->m_write.m_tag);
if (entry->m_share != nullptr)
valid.validate_tag(entry->m_share);
}
// release the address map
global_free(map);
// let the map check itself
addrmap.map_validity_check(valid, device(), spacenum);
}
}
}