/* ByteMemoryArea.java (c) 2008-2015 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.engine.memory; import v9t9.common.memory.ByteMemoryAccess; import v9t9.common.memory.IMemoryDomain; import v9t9.common.memory.IMemoryEntry; /** * Byte memory decomposes word accesses into two byte accesses in big-endian order. * <p> * This area provides a basis for "traditional" memory which has a flat * array of bytes with read and/or write support. * * @author ejs */ public class ByteMemoryArea extends MemoryArea { public ByteMemoryArea() { super(0); } public ByteMemoryArea(int latency) { super(latency); } public ByteMemoryArea(int latency, byte[] memory, boolean isStored) { super(latency); if (memory != null && memory.length % IMemoryDomain.AREASIZE != 0) assert false : "memory area size not multiple of " + IMemoryDomain.AREASIZE; this.memory = memory; this.read = memory; if (isStored) this.write = memory; } /* actual memory for area, except for empty mem */ public byte[] memory; /* if non-NULL, we can statically read */ public byte[] read; /* if non-NULL, we can statically write */ public byte[] write; /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (!(obj instanceof ByteMemoryArea)) { return false; } ByteMemoryArea area = (ByteMemoryArea)obj; return area.memory == memory && area.read == read && area.write == write; } @Override public boolean hasWriteAccess() { return read != null && write != null; } @Override public boolean hasReadAccess() { return read != null; } @Override protected int getSize() { return memory != null ? memory.length : 0; } @Override public void copyFromBytes(byte[] array) { if (memory == null) { memory = new byte[array.length]; read = memory; } System.arraycopy(array, 0, memory, 0, Math.min(array.length, memory.length)); } @Override public void copyToBytes(byte[] array) { System.arraycopy(memory, 0, array, 0, Math.min(array.length, memory.length)); } @Override public short readWord(IMemoryEntry entry, int addr) { if (addr + 1 - entry.getAddr() < entry.getSize()) return (short) ((readByte(entry, addr) << 8) | (readByte(entry, (addr + 1) & 0xffff) & 0xff)); else return (short) ((readByte(entry, addr) << 8)); } @Override public byte readByte(IMemoryEntry entry, int addr) { if (read != null) { int offs = addr - entry.getAddr(); if (offs >= 0 && offs < read.length) return read[offs]; } return 0; } @Override public void writeWord(IMemoryEntry entry, int addr, short val) { writeByte(entry, addr, (byte) (val >> 8)); if (addr + 1 - entry.getAddr() < entry.getSize()) writeByte(entry, addr + 1, (byte) (val & 0xff)); } /* (non-Javadoc) * @see v9t9.engine.memory.MemoryArea#patchWord(v9t9.engine.memory.MemoryEntry, int, short) */ @Override public boolean patchWord(MemoryEntry entry, int addr, short value) { int addr1 = addr - entry.getAddr(); byte hi = (byte) (value >> 8); byte lo = (byte) (value & 0xff); if (memory[addr1] != hi || memory[addr1+1] != lo) { memory[addr1] = hi; memory[addr1+1] = lo; return true; } return false; } @Override public void writeByte(IMemoryEntry entry, int addr, byte val) { if (write != null) { int offs = addr - entry.getAddr(); if (offs >= 0 && offs < write.length) write[offs] = val; } } public ByteMemoryAccess getReadMemoryAccess(IMemoryEntry entry, int addr) { return new ByteMemoryAccess(read, addr - entry.getAddr()); } }