/*
GplMmio.java
(c) 2005-2014 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 java.io.PrintWriter;
import ejs.base.properties.IPersistable;
import ejs.base.properties.IProperty;
import ejs.base.settings.ISettingSection;
import ejs.base.settings.Logging;
import ejs.base.utils.HexUtils;
import v9t9.common.client.ISettingsHandler;
import v9t9.common.cpu.ICpu;
import v9t9.common.machine.IBaseMachine;
import v9t9.common.memory.IMemoryDomain;
import v9t9.common.settings.SettingSchema;
import v9t9.common.settings.Settings;
/** GPL chip entry
* @author ejs
*/
public class GplMmio implements IConsoleMmioReader, IConsoleMmioWriter, IPersistable {
static public final SettingSchema settingDumpGplAccess = new SettingSchema(
ISettingsHandler.TRANSIENT,
"DumpGplAccess", Boolean.FALSE);
private IMemoryDomain domain;
short gromaddr;
boolean gromwaddrflag, gromraddrflag;
byte buf;
private IProperty dumpGplAccess;
private IProperty dumpFullInstructions;
/**
*/
public GplMmio(IBaseMachine machine, IMemoryDomain domain) {
if (domain == null) {
throw new IllegalArgumentException();
}
this.domain = domain;
dumpFullInstructions = Settings.get(machine, ICpu.settingDumpFullInstructions);
dumpGplAccess = Settings.get(machine, settingDumpGplAccess);
}
/* GROM has a strange banking scheme where the upper portion
of the address does not change when incremented;
this acts like an 8K bank. */
private short getNextAddr(short addr) {
return (short) (addr+1 & 0x1fff | gromaddr & 0xe000);
}
public int getAddr() {
return gromaddr;
}
public byte getAddrByte() {
return (byte) (getNextAddr(gromaddr) >> 8);
}
public void setAddr(short addr) {
gromaddr = addr;
}
public boolean addrIsComplete() {
return !gromwaddrflag;
}
/**
* @see v9t9.common.memory.Memory.IConsoleMmioReader#read
*/
public byte read(int addr) {
byte ret;
if ((addr & 2) != 0) {
/* >9802, address read */
gromwaddrflag = false;
if (gromraddrflag)
ret = (byte) (gromaddr & 0xff);
else
ret = (byte) (gromaddr >> 8);
gromraddrflag = !gromraddrflag;
} else {
/* >9800, memory read */
if (dumpGplAccess.getBoolean() && dumpFullInstructions.getBoolean()) {
PrintWriter pw = Logging.getLog(dumpFullInstructions);
if (pw != null)
pw.println(
"Read GPL >" + HexUtils.toHex4(gromaddr - 1) + " = >" + HexUtils.toHex2(buf));
}
ret = readGrom();
}
return ret;
}
/**
* @return
*/
private byte readGrom() {
byte ret = buf;
buf = domain.readByte(gromaddr);
gromaddr = getNextAddr(gromaddr);
return ret;
}
/**
* @see v9t9.common.memory.Memory.IConsoleMmioWriter#write
*/
public void write(int addr, byte val) {
if ((addr & 2) != 0) {
/* >9C02, address write */
gromraddrflag = false;
if (gromwaddrflag) {
gromaddr = (short) (gromaddr & 0xff00 | val & 0xff);
readGrom();
}
else
gromaddr = (short) (((val & 0xff) << 8) | gromaddr & 0xff);
gromwaddrflag = !gromwaddrflag;
} else {
/* >9C00, data write */
gromraddrflag = gromwaddrflag = false;
if (dumpGplAccess.getBoolean() && dumpFullInstructions.getBoolean()) {
PrintWriter pw = Logging.getLog(dumpFullInstructions);
if (pw != null)
pw.println(
"Write GPL >" + HexUtils.toHex4(gromaddr - 1) + " = >" + HexUtils.toHex2(val));
}
domain.writeByte(gromaddr - 1, val);
gromaddr = getNextAddr(gromaddr);
}
}
public void loadState(ISettingSection section) {
if (section == null)
return;
gromaddr = (short) section.getInt("Addr");
gromraddrflag = section.getBoolean("ReadAddrFlag");
gromwaddrflag = section.getBoolean("WriteAddrFlag");
buf = domain.readByte(((gromaddr - 1) & 0x1fff) | (gromaddr & 0xe000));
}
public void saveState(ISettingSection section) {
section.put("Addr", gromaddr);
section.put("ReadAddrFlag", gromraddrflag);
section.put("WriteAddrFlag", gromwaddrflag);
}
/**
*
*/
public void reset() {
gromaddr = 0;
gromraddrflag = gromwaddrflag = false;
buf = 0;
}
}