Class Memory

java.lang.Object
mars.mips.hardware.Memory

public class Memory extends Object
Representation of MIPS memory.
Author:
Pete Sanderson, August 2003; Sean Clarke, May 2024
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    Class representing an arbitrary contiguous region of memory which contains data.
    static interface 
    Interface representing a listener of memory read/write operations.
    static class 
    Class representing an arbitrary contiguous region of memory which contains text.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    MIPS doubleword length in bytes.
    static final int
    MIPS halfword length in bytes.
    static final int
    MIPS word length in bytes.
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Register the given listener to all memory addresses (0x00000000 through 0xFFFFFFFF).
    void
    addListener(Memory.Listener listener, int address)
    Register the given listener to a single address.
    void
    addListener(Memory.Listener listener, int firstAddress, int lastAddress)
    Register the given listener to a range of memory addresses.
    static int
    alignToNext(int address, int alignment)
    Align the given address to the next alignment boundary.
    static int
    alignToPrevious(int address, int alignment)
    Align the given address to the previous alignment boundary.
    int
    allocateHeapSpace(int numBytes)
    Returns the next available word-aligned heap address.
    static void
    enforceDoublewordAlignment(int address, int exceptionCause)
    Ensure that a given address is aligned on a doubleword boundary, throwing an exception otherwise.
    static void
    enforceHalfwordAlignment(int address, int exceptionCause)
    Ensure that a given address is aligned on a halfword boundary, throwing an exception otherwise.
    static void
    enforceWordAlignment(int address, int exceptionCause)
    Ensure that a given address is aligned on a word boundary, throwing an exception otherwise.
    int
    fetch(int address, int length, boolean notify)
    Fetch a byte, halfword, or word from memory at a given address, which must be aligned properly.
    int
    fetchByte(int address, boolean notify)
    Fetch a byte from memory at a given address.
    long
    fetchDoubleword(int address, boolean notify)
    Fetch a doubleword from memory at a given address, which must be aligned to a word boundary.
    int
    fetchHalfword(int address, boolean notify)
    Fetch a halfword from memory at a given address, which must be aligned to a halfword boundary.
    Reads a null-terminated string from memory starting at the given address.
    fetchStatement(int address, boolean notify)
    Fetch a statement from memory at a given address, which must be aligned to a word boundary.
    int
    fetchWord(int address, boolean notify)
    Fetch a word from memory at a given address, which must be aligned to a word boundary.
    fetchWordOrNull(int address)
    Fetch a word from memory at a given address, which must be aligned to a word boundary.
    int
    getAddress(int key)
     
    int
    getAddressOfFirstNullWord(int firstAddress, int lastAddress)
    Search for first "null" memory value in an address range, as indicated by the return value of fetchWordOrNull(int).
    Get the data memory region a given address is mapped to, if applicable.
    Get the current endianness (i.e. byte ordering) in use.
    static Memory
    Get the singleton memory instance.
    int
    Get the next address on the heap which will be used for dynamic memory allocation.
    Get the text memory region a given address is mapped to, if applicable.
    static boolean
    isDoublewordAligned(int address)
    Determine whether a given address is aligned on a doubleword boundary.
    static boolean
    isHalfwordAligned(int address)
    Determine whether a given address is aligned on a halfword boundary.
    boolean
    isInDataSegment(int address)
    Determine whether the given memory address is contained within the data segment, as defined by the current memory configuration.
    boolean
    isInKernelDataSegment(int address)
    Determine whether the given memory address is contained within the kernel data segment, as defined by the current memory configuration.
    boolean
    isInKernelTextSegment(int address)
    Determine whether the given memory address is contained within the kernel text segment, as defined by the current memory configuration.
    boolean
    isInMemoryMappedIO(int address)
    Determine whether the given memory address is contained within the memory-mapped I/O range, as defined by the current memory configuration.
    boolean
    isInTextSegment(int address)
    Determine whether the given memory address is contained within the text segment, as defined by the current memory configuration.
    boolean
    Determine whether the current memory configuration fits a 16-bit address space.
    static boolean
    isWordAligned(int address)
    Determine whether a given address is aligned on a word boundary.
    static boolean
    rangesIntersect(int start1, int end1, int start2, int end2)
    Determine whether two inclusive ranges of unsigned integers intersect.
    static boolean
    rangesMergeable(int start1, int end1, int start2, int end2)
    Determine whether two inclusive ranges of unsigned integers can be merged into a single range.
    void
    Unregister the given listener from all memory addresses it is registered to.
    void
    Reinitialize the memory contents with the current memory configuration (MemoryConfigurations.getCurrentConfiguration()) and reset the heap address to its initial state.
    void
    store(int address, int value, int length, boolean notify)
    Store a byte, halfword, or word in memory at a given address, which must be aligned properly.
    void
    storeByte(int address, int value, boolean notify)
    Store a byte in memory at a given address.
    void
    storeDoubleword(int address, long value, boolean notify)
    Store a doubleword in memory at a given address, which must be aligned to a word boundary.
    void
    storeHalfword(int address, int value, boolean notify)
    Store a halfword in memory at a given address, which must be aligned to a halfword boundary.
    void
    storeStatement(int address, BasicStatement statement, boolean notify)
    Store a statement in memory at a given address, which must be aligned to a word boundary.
    void
    storeWord(int address, int value, boolean notify)
    Store a word in memory at a given address, which must be aligned to a word boundary.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • BYTES_PER_WORD

      public static final int BYTES_PER_WORD
      MIPS word length in bytes.
      See Also:
    • BYTES_PER_HALFWORD

      public static final int BYTES_PER_HALFWORD
      MIPS halfword length in bytes.
      See Also:
    • BYTES_PER_DOUBLEWORD

      public static final int BYTES_PER_DOUBLEWORD
      MIPS doubleword length in bytes.
      See Also:
  • Constructor Details

    • Memory

      public Memory()
  • Method Details

    • isWordAligned

      public static boolean isWordAligned(int address)
      Determine whether a given address is aligned on a word boundary.
      Parameters:
      address - The address to check.
      Returns:
      True if address is word-aligned, false otherwise.
    • enforceWordAlignment

      public static void enforceWordAlignment(int address, int exceptionCause) throws AddressErrorException
      Ensure that a given address is aligned on a word boundary, throwing an exception otherwise.
      Parameters:
      address - The address to check.
      exceptionCause - The cause given if an exception is thrown (usually either ExceptionCause.ADDRESS_STORE or ExceptionCause.ADDRESS_FETCH).
      Throws:
      AddressErrorException - Thrown if the address is not word-aligned.
    • isHalfwordAligned

      public static boolean isHalfwordAligned(int address)
      Determine whether a given address is aligned on a halfword boundary.
      Parameters:
      address - The address to check.
      Returns:
      True if address is halfword-aligned, false otherwise.
    • enforceHalfwordAlignment

      public static void enforceHalfwordAlignment(int address, int exceptionCause) throws AddressErrorException
      Ensure that a given address is aligned on a halfword boundary, throwing an exception otherwise.
      Parameters:
      address - The address to check.
      exceptionCause - The cause given if an exception is thrown (usually either ExceptionCause.ADDRESS_STORE or ExceptionCause.ADDRESS_FETCH).
      Throws:
      AddressErrorException - Thrown if the address is not halfword-aligned.
    • isDoublewordAligned

      public static boolean isDoublewordAligned(int address)
      Determine whether a given address is aligned on a doubleword boundary.
      Parameters:
      address - The address to check.
      Returns:
      True if address is doubleword-aligned, false otherwise.
    • enforceDoublewordAlignment

      public static void enforceDoublewordAlignment(int address, int exceptionCause) throws AddressErrorException
      Ensure that a given address is aligned on a doubleword boundary, throwing an exception otherwise.
      Parameters:
      address - The address to check.
      exceptionCause - The cause given if an exception is thrown (usually either ExceptionCause.ADDRESS_STORE or ExceptionCause.ADDRESS_FETCH).
      Throws:
      AddressErrorException - Thrown if the address is not doubleword-aligned.
    • alignToNext

      public static int alignToNext(int address, int alignment)
      Align the given address to the next alignment boundary. If the address is already aligned, it is left unchanged.
      Parameters:
      address - The memory address to align.
      alignment - The alignment required in bytes, which must be a power of 2.
      Returns:
      The next address divisible by alignment.
    • alignToPrevious

      public static int alignToPrevious(int address, int alignment)
      Align the given address to the previous alignment boundary. If the address is already aligned, it is left unchanged.
      Parameters:
      address - The memory address to align.
      alignment - The alignment required in bytes, which must be a power of 2.
      Returns:
      The previous address divisible by alignment.
    • rangesIntersect

      public static boolean rangesIntersect(int start1, int end1, int start2, int end2)
      Determine whether two inclusive ranges of unsigned integers intersect. In order for the ranges to intersect, they must share at least one integer between them; thus, ranges that "touch" but do not overlap are not considered to intersect.

      For meaningful results, it should hold that start1end1 and start2end2 (when treated as unsigned integers).

      Parameters:
      start1 - The first unsigned integer specified by the first range.
      end1 - The last unsigned integer specified by the first range.
      start2 - The first unsigned integer specified by the second range.
      end2 - The last unsigned integer specified by the second range.
      Returns:
      true if the ranges [start1, end1] and [start2, end2] share any elements, or false otherwise.
      See Also:
    • rangesMergeable

      public static boolean rangesMergeable(int start1, int end1, int start2, int end2)
      Determine whether two inclusive ranges of unsigned integers can be merged into a single range. In order for the ranges to be mergeable, they must either intersect or be adjacent. This is different than the condition for rangesIntersect(int, int, int, int) since ranges that only "touch" are also considered mergeable.

      For meaningful results, it should hold that start1end1 and start2end2 (when treated as unsigned integers).

      Parameters:
      start1 - The first unsigned integer specified by the first range.
      end1 - The last unsigned integer specified by the first range.
      start2 - The first unsigned integer specified by the second range.
      end2 - The last unsigned integer specified by the second range.
      Returns:
      true if the ranges [start1, end1] and [start2, end2] can be merged into a single range, or false otherwise.
      See Also:
    • getInstance

      public static Memory getInstance()
      Get the singleton memory instance.
    • reset

      public void reset()
      Reinitialize the memory contents with the current memory configuration (MemoryConfigurations.getCurrentConfiguration()) and reset the heap address to its initial state.
    • getAddress

      public int getAddress(int key)
    • getEndianness

      public Endianness getEndianness()
      Get the current endianness (i.e. byte ordering) in use. This reflects the value of Settings.useBigEndian; however, it is only updated when reset() is called.
      Returns:
      Either Endianness.LITTLE_ENDIAN or Endianness.BIG_ENDIAN.
    • getNextHeapAddress

      public int getNextHeapAddress()
      Get the next address on the heap which will be used for dynamic memory allocation.
      Returns:
      The next heap address, which is always word-aligned.
    • allocateHeapSpace

      public int allocateHeapSpace(int numBytes) throws IllegalArgumentException
      Returns the next available word-aligned heap address. This is roughly equivalent to malloc in C. Unfortunately, there is currently no way to deallocate space. (Might be added in the future.)
      Parameters:
      numBytes - Number of contiguous bytes to allocate.
      Returns:
      Address of the allocated heap storage.
      Throws:
      IllegalArgumentException - Thrown if the number of requested bytes is negative or exceeds available heap storage.
    • isUsingCompactAddressSpace

      public boolean isUsingCompactAddressSpace()
      Determine whether the current memory configuration fits a 16-bit address space.
      Returns:
      True if the highest mapped address can be stored in 16 bits, false otherwise.
    • isInTextSegment

      public boolean isInTextSegment(int address)
      Determine whether the given memory address is contained within the text segment, as defined by the current memory configuration.
      Parameters:
      address - The byte address to check.
      Returns:
      True if the address is within the text segment, false otherwise.
    • isInKernelTextSegment

      public boolean isInKernelTextSegment(int address)
      Determine whether the given memory address is contained within the kernel text segment, as defined by the current memory configuration.
      Parameters:
      address - The byte address to check.
      Returns:
      True if the address is within the kernel text segment, false otherwise.
    • isInDataSegment

      public boolean isInDataSegment(int address)
      Determine whether the given memory address is contained within the data segment, as defined by the current memory configuration.
      Parameters:
      address - The byte address to check.
      Returns:
      True if the address is within the data segment, false otherwise.
    • isInKernelDataSegment

      public boolean isInKernelDataSegment(int address)
      Determine whether the given memory address is contained within the kernel data segment, as defined by the current memory configuration.
      Parameters:
      address - The byte address to check.
      Returns:
      True if the address is within the kernel data segment, false otherwise.
    • isInMemoryMappedIO

      public boolean isInMemoryMappedIO(int address)
      Determine whether the given memory address is contained within the memory-mapped I/O range, as defined by the current memory configuration.
      Parameters:
      address - The byte address to check.
      Returns:
      True if the address is within the memory-mapped I/O range, false otherwise.
    • getDataRegionForAddress

      public Memory.DataRegion getDataRegionForAddress(int address)
      Get the data memory region a given address is mapped to, if applicable.
      Parameters:
      address - The address to find the region for.
      Returns:
      The corresponding data region, or null if no data regions use the given address.
    • getTextRegionForAddress

      public Memory.TextRegion getTextRegionForAddress(int address)
      Get the text memory region a given address is mapped to, if applicable.
      Parameters:
      address - The address to find the region for.
      Returns:
      The corresponding text region, or null if no text regions use the given address.
    • store

      public void store(int address, int value, int length, boolean notify) throws AddressErrorException
      Store a byte, halfword, or word in memory at a given address, which must be aligned properly. May write to a memory region containing text, but only if Settings.selfModifyingCodeEnabled is set to true.

      This method simply delegates to storeByte(int, int, boolean), storeHalfword(int, int, boolean), or storeWord(int, int, boolean).

      Parameters:
      address - Address where memory will be written.
      value - Value to be stored at that address.
      length - Number of bytes to be written. Must be 1 (single byte), BYTES_PER_HALFWORD, or BYTES_PER_WORD. No other values are accepted.
      notify - Whether to notify listeners of the write operation.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned, is out of range, or does not allow this operation.
    • storeWord

      public void storeWord(int address, int value, boolean notify) throws AddressErrorException
      Store a word in memory at a given address, which must be aligned to a word boundary. May write to a memory region containing text, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Address of the word where memory will be written.
      value - Value to be stored at that address.
      notify - Whether to notify listeners of the write operation.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned, is out of range, or does not allow this operation.
    • storeHalfword

      public void storeHalfword(int address, int value, boolean notify) throws AddressErrorException
      Store a halfword in memory at a given address, which must be aligned to a halfword boundary. May write to a memory region containing text, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Address of the halfword where memory will be written.
      value - Value to be stored at that address. (Only the lowest 16 bits are used.)
      notify - Whether to notify listeners of the write operation.
      Throws:
      AddressErrorException - Thrown if the given address is not halfword-aligned, is out of range, or does not allow this operation.
    • storeByte

      public void storeByte(int address, int value, boolean notify) throws AddressErrorException
      Store a byte in memory at a given address. May write to a memory region containing text, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Address of the byte where memory will be written.
      value - Value to be stored at that address. (Only the lowest 8 bits are used.)
      notify - Whether to notify listeners of the write operation.
      Throws:
      AddressErrorException - Thrown if the given address is out of range or does not allow this operation.
    • storeDoubleword

      public void storeDoubleword(int address, long value, boolean notify) throws AddressErrorException
      Store a doubleword in memory at a given address, which must be aligned to a word boundary. (Note that aligning to a doubleword boundary is not required.) May write to a memory region containing text, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Address of the first word where memory will be written.
      value - Value to be stored at that address.
      notify - Whether to notify listeners of the 2 write operations (1 for each word).
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned, is out of range, or does not allow this operation.
    • storeStatement

      public void storeStatement(int address, BasicStatement statement, boolean notify) throws AddressErrorException
      Store a statement in memory at a given address, which must be aligned to a word boundary. May write to a memory region containing data, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Word-aligned address where memory will be written.
      statement - Value to be stored at that address.
      notify - Whether to notify listeners of the write operation.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned, is out of range, or does not allow this operation.
    • fetch

      public int fetch(int address, int length, boolean notify) throws AddressErrorException
      Fetch a byte, halfword, or word from memory at a given address, which must be aligned properly. May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false.

      This method simply delegates to fetchByte(int, boolean), fetchHalfword(int, boolean), or fetchWord(int, boolean).

      Parameters:
      address - Address where memory will be read.
      length - Number of bytes to read. Must be 1 (single byte), BYTES_PER_HALFWORD, or BYTES_PER_WORD. No other values are accepted.
      notify - Whether to notify listeners of the read operation.
      Returns:
      The value fetched from memory.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned or is out of range.
    • fetchWord

      public int fetchWord(int address, boolean notify) throws AddressErrorException
      Fetch a word from memory at a given address, which must be aligned to a word boundary. May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false.
      Parameters:
      address - Address of the word to fetch.
      notify - Whether to notify listeners of the read operation.
      Returns:
      The value fetched from memory.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned or is out of range.
    • fetchWordOrNull

      public Integer fetchWordOrNull(int address) throws AddressErrorException
      Fetch a word from memory at a given address, which must be aligned to a word boundary. May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false. Listeners are not notified of a read operation.

      Returns null if one of the following is true:

      • The address lies in a region containing text and there is no instruction at the given address.
      • The address lies in a region containing data and the 4-KiB block surrounding it has not been written to since the last call to reset().
      • The address lies in an unmapped portion of memory.

      This method was originally developed by Greg Giberling of UC Berkeley to support the memory dump feature that he implemented in Fall 2007.

      Parameters:
      address - Word-aligned address where memory will be read.
      Returns:
      The value fetched from memory, or null as described above.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned.
    • fetchHalfword

      public int fetchHalfword(int address, boolean notify) throws AddressErrorException
      Fetch a halfword from memory at a given address, which must be aligned to a halfword boundary. May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false.
      Parameters:
      address - Address of the halfword to fetch.
      notify - Whether to notify listeners of the read operation.
      Returns:
      The zero-extended value fetched from memory. (Only the lowest 16 bits are used.)
      Throws:
      AddressErrorException - Thrown if the given address is not halfword-aligned or is out of range.
    • fetchByte

      public int fetchByte(int address, boolean notify) throws AddressErrorException
      Fetch a byte from memory at a given address. May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false.
      Parameters:
      address - Address of the byte to fetch.
      notify - Whether to notify listeners of the read operation.
      Returns:
      The zero-extended value fetched from memory. (Only the lowest 8 bits are used.)
      Throws:
      AddressErrorException - Thrown if the given address is out of range.
    • fetchDoubleword

      public long fetchDoubleword(int address, boolean notify) throws AddressErrorException
      Fetch a doubleword from memory at a given address, which must be aligned to a word boundary. (Note that aligning to a doubleword boundary is not required.) May read from a memory region containing text, even if Settings.selfModifyingCodeEnabled is set to false.
      Parameters:
      address - Address of the first word to fetch.
      notify - Whether to notify listeners of the 2 read operations (1 for each word).
      Returns:
      The value fetched from memory.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned or is out of range.
    • fetchStatement

      public BasicStatement fetchStatement(int address, boolean notify) throws AddressErrorException
      Fetch a statement from memory at a given address, which must be aligned to a word boundary. May read from a memory region containing data, but only if Settings.selfModifyingCodeEnabled is set to true.
      Parameters:
      address - Address of the statement to fetch.
      notify - Whether to notify listeners of the read operation.
      Returns:
      The statement fetched from memory, or null if no statement exists at the given address.
      Throws:
      AddressErrorException - Thrown if the given address is not word-aligned, is out of range, or does not allow this operation.
    • fetchNullTerminatedString

      public String fetchNullTerminatedString(int address) throws AddressErrorException
      Reads a null-terminated string from memory starting at the given address.
      Parameters:
      address - The address of the first byte in the string.
      Returns:
      The string from memory, excluding the null terminator.
      Throws:
      AddressErrorException - If a byte cannot be read at any point.
    • getAddressOfFirstNullWord

      public int getAddressOfFirstNullWord(int firstAddress, int lastAddress) throws AddressErrorException
      Search for first "null" memory value in an address range, as indicated by the return value of fetchWordOrNull(int).
      Parameters:
      firstAddress - First address to be searched; the starting point. Must be word-aligned.
      lastAddress - Last address to be searched.
      Returns:
      Address of the first word within the specified range that does not contain a value.
      Throws:
      AddressErrorException - Thrown if the first address is not word-aligned.
    • addListener

      public void addListener(Memory.Listener listener)
      Register the given listener to all memory addresses (0x00000000 through 0xFFFFFFFF). The listener will be notified when any read/write operations occur anywhere in memory.

      This is equivalent to calling addListener(listener, 0x00000000, 0xFFFFFFFF).

      Parameters:
      listener - The listener to add.
    • addListener

      public void addListener(Memory.Listener listener, int address)
      Register the given listener to a single address. The listener will be notified when any read/write operations occur on the byte at that address.

      This is equivalent to calling addListener(listener, address, address).

      Parameters:
      listener - The listener to add.
      address - The memory address of the byte to attach the listener to.
    • addListener

      public void addListener(Memory.Listener listener, int firstAddress, int lastAddress)
      Register the given listener to a range of memory addresses. The range is inclusive; that is, all bytes starting at firstAddress up to (and including) lastAddress will notify the listener if a read/write operation occurs.

      If the listener object has already been attached to an adjacent or overlapping range of memory, those ranges will be merged

      Parameters:
      listener - The listener to add.
      firstAddress - The memory address of the first byte in the range.
      lastAddress - The memory address of the last byte in the range.
    • removeListener

      public void removeListener(Memory.Listener listener)
      Unregister the given listener from all memory addresses it is registered to. The listener will no longer be notified of any read/write operations unless it is added again.
      Parameters:
      listener - The listener to remove.