summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/express.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug/express.cpp')
-rw-r--r--src/emu/debug/express.cpp135
1 files changed, 134 insertions, 1 deletions
diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp
index 219ed6a89ef..4408d621460 100644
--- a/src/emu/debug/express.cpp
+++ b/src/emu/debug/express.cpp
@@ -319,7 +319,7 @@ std::string expression_error::code_string() const
case TOO_MANY_STRINGS: return "too many strings";
case INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)";
case NO_SUCH_MEMORY_SPACE: return "non-existent memory space";
- case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)";
+ case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m/s expected)";
case INVALID_MEMORY_NAME: return "invalid memory name";
case MISSING_MEMORY_NAME: return "missing memory name";
default: return "unknown error";
@@ -673,6 +673,11 @@ u64 symbol_table::memory_value(const char *name, expression_space spacenum, u32
return read_memory_region(name, address, size);
break;
+ case EXPSPACE_SHARE:
+ if (name)
+ return read_memory_share(name, address, size);
+ break;
+
default:
break;
}
@@ -783,6 +788,55 @@ u64 symbol_table::read_memory_region(const char *rgntag, offs_t address, int siz
//-------------------------------------------------
+// read_memory_share - read memory from a
+// memory share
+//-------------------------------------------------
+
+u64 symbol_table::read_memory_share(const char *shatag, offs_t address, int size)
+{
+ auto search = get_device_search(m_machine, m_memintf, shatag);
+ memory_share *const share = search.first.memshare(search.second);
+ u64 result = ~u64(0) >> (64 - 8*size);
+
+ // make sure we get a valid base before proceeding
+ if (share)
+ {
+ // call ourself recursively until we are byte-sized
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+ u64 r0, r1;
+
+ // read each half, from lower address to upper address
+ r0 = read_memory_share(shatag, address + 0, halfsize);
+ r1 = read_memory_share(shatag, address + halfsize, halfsize);
+
+ // assemble based on the target endianness
+ if (share->endianness() == ENDIANNESS_LITTLE)
+ result = r0 | (r1 << (8 * halfsize));
+ else
+ result = r1 | (r0 << (8 * halfsize));
+ }
+
+ // only process if we're within range
+ else if (address < share->bytes())
+ {
+ // lowmask specified which address bits are within the databus width
+ u32 lowmask = share->bytewidth() - 1;
+ u8 *base = reinterpret_cast<u8 *>(share->ptr()) + (address & ~lowmask);
+
+ // if we have a valid base, return the appropriate byte
+ if (share->endianness() == ENDIANNESS_LITTLE)
+ result = base[BYTE8_XOR_LE(address) & lowmask];
+ else
+ result = base[BYTE8_XOR_BE(address) & lowmask];
+ }
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
// set_memory_value - write 1,2,4 or 8 bytes at
// the given offset in the given address space
//-------------------------------------------------
@@ -831,6 +885,11 @@ void symbol_table::set_memory_value(const char *name, expression_space spacenum,
write_memory_region(name, address, size, data);
break;
+ case EXPSPACE_SHARE:
+ if (name)
+ write_memory_share(name, address, size, data);
+ break;
+
default:
break;
}
@@ -954,6 +1013,65 @@ void symbol_table::write_memory_region(const char *rgntag, offs_t address, int s
//-------------------------------------------------
+// write_memory_share - write memory to a
+// memory share
+//-------------------------------------------------
+
+void symbol_table::write_memory_share(const char *shatag, offs_t address, int size, u64 data)
+{
+ auto search = get_device_search(m_machine, m_memintf, shatag);
+ memory_share *const share = search.first.memshare(search.second);
+
+ // make sure we get a valid base before proceeding
+ if (share)
+ {
+ // call ourself recursively until we are byte-sized
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+
+ // break apart based on the target endianness
+ u64 halfmask = ~u64(0) >> (64 - 8 * halfsize);
+ u64 r0, r1;
+ if (share->endianness() == ENDIANNESS_LITTLE)
+ {
+ r0 = data & halfmask;
+ r1 = (data >> (8 * halfsize)) & halfmask;
+ }
+ else
+ {
+ r0 = (data >> (8 * halfsize)) & halfmask;
+ r1 = data & halfmask;
+ }
+
+ // write each half, from lower address to upper address
+ write_memory_share(shatag, address + 0, halfsize, r0);
+ write_memory_share(shatag, address + halfsize, halfsize, r1);
+ }
+
+ // only process if we're within range
+ else if (address < share->bytes())
+ {
+ // lowmask specified which address bits are within the databus width
+ u32 lowmask = share->bytewidth() - 1;
+ u8 *base = reinterpret_cast<u8 *>(share->ptr()) + (address & ~lowmask);
+
+ // if we have a valid base, set the appropriate byte
+ if (share->endianness() == ENDIANNESS_LITTLE)
+ {
+ base[BYTE8_XOR_LE(address) & lowmask] = data;
+ }
+ else
+ {
+ base[BYTE8_XOR_BE(address) & lowmask] = data;
+ }
+ notify_memory_modified();
+ }
+ }
+}
+
+
+//-------------------------------------------------
// memory_valid - return true if the given
// memory name/space/offset combination is valid
//-------------------------------------------------
@@ -998,6 +1116,20 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres
}
break;
+ case EXPSPACE_SHARE:
+ if (!name)
+ {
+ return expression_error::MISSING_MEMORY_NAME;
+ }
+ else
+ {
+ auto search = get_device_search(m_machine, m_memintf, name);
+ memory_share *const share = search.first.memshare(search.second);
+ if (!share || !share->ptr())
+ return expression_error::INVALID_MEMORY_NAME;
+ }
+ break;
+
default:
return expression_error::NO_SUCH_MEMORY_SPACE;
}
@@ -1618,6 +1750,7 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st
case 'r': memspace = EXPSPACE_PRGDIRECT; break;
case 'o': memspace = EXPSPACE_OPDIRECT; break;
case 'm': memspace = EXPSPACE_REGION; break;
+ case 's': memspace = EXPSPACE_SHARE; break;
default: throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
}