/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.Allegrex.compiler;
import jpcsp.Memory;
import jpcsp.memory.IMemoryReader;
import jpcsp.memory.MemoryReader;
/**
* @author gid15
*
*/
public class MemoryRange {
private int address;
private int length;
private int[] values;
public MemoryRange(int address, int length) {
setAddress(address);
setLength(length);
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address & Memory.addressMask;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public void updateValues() {
values = new int[length >> 2];
if (!RuntimeContext.hasMemoryInt()) {
IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 4);
for (int i = 0; i < values.length; i++) {
values[i] = memoryReader.readNext();
}
} else {
System.arraycopy(RuntimeContext.getMemoryInt(), address >> 2, values, 0, values.length);
}
}
public boolean isOverlappingWithAddress(int address) {
return this.address <= address && address < this.address + length;
}
public void extendBottom(int size) {
address -= size;
length += size;
}
public void extendTop(int size) {
length += size;
}
public boolean areValuesChanged() {
if (!RuntimeContext.hasMemoryInt()) {
IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 4);
for (int i = 0; i < values.length; i++) {
if (values[i] != memoryReader.readNext()) {
return true;
}
}
} else {
// Optimized for the most common case (i.e. using memoryInt)
int[] memoryInt = RuntimeContext.getMemoryInt();
int memoryIndex = address >> 2;
for (int i = 0; i < values.length; i++, memoryIndex++) {
if (memoryInt[memoryIndex] != values[i]) {
return true;
}
}
}
return false;
}
public boolean isOverlappingWithAddressRange(int address, int size) {
// Address range is completely above or below our range: no overlap
// E.g.:
// [...MemoryRange...]
// [...address&size...] or [...address&size...]
if (address >= this.address + length || address + size < this.address) {
return false;
}
// The range begin or end is within our range: overlap
// E.g.:
// [...MemoryRange...]
// [...address&size...] or [...address&size...]
if (isOverlappingWithAddress(address) || isOverlappingWithAddress(address + size)) {
return true;
}
// Range overlaps completely our range: overlap
// E.g.:
// [...MemoryRange...]
// [.....address&size.....]
if (address < this.address && address + size >= this.address + length) {
return true;
}
// No overlap found
return false;
}
@Override
public String toString() {
return String.format("[0x%08X-0x%08X]", address, address + length);
}
}