/* 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); } } }