/*
JPC: An x86 PC Hardware Emulator for a pure Java Virtual Machine
Release Version 2.4
A project from the Physics Dept, The University of Oxford
Copyright (C) 2007-2010 The University of Oxford
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as published by
the Free Software Foundation.
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Details (including contact information) can be found at:
jpc.sourceforge.net
or the developer website
sourceforge.net/projects/jpc/
Conceived and Developed by:
Rhys Newman, Ian Preston, Chris Dennis
End of licence header
*/
package org.jpc.debugger;
import java.lang.reflect.*;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import org.jpc.emulator.processor.*;
import org.jpc.emulator.memory.*;
public class LinearMemoryViewer extends MemoryViewer implements ActionListener
{
private PhysicalAddressSpace physicalMemory;
private LinearAddressSpace linearMemory;
private JRadioButton asRead, asWrite, asSupervisor, asUser;
private Memory[] wu, ws, ru, rs;
public LinearMemoryViewer(String title)
{
super(title);
asRead = new JRadioButton("Reading", true);
asRead.addActionListener(this);
asWrite = new JRadioButton("Writing");
asWrite.addActionListener(this);
ButtonGroup group = new ButtonGroup();
group.add(asRead);
group.add(asWrite);
asSupervisor = new JRadioButton("Supervisor", true);
asSupervisor.addActionListener(this);
asUser = new JRadioButton("User");
asUser.addActionListener(this);
group = new ButtonGroup();
group.add(asSupervisor);
group.add(asUser);
JPanel controlPanel = new JPanel(new GridLayout(1, 0, 5, 5));
controlPanel.add(asRead);
controlPanel.add(asWrite);
controlPanel.add(asSupervisor);
controlPanel.add(asUser);
//add("South", controlPanel);
}
public void actionPerformed(ActionEvent evt)
{
refreshDetails();
}
protected MemoryViewPanel createMemoryViewPanel()
{
return new LinearMemoryViewPanel();
}
private Memory[] getIndexArray(String name) throws Exception
{
Field f = LinearAddressSpace.class.getDeclaredField(name);
f.setAccessible(true);
return (Memory[]) f.get(linearMemory);
}
protected void getAddressSpace()
{
physicalMemory = (PhysicalAddressSpace) JPC.getObject(PhysicalAddressSpace.class);
linearMemory = (LinearAddressSpace) JPC.getObject(LinearAddressSpace.class);
memory = linearMemory;
try
{
ru = getIndexArray("readUserIndex");
rs = getIndexArray("readSupervisorIndex");
wu = getIndexArray("writeUserIndex");
ws = getIndexArray("writeSupervisorIndex");
}
catch (Throwable t)
{
t.printStackTrace();
}
}
class LinearMemoryViewPanel extends MemoryViewPanel
{
protected Object formatMemoryDisplay(int address)
{
controllable.lower.setBorder(BorderFactory.createTitledBorder("View Parameters : Physical address = " + Integer.toHexString(translateLinearAddressToInt(physicalMemory, processor, startAddress))));
StringBuffer buf = new StringBuffer("<HTML>");
for (int i=0; i<4; i++, address++)
{
Memory mem = translateLinearAddress(physicalMemory, processor, address);
int index = address >>> AddressSpace.INDEX_SHIFT;
String colourString = "009900";
if (((rs != null) && (rs[index] != null)) || ((ru != null) && (ru[index] != null)) ||
((ws != null) && (ws[index] != null)) || ((wu != null) && (wu[index] != null)))
colourString = "090290";
if (mem == null)
buf.append("<font color='#FF0000'>N</font>");
else
{
int val = mem.getByte(address & AddressSpace.BLOCK_MASK);
buf.append("<font color='#"+colourString+"'>"+zeroPadHex(0xFF & val, 2)+"</font>");
}
}
buf.append("</HTML>");
return buf;
}
protected Object formatAsciiDisplay(int address)
{
StringBuffer buffer = new StringBuffer();
for (int i=0; i<16; i++, address++)
{
Memory mem = translateLinearAddress(physicalMemory, processor, address);
if (mem == null)
buffer.append(' ');
else
buffer.append(getASCII(mem.getByte(address & AddressSpace.BLOCK_MASK)));
}
return buffer;
}
}
public static int translateLinearAddressToInt(PhysicalAddressSpace physical, Processor proc, int offset)
{
if ((proc.getCR0() & 0x80000000) == 0)
return offset;
int baseAddress = proc.getCR3() & 0xFFFFF000;
int idx = offset >>> AddressSpace.INDEX_SHIFT;
int directoryAddress = baseAddress | (0xFFC & (offset >>> 20)); // This should be (offset >>> 22) << 2.
int directoryRawBits = physical.getDoubleWord(directoryAddress);
boolean directoryPresent = (0x1 & directoryRawBits) != 0;
if (!directoryPresent)
return -1;
int tableIndex = (0xFFC00000 & offset) >>> 12;
boolean directoryIs4MegPage = ((0x80 & directoryRawBits) != 0) && ((proc.getCR4() & 0x10) != 0);
if (directoryIs4MegPage)
{
int fourMegPageStartAddress = 0xFFC00000 & directoryRawBits;
return fourMegPageStartAddress | (offset & 0x3FFFFF);
}
else
{
tableIndex = (0xFFFFF000 & offset) >>> 12;
int directoryBaseAddress = directoryRawBits & 0xFFFFF000;
int tableAddress = directoryBaseAddress | ((offset >>> 10) & 0xFFC);
int tableRawBits = physical.getDoubleWord(tableAddress);
boolean tablePresent = (0x1 & tableRawBits) != 0;
if (!tablePresent)
return -1;
int fourKStartAddress = tableRawBits & 0xFFFFF000;
return fourKStartAddress;
}
}
public static Memory translateLinearAddress(PhysicalAddressSpace physical, Processor proc, int offset)
{
if ((proc.getCR0() & 0x80000000) == 0)
return MemoryViewer.getReadMemoryBlockAt(physical, offset);
int baseAddress = proc.getCR3() & 0xFFFFF000;
int idx = offset >>> AddressSpace.INDEX_SHIFT;
int directoryAddress = baseAddress | (0xFFC & (offset >>> 20)); // This should be (offset >>> 22) << 2.
int directoryRawBits = physical.getDoubleWord(directoryAddress);
boolean directoryPresent = (0x1 & directoryRawBits) != 0;
if (!directoryPresent)
return null;
int tableIndex = (0xFFC00000 & offset) >>> 12;
boolean directoryIs4MegPage = ((0x80 & directoryRawBits) != 0) && ((proc.getCR4() & 0x10) != 0);
if (directoryIs4MegPage)
{
int fourMegPageStartAddress = 0xFFC00000 & directoryRawBits;
return MemoryViewer.getReadMemoryBlockAt(physical, fourMegPageStartAddress | (offset & 0x3FFFFF));
}
else
{
tableIndex = (0xFFFFF000 & offset) >>> 12;
int directoryBaseAddress = directoryRawBits & 0xFFFFF000;
int tableAddress = directoryBaseAddress | ((offset >>> 10) & 0xFFC);
int tableRawBits = physical.getDoubleWord(tableAddress);
boolean tablePresent = (0x1 & tableRawBits) != 0;
if (!tablePresent)
return null;
int fourKStartAddress = tableRawBits & 0xFFFFF000;
return MemoryViewer.getReadMemoryBlockAt(physical, fourKStartAddress);
}
}
}