Implementing disassembler back-end, yet more adjustments to CPU window
This commit is contained in:
parent
b7c2545ea7
commit
76c95b0523
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2019 Planet Virtual Boy
|
Copyright (C) 2020 Planet Virtual Boy
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -79,7 +79,6 @@ static void cpuDecode(VUE_INST *inst, int32_t bits) {
|
||||||
|
|
||||||
/* Decode by format */
|
/* Decode by format */
|
||||||
switch (inst->format) {
|
switch (inst->format) {
|
||||||
case 0: return; /* Illegal opcode */
|
|
||||||
case 1:
|
case 1:
|
||||||
inst->reg2 = bits >> 21 & 31;
|
inst->reg2 = bits >> 21 & 31;
|
||||||
inst->reg1 = bits >> 16 & 31;
|
inst->reg1 = bits >> 16 & 31;
|
||||||
|
|
|
@ -159,6 +159,7 @@ typedef struct {
|
||||||
|
|
||||||
/* Emulation state */
|
/* Emulation state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
VUE_INST inst; /* Instruction state */
|
||||||
|
|
||||||
/* Memory bus */
|
/* Memory bus */
|
||||||
struct {
|
struct {
|
||||||
|
@ -221,8 +222,6 @@ typedef struct {
|
||||||
uint16_t ecr_fecc; /* Fatal Error Cause Code */
|
uint16_t ecr_fecc; /* Fatal Error Cause Code */
|
||||||
} cpu;
|
} cpu;
|
||||||
|
|
||||||
/* Additional fields */
|
|
||||||
VUE_INST inst; /* Instruction state */
|
|
||||||
} VUE;
|
} VUE;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,257 +0,0 @@
|
||||||
package app;
|
|
||||||
|
|
||||||
// Java imports
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
// Project imports
|
|
||||||
import util.*;
|
|
||||||
import vue.*;
|
|
||||||
|
|
||||||
// CPU window
|
|
||||||
class CPU extends ChildWindow {
|
|
||||||
|
|
||||||
// Instance fields
|
|
||||||
private int expandWidth; // Width of expand buttons
|
|
||||||
private Font font; // Display font
|
|
||||||
private int fontHeight; // Font line height
|
|
||||||
private int fontWidth; // Font maximum character width
|
|
||||||
private boolean shown; // Window has been shown
|
|
||||||
private int systemHeight; // Initial height of system register list
|
|
||||||
|
|
||||||
// UI components
|
|
||||||
private JPanel dasm; // Disassembler
|
|
||||||
private JPanel system; // System registers
|
|
||||||
private JPanel program; // Program registers
|
|
||||||
private ArrayList<Register> registers; // Register controls
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructors //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Default constructor
|
|
||||||
CPU(MainWindow parent) {
|
|
||||||
super(parent, "cpu.title");
|
|
||||||
var client = getContentPane();
|
|
||||||
|
|
||||||
// Configure instance fields
|
|
||||||
font = new Font(Util.fontFamily(new String[]
|
|
||||||
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14);
|
|
||||||
registers = new ArrayList<Register>();
|
|
||||||
|
|
||||||
dasm = new JPanel(null);
|
|
||||||
dasm.setBackground(SystemColor.window);
|
|
||||||
dasm.setFocusable(true);
|
|
||||||
|
|
||||||
var inner = initRegisters();
|
|
||||||
var outer = Util.splitPane(JSplitPane.HORIZONTAL_SPLIT);
|
|
||||||
outer.setLeftComponent(new JScrollPane(dasm,
|
|
||||||
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
|
|
||||||
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
|
|
||||||
outer.setRightComponent(inner);
|
|
||||||
outer.setResizeWeight(1);
|
|
||||||
|
|
||||||
client.add(outer);
|
|
||||||
client.setPreferredSize(new Dimension(480, 300));
|
|
||||||
setFont2(font);
|
|
||||||
pack();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Register Constructors //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize program register list
|
|
||||||
private void initProgram() {
|
|
||||||
Dimension target = null;
|
|
||||||
|
|
||||||
// Program register container
|
|
||||||
var lst = program = new JPanel(new GridBagLayout()) {
|
|
||||||
public Dimension getPreferredSize() {
|
|
||||||
var ret = super.getPreferredSize();
|
|
||||||
if (!shown)
|
|
||||||
ret.height = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
public void paintComponent(Graphics g) {
|
|
||||||
super.paintComponent(g);
|
|
||||||
if (shown)
|
|
||||||
return;
|
|
||||||
shown = true;
|
|
||||||
system.revalidate();
|
|
||||||
program.revalidate();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
lst.setBackground(SystemColor.window);
|
|
||||||
lst.setFocusable(true);
|
|
||||||
lst.addMouseListener(Util.onMouse(e->lst.requestFocus(),null));
|
|
||||||
|
|
||||||
// Produce the list of program registers
|
|
||||||
for (int x = 0; x < 32; x++) {
|
|
||||||
String name = "r" + x;
|
|
||||||
switch (x) {
|
|
||||||
case VUE.GP: name = "gp"; break;
|
|
||||||
case VUE.HP: name = "hp"; break;
|
|
||||||
case VUE.LP: name = "lp"; break;
|
|
||||||
case VUE.SP: name = "sp"; break;
|
|
||||||
case VUE.TP: name = "tp"; break;
|
|
||||||
}
|
|
||||||
registers.add(new Register(
|
|
||||||
parent, lst, name, x, Register.PROGRAM));
|
|
||||||
}
|
|
||||||
endList(lst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize register lists
|
|
||||||
private JSplitPane initRegisters() {
|
|
||||||
initSystem();
|
|
||||||
initProgram();
|
|
||||||
|
|
||||||
var ret = Util.splitPane(JSplitPane.VERTICAL_SPLIT);
|
|
||||||
ret.setTopComponent(new JScrollPane(system,
|
|
||||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
|
||||||
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
|
|
||||||
));
|
|
||||||
ret.setBottomComponent(new JScrollPane(program,
|
|
||||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
|
||||||
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
|
|
||||||
));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize system register list
|
|
||||||
private void initSystem() {
|
|
||||||
|
|
||||||
// System register container
|
|
||||||
var lst = system = new JPanel(new GridBagLayout()) {
|
|
||||||
public Dimension getPreferredSize() {
|
|
||||||
var ret = super.getPreferredSize();
|
|
||||||
if (!shown)
|
|
||||||
ret.height = systemHeight;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
system.setBackground(SystemColor.window);
|
|
||||||
system.setFocusable(true);
|
|
||||||
system.addMouseListener(Util.onMouse(e->system.requestFocus(), null));
|
|
||||||
system.putClientProperty("shown", true);
|
|
||||||
|
|
||||||
// Add the first two system registers and expand PSW
|
|
||||||
int plain = Register.PLAIN;
|
|
||||||
registers.add(new Register(parent, lst, "PC" , VUE.PC , plain ));
|
|
||||||
Register psw =new Register(parent, lst, "PSW" , VUE.PSW , VUE.PSW );
|
|
||||||
psw.setExpanded(true);
|
|
||||||
registers.add(psw);
|
|
||||||
shown = true;
|
|
||||||
systemHeight = system.getPreferredSize().height + 6;
|
|
||||||
shown = false;
|
|
||||||
|
|
||||||
// Add the remaining system registers
|
|
||||||
registers.add(new Register(parent, lst, "EIPC" , VUE.EIPC , plain ));
|
|
||||||
registers.add(new Register(parent, lst, "EIPSW", VUE.EIPSW, VUE.PSW ));
|
|
||||||
registers.add(new Register(parent, lst, "FEPC" , VUE.FEPC , plain ));
|
|
||||||
registers.add(new Register(parent, lst, "FEPSW", VUE.FEPSW, VUE.PSW ));
|
|
||||||
registers.add(new Register(parent, lst, "ECR" , VUE.ECR , VUE.ECR ));
|
|
||||||
registers.add(new Register(parent, lst, "ADTRE", VUE.ADTRE, plain ));
|
|
||||||
registers.add(new Register(parent, lst, "CHCW" , VUE.CHCW , VUE.CHCW));
|
|
||||||
registers.add(new Register(parent, lst, "PIR" , VUE.PIR , VUE.PIR ));
|
|
||||||
registers.add(new Register(parent, lst, "TKCW" , VUE.TKCW , VUE.TKCW));
|
|
||||||
registers.add(new Register(parent, lst, "29" , 29, plain ));
|
|
||||||
registers.add(new Register(parent, lst, "30" , 30, plain ));
|
|
||||||
registers.add(new Register(parent, lst, "31" , 31, plain ));
|
|
||||||
endList(lst);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Event Handlers //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Client resize
|
|
||||||
private void onResize() {
|
|
||||||
//refreshDasm();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Package Methods //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Update the display
|
|
||||||
void refresh() {
|
|
||||||
|
|
||||||
// The element is not ready
|
|
||||||
if (registers == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Refresh registers
|
|
||||||
for (var reg : registers)
|
|
||||||
reg.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specify a new font
|
|
||||||
void setFont2(Font font) {
|
|
||||||
this.font = font;
|
|
||||||
|
|
||||||
// Configure the maximum font dimensions
|
|
||||||
var fontMax = new JLabel("!");
|
|
||||||
fontMax.setFont(font);
|
|
||||||
fontHeight = Math.max(1, fontMax.getPreferredSize().height);
|
|
||||||
fontWidth = -1;
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
fontMax.setText(Integer.toString(x, 16).toUpperCase());
|
|
||||||
fontWidth = Math.max(fontWidth, fontMax.getPreferredSize().width);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure register list scrolling
|
|
||||||
for (int x = 0; x < 2; x++) {
|
|
||||||
Component ctrl = x == 0 ? system : program;
|
|
||||||
while (!(ctrl instanceof JScrollPane))
|
|
||||||
ctrl = ctrl.getParent();
|
|
||||||
((JScrollPane) ctrl).getVerticalScrollBar()
|
|
||||||
.setUnitIncrement(fontHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the width of the register expand buttons
|
|
||||||
var expand = new JLabel("+");
|
|
||||||
int width = expand.getPreferredSize().width;
|
|
||||||
expand.setText("-");
|
|
||||||
width = Math.max(width, expand.getPreferredSize().width) + 4;
|
|
||||||
|
|
||||||
// Configure registers
|
|
||||||
for (var reg : registers) {
|
|
||||||
reg.setExpandWidth(width);
|
|
||||||
reg.setFont(font, fontWidth, fontHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
onResize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private Methods //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Terminate a register list
|
|
||||||
private JPanel endList(JPanel list) {
|
|
||||||
var spacer = new JPanel(null);
|
|
||||||
spacer.setOpaque(false);
|
|
||||||
spacer.setPreferredSize(new Dimension(1, 1));
|
|
||||||
var gbc = new GridBagConstraints();
|
|
||||||
gbc.gridheight = GridBagConstraints.REMAINDER;
|
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
||||||
gbc.weighty = 1;
|
|
||||||
list.add(spacer, gbc);
|
|
||||||
return spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
package app;
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
// Project imports
|
||||||
|
import util.*;
|
||||||
|
import vue.*;
|
||||||
|
|
||||||
|
// CPU window
|
||||||
|
class CPUWindow extends ChildWindow {
|
||||||
|
|
||||||
|
// Instance fields
|
||||||
|
private int expandWidth; // Width of expand buttons
|
||||||
|
private boolean shown; // Window has been shown
|
||||||
|
private int systemHeight; // Initial height of system register list
|
||||||
|
|
||||||
|
// UI components
|
||||||
|
private JPanel dasm; // Disassembler
|
||||||
|
private RegisterList lstProgram; // Program register list
|
||||||
|
private RegisterList lstSystem; // System register list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Global Settings //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int regExpandWidth; // Width of register list expand button
|
||||||
|
static Font regHexFont; // Register list hex font
|
||||||
|
static Dimension regHexFontSize; // Max dimensions
|
||||||
|
static HashSet<CPUWindow> instances; // Spawned instances
|
||||||
|
|
||||||
|
// Static initializer
|
||||||
|
static {
|
||||||
|
setDefaults();
|
||||||
|
instances = new HashSet<CPUWindow>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Static Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Apply configuration settings to all instances
|
||||||
|
static void configureAll() {
|
||||||
|
for (var inst : instances)
|
||||||
|
inst.configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all settings to their default values
|
||||||
|
static void setDefaults() {
|
||||||
|
|
||||||
|
// Register list hex font
|
||||||
|
setRegHexFont(new Font(Util.fontFamily(new String[]
|
||||||
|
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
|
||||||
|
|
||||||
|
// Width of register list expand button
|
||||||
|
var label = new JLabel("+");
|
||||||
|
regExpandWidth = label.getPreferredSize().width;
|
||||||
|
label.setText("-");
|
||||||
|
regExpandWidth = Math.max(regExpandWidth,
|
||||||
|
label.getPreferredSize().width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify a font to use as the register list hex font
|
||||||
|
static void setRegHexFont(Font font) {
|
||||||
|
regHexFont = font;
|
||||||
|
regHexFontSize = measureHex(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
CPUWindow(MainWindow parent) {
|
||||||
|
super(parent, "cpu.title");
|
||||||
|
instances.add(this);
|
||||||
|
|
||||||
|
var client = getContentPane();
|
||||||
|
|
||||||
|
dasm = new JPanel(null);
|
||||||
|
dasm.setBackground(SystemColor.window);
|
||||||
|
dasm.setFocusable(true);
|
||||||
|
|
||||||
|
lstSystem = new RegisterList(this, true);
|
||||||
|
lstProgram = new RegisterList(this, false);
|
||||||
|
var inner = Util.splitPane(JSplitPane.VERTICAL_SPLIT);
|
||||||
|
inner.setTopComponent(lstSystem);
|
||||||
|
inner.setBottomComponent(lstProgram);
|
||||||
|
|
||||||
|
var outer = Util.splitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||||
|
outer.setLeftComponent(new JScrollPane(dasm,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
|
||||||
|
outer.setRightComponent(inner);
|
||||||
|
outer.setResizeWeight(1);
|
||||||
|
|
||||||
|
client.add(outer);
|
||||||
|
client.setPreferredSize(new Dimension(480, 300));
|
||||||
|
configure();
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// The window is closing
|
||||||
|
public void dispose() {
|
||||||
|
instances.remove(this);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Package Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Apply configuration settings
|
||||||
|
void configure() {
|
||||||
|
lstProgram.configure();
|
||||||
|
lstSystem .configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the display
|
||||||
|
void refresh() {
|
||||||
|
lstSystem.refresh();
|
||||||
|
lstProgram.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Event Handlers //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Client resize
|
||||||
|
private void onResize() {
|
||||||
|
//refreshDasm();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Determine the maximum character width of a hex character in a font
|
||||||
|
private static Dimension measureHex(Font font) {
|
||||||
|
int ret = 0;
|
||||||
|
Dimension size = null;
|
||||||
|
|
||||||
|
// Process all digits
|
||||||
|
var label = new JLabel();
|
||||||
|
label.setFont(font);
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
label.setText(String.format(
|
||||||
|
"%" + (Disassembler.hexCaps ? "X" : "x"
|
||||||
|
), x));
|
||||||
|
size = label.getPreferredSize();
|
||||||
|
ret = Math.max(ret, size.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Dimension(ret, size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import java.awt.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
// Console window
|
// Console window
|
||||||
class Console extends ChildWindow {
|
class ConsoleWindow extends ChildWindow {
|
||||||
|
|
||||||
// Instance fields
|
// Instance fields
|
||||||
private boolean shown; // Component has been visible
|
private boolean shown; // Component has been visible
|
||||||
|
@ -17,7 +17,7 @@ class Console extends ChildWindow {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Default constructor
|
// Default constructor
|
||||||
Console(MainWindow parent) {
|
ConsoleWindow(MainWindow parent) {
|
||||||
super(parent, "console.title");
|
super(parent, "console.title");
|
||||||
getContentPane().setPreferredSize(new Dimension(384, 224));
|
getContentPane().setPreferredSize(new Dimension(384, 224));
|
||||||
pack();
|
pack();
|
|
@ -0,0 +1,379 @@
|
||||||
|
package app;
|
||||||
|
|
||||||
|
// Project imports
|
||||||
|
import vue.*;
|
||||||
|
|
||||||
|
// Instruction disassembler
|
||||||
|
class Disassembler {
|
||||||
|
private Disassembler() { } // Cannot be instantiated
|
||||||
|
static { setDefaults(); } // Initialize to default settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Global Settings //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static boolean bcondCombine; // Merge Bcond condition into mnemonic
|
||||||
|
static boolean bcondNames; // Use symbolic condition names for Bcond
|
||||||
|
static boolean condCaps; // Uppercase condition mnemonics
|
||||||
|
static boolean destLast; // Destination register last
|
||||||
|
static boolean dispDest; // Resolve jump destination addresses
|
||||||
|
static boolean dispInside; // Load/store displacement inside brackets
|
||||||
|
static boolean hexCaps; // Upercase hexadecimal
|
||||||
|
static int hexMode; // Hexadecimal decoration
|
||||||
|
static boolean immNumber; // Use number sign with immediate values
|
||||||
|
static boolean jmpBrackets; // Square brackets around JMP
|
||||||
|
static boolean jumpAddress; // Use jump destination addresses
|
||||||
|
static boolean lower; // Use L instead of C in conditions
|
||||||
|
static boolean mnemonicCaps; // Uppercase mnemonics
|
||||||
|
static boolean programCaps; // Uppercase program register names
|
||||||
|
static boolean programNames; // Use symbolic program register names
|
||||||
|
static boolean setfCombine; // Merge SETF condition into mnemonic
|
||||||
|
static boolean setfNames; // Use symbolic condition names for SETF
|
||||||
|
static boolean systemCaps; // Uppercase system register names
|
||||||
|
static boolean systemNames; // Use symbolic system register names
|
||||||
|
static boolean zero; // Use Z instead of E in conditions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constants //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Hexadecimal decorations
|
||||||
|
static final int DOLLAR = 0;
|
||||||
|
static final int H = 1;
|
||||||
|
static final int ZEROX = 2;
|
||||||
|
|
||||||
|
// Condition mneonics
|
||||||
|
static final String[] CONDITIONS = {
|
||||||
|
"V" , "C" , "E" , "NH", "N", "T", "LT", "LE",
|
||||||
|
"NV", "NC", "NE", "H" , "P", "F", "GE", "GT"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mnemonics
|
||||||
|
static final String[] MNEMONICS = {
|
||||||
|
"---" , "ADD" , "ADD" , "ADDF.S", "ADDI" , "AND" ,
|
||||||
|
"ANDBSU" , "ANDI" , "ANDNBSU", "Bcond" , "CAXI" , "CLI" ,
|
||||||
|
"CMP" , "CMP" , "CMPF.S" , "CVT.SW", "CVT.WS" , "DIV" ,
|
||||||
|
"DIVF.S" , "DIVU" , "HALT" , "IN.B" , "IN.H" , "IN.W" ,
|
||||||
|
"JAL" , "JMP" , "JR" , "LD.B" , "LD.H" , "LD.W" ,
|
||||||
|
"LDSR" , "MOV" , "MOV" , "MOVBSU", "MOVEA" , "MOVHI" ,
|
||||||
|
"MPYHW" , "MUL" , "MULF.S" , "MULU" , "NOT" , "NOTBSU" ,
|
||||||
|
"OR" , "ORBSU" , "ORI" , "ORNBSU", "OUT.B" , "OUT.H" ,
|
||||||
|
"OUT.W" , "RETI" , "REV" , "SAR" , "SAR" , "SCH0BSD",
|
||||||
|
"SCH0BSU", "SCH1BSD", "SCH1BSU", "SEI" , "SETF" , "SHL" ,
|
||||||
|
"SHL" , "SHR" , "SHR" , "ST.B" , "ST.H" , "ST.W" ,
|
||||||
|
"STSR" , "SUB" , "SUBF.S" , "TRAP" , "TRNC.SW", "XB" ,
|
||||||
|
"XH" , "XOR" , "XORBSU" , "XORI" , "XORNBSU"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Program register names
|
||||||
|
private static final String[] PROGRAMS = {
|
||||||
|
null, null, "hp", "sp", "gp", "tp", null, null,
|
||||||
|
null, null, null, null, null, null, null, null,
|
||||||
|
null, null, null, null, null, null, null, null,
|
||||||
|
null, null, null, null, null, null, null, "lp"
|
||||||
|
};
|
||||||
|
|
||||||
|
// System register names
|
||||||
|
private static final String[] SYSTEMS = {
|
||||||
|
"EIPC", "EIPSW", "FEPC", "FEPSW", "ECR", "PSW", "PIR", "TKCW",
|
||||||
|
null , null , null , null , null , null , null , null ,
|
||||||
|
null , null , null , null , null , null , null , null ,
|
||||||
|
"CHCW", "ADTRE", null , null , null , null , null , null
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Classes //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// One row of output
|
||||||
|
static class Row {
|
||||||
|
String address; // Bus address
|
||||||
|
String bytes; // Encoded bytes in bus order
|
||||||
|
String mnemonic; // Instruction mnemonic
|
||||||
|
String operands; // Instruction operands, if any
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Static Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Reset all settings to their default values
|
||||||
|
static void setDefaults() {
|
||||||
|
bcondCombine = true;
|
||||||
|
bcondNames = true;
|
||||||
|
condCaps = true;
|
||||||
|
destLast = true;
|
||||||
|
dispDest = true;
|
||||||
|
dispInside = false;
|
||||||
|
hexCaps = true;
|
||||||
|
hexMode = ZEROX;
|
||||||
|
immNumber = false;
|
||||||
|
jmpBrackets = true;
|
||||||
|
jumpAddress = true;
|
||||||
|
lower = true;
|
||||||
|
mnemonicCaps = true;
|
||||||
|
programCaps = false;
|
||||||
|
programNames = true;
|
||||||
|
setfCombine = false;
|
||||||
|
setfNames = true;
|
||||||
|
systemCaps = true;
|
||||||
|
systemNames = true;
|
||||||
|
zero = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Package Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Represent an instruction as text fields
|
||||||
|
static void disassemble(int address, Instruction inst, Row row) {
|
||||||
|
|
||||||
|
// Address
|
||||||
|
String x = hexCaps ? "X" : "x";
|
||||||
|
row.address = String.format("%08" + x, address);
|
||||||
|
|
||||||
|
// Bytes
|
||||||
|
x = "%02" + x;
|
||||||
|
row.bytes = inst.size == 2 ?
|
||||||
|
String.format(x + " " + x,
|
||||||
|
inst.bits >> 16 & 0xFF,
|
||||||
|
inst.bits >> 24 & 0xFF
|
||||||
|
) : String.format(x + " " + x + " " + x + " " + x,
|
||||||
|
inst.bits >> 16 & 0xFF,
|
||||||
|
inst.bits >> 24 & 0xFF,
|
||||||
|
inst.bits & 0xFF,
|
||||||
|
inst.bits >> 8 & 0xFF
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
// Bcond mnemonic
|
||||||
|
if (inst.id == VUE.BCOND && bcondCombine) {
|
||||||
|
row.mnemonic = "B" + CONDITIONS[inst.cond];
|
||||||
|
if (lower && (inst.cond & 7) == 1)
|
||||||
|
row.mnemonic = inst.cond == 1 ? "BL" : "BNL";
|
||||||
|
if (zero && (inst.cond & 7) == 2)
|
||||||
|
row.mnemonic = inst.cond == 2 ? "BZ" : "BNZ";
|
||||||
|
if ( (inst.cond & 7) == 5)
|
||||||
|
row.mnemonic = inst.cond == 5 ? "BR" : "NOP";
|
||||||
|
}
|
||||||
|
|
||||||
|
// SETF mnemonic
|
||||||
|
else if (inst.id == VUE.SETF && setfCombine)
|
||||||
|
row.mnemonic = "SETF" + CONDITIONS[inst.imm];
|
||||||
|
|
||||||
|
// All other mnemonics
|
||||||
|
else row.mnemonic = MNEMONICS[inst.id];
|
||||||
|
|
||||||
|
// Adjust mnemonic case
|
||||||
|
if (!mnemonicCaps)
|
||||||
|
row.mnemonic = row.mnemonic.toLowerCase();
|
||||||
|
|
||||||
|
// Operands by format
|
||||||
|
row.operands = null;
|
||||||
|
if (inst.id != VUE.ILLEGAL) switch (inst.format) {
|
||||||
|
case 1: // Fallthrough
|
||||||
|
case 7: row.operands = formatI_VII(inst ); break;
|
||||||
|
case 2: row.operands = formatII (inst ); break;
|
||||||
|
case 3: row.operands = formatIII (inst, address); break;
|
||||||
|
case 4: row.operands = destination(inst, address); break;
|
||||||
|
case 5: row.operands = formatV (inst ); break;
|
||||||
|
case 6: row.operands = formatVI (inst ); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Format the destination of a branch or jump
|
||||||
|
private static String destination(Instruction inst, int address) {
|
||||||
|
return !dispDest ? toHex(inst.disp, 1, immNumber) :
|
||||||
|
String.format("%08" + (hexCaps ? "X" : "x"), address + inst.disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operands for Format I and Format VII
|
||||||
|
private static String formatI_VII(Instruction inst) {
|
||||||
|
String reg1 = program(inst.reg1);
|
||||||
|
String reg2 = program(inst.reg2);
|
||||||
|
|
||||||
|
// One-operand instructions
|
||||||
|
switch (inst.id) {
|
||||||
|
case VUE.JMP:
|
||||||
|
return String.format(jmpBrackets ? "[%s]" : "%s", reg1);
|
||||||
|
case VUE.XB: // Fallthrough
|
||||||
|
case VUE.XH:
|
||||||
|
return reg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic
|
||||||
|
return String.format("%s, %s",
|
||||||
|
destLast ? reg1 : reg2,
|
||||||
|
destLast ? reg2 : reg1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operands for Format II
|
||||||
|
private static String formatII(Instruction inst) {
|
||||||
|
|
||||||
|
// Bit string
|
||||||
|
if (inst.opcode == 0b011111)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Zero- or one-operand instructions
|
||||||
|
switch (inst.id) {
|
||||||
|
|
||||||
|
// Zero-operand
|
||||||
|
case VUE.CLI : // Fallthrough
|
||||||
|
case VUE.HALT: // Fallthrough
|
||||||
|
case VUE.RETI: // Fallthrough
|
||||||
|
case VUE.SEI :
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// One-operand
|
||||||
|
case VUE.TRAP:
|
||||||
|
return Integer.toString(inst.imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined SETF
|
||||||
|
String reg2 = program(inst.reg2);
|
||||||
|
if (inst.id == VUE.SETF && setfCombine)
|
||||||
|
return reg2;
|
||||||
|
|
||||||
|
// Two-operand instructions
|
||||||
|
String imm = String.format("%s%d", immNumber ? "#" : "", inst.imm);
|
||||||
|
switch (inst.id) {
|
||||||
|
case VUE.LDSR: // Fallthrough
|
||||||
|
case VUE.STSR:
|
||||||
|
if (!systemNames || SYSTEMS[inst.imm] == null)
|
||||||
|
break;
|
||||||
|
imm = SYSTEMS[inst.imm];
|
||||||
|
if (!systemCaps)
|
||||||
|
imm = imm.toLowerCase();
|
||||||
|
break;
|
||||||
|
case VUE.SETF:
|
||||||
|
if (!setfNames)
|
||||||
|
break;
|
||||||
|
imm = CONDITIONS[inst.imm];
|
||||||
|
if (!condCaps)
|
||||||
|
imm = imm.toLowerCase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic
|
||||||
|
return String.format("%s, %s",
|
||||||
|
destLast ? imm : reg2,
|
||||||
|
destLast ? reg2 : imm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operands for Format III
|
||||||
|
private static String formatIII(Instruction inst, int address) {
|
||||||
|
|
||||||
|
// NOP
|
||||||
|
if (bcondCombine && inst.cond == 13)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Format destination
|
||||||
|
String dest = destination(inst, address);
|
||||||
|
|
||||||
|
// One-operand notation
|
||||||
|
if (bcondCombine)
|
||||||
|
return dest;
|
||||||
|
|
||||||
|
// Two-operand notation
|
||||||
|
String cond = bcondNames ?
|
||||||
|
CONDITIONS[inst.cond] : Integer.toString(inst.cond);
|
||||||
|
if (bcondNames && !condCaps)
|
||||||
|
cond = cond.toLowerCase();
|
||||||
|
return String.format("%s, %s", cond, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operands for Format V
|
||||||
|
private static String formatV(Instruction inst) {
|
||||||
|
String reg1 = program(inst.reg1);
|
||||||
|
String reg2 = program(inst.reg2);
|
||||||
|
String imm = toHex(
|
||||||
|
inst.id == VUE.MOVEA ? inst.imm & 0xFFFF : inst.imm,
|
||||||
|
inst.id == VUE.ADDI ? 1 : 4,
|
||||||
|
immNumber
|
||||||
|
);
|
||||||
|
return String.format("%s, %s, %s",
|
||||||
|
destLast ? imm : reg2,
|
||||||
|
reg1,
|
||||||
|
destLast ? reg2 : imm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operands for Format VI
|
||||||
|
private static String formatVI(Instruction inst) {
|
||||||
|
String src = program(inst.reg1);
|
||||||
|
String dest = program(inst.reg2);
|
||||||
|
|
||||||
|
// Data operand
|
||||||
|
src = inst.disp == 0 ? String.format("[%s]", src) :
|
||||||
|
dispInside ? String.format(
|
||||||
|
"[%s %s %s]",
|
||||||
|
src,
|
||||||
|
inst.disp < 0 ? "-" : "+",
|
||||||
|
toHex(Math.abs(inst.disp), 1, immNumber)
|
||||||
|
) : String.format(
|
||||||
|
"%s[%s]",
|
||||||
|
toHex(inst.disp, 1, immNumber),
|
||||||
|
src
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
// Write instruction
|
||||||
|
switch (inst.id) {
|
||||||
|
case VUE.OUT_B: // Fallthrough
|
||||||
|
case VUE.OUT_H: // Fallthrough
|
||||||
|
case VUE.OUT_W: // Fallthrough
|
||||||
|
case VUE.ST_B : // Fallthrough
|
||||||
|
case VUE.ST_H : // Fallthrough
|
||||||
|
case VUE.ST_W :
|
||||||
|
String temp = src;
|
||||||
|
src = dest;
|
||||||
|
dest = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format operands
|
||||||
|
return String.format("%s, %s",
|
||||||
|
destLast ? src : dest,
|
||||||
|
destLast ? dest : src
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format a program register
|
||||||
|
private static String program(int index) {
|
||||||
|
String ret = programNames ? PROGRAMS[index] : null;
|
||||||
|
if (ret == null)
|
||||||
|
ret = "r" + index;
|
||||||
|
return programCaps ? ret.toUpperCase() : ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represent an immediate value as hexadecimal
|
||||||
|
private static String toHex(int value, int digits, boolean number) {
|
||||||
|
return String.format(
|
||||||
|
"%s%s%s%0" + digits + (hexCaps ? "X" : "x") + "%s",
|
||||||
|
number ? "#" : "",
|
||||||
|
value < 0 ? "-" : "",
|
||||||
|
hexMode == DOLLAR ? "$" : hexMode == ZEROX ? "0x" : "",
|
||||||
|
value < 0 ? -value : value,
|
||||||
|
hexMode == H ? "h" : ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,12 +28,12 @@ class MainWindow extends JFrame {
|
||||||
|
|
||||||
// UI components
|
// UI components
|
||||||
private JPanel client; // Common client container
|
private JPanel client; // Common client container
|
||||||
private Console console; // Console window
|
private ConsoleWindow console; // Console window
|
||||||
private CPU cpu; // CPU window
|
private CPUWindow cpu; // CPU window
|
||||||
private JDesktopPane desktop; // Container for child windows
|
private JDesktopPane desktop; // Container for child windows
|
||||||
private Memory memory; // Memory window
|
private MemoryWindow memory; // Memory window
|
||||||
private JPanel video; // Video output
|
|
||||||
private JMenu mnuDebug; // Debug menu
|
private JMenu mnuDebug; // Debug menu
|
||||||
|
private JPanel video; // Video output
|
||||||
private JMenuItem mnuFileDebugMode; // File -> Debug mode
|
private JMenuItem mnuFileDebugMode; // File -> Debug mode
|
||||||
private JMenuItem mnuFileGameMode; // File -> Game mode
|
private JMenuItem mnuFileGameMode; // File -> Game mode
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ class MainWindow extends JFrame {
|
||||||
// Configure child windows
|
// Configure child windows
|
||||||
desktop = new JDesktopPane();
|
desktop = new JDesktopPane();
|
||||||
desktop.setBackground(SystemColor.controlShadow);
|
desktop.setBackground(SystemColor.controlShadow);
|
||||||
desktop.add(console = new Console(this));
|
desktop.add(console = new ConsoleWindow(this));
|
||||||
desktop.add(cpu = new CPU (this));
|
desktop.add(cpu = new CPUWindow (this));
|
||||||
desktop.add(memory = new Memory (this));
|
desktop.add(memory = new MemoryWindow (this));
|
||||||
|
|
||||||
// Display window
|
// Display window
|
||||||
refreshDebug();
|
refreshDebug();
|
||||||
|
@ -207,6 +207,7 @@ class MainWindow extends JFrame {
|
||||||
// Window close, File -> Exit
|
// Window close, File -> Exit
|
||||||
private void onClose() {
|
private void onClose() {
|
||||||
app.removeWindow(this);
|
app.removeWindow(this);
|
||||||
|
cpu.dispose();
|
||||||
dispose();
|
dispose();
|
||||||
vue.dispose();
|
vue.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import javax.swing.*;
|
||||||
import util.*;
|
import util.*;
|
||||||
|
|
||||||
// Memory viewer and hex editor window
|
// Memory viewer and hex editor window
|
||||||
class Memory extends ChildWindow {
|
class MemoryWindow extends ChildWindow {
|
||||||
|
|
||||||
// Private fields
|
// Private fields
|
||||||
private int address; // Address of top row
|
private int address; // Address of top row
|
||||||
|
@ -41,7 +41,7 @@ class Memory extends ChildWindow {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Default constructor
|
// Default constructor
|
||||||
Memory(MainWindow parent) {
|
MemoryWindow(MainWindow parent) {
|
||||||
super(parent, "memory.title");
|
super(parent, "memory.title");
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
|
@ -14,26 +14,22 @@ import vue.*;
|
||||||
class Register {
|
class Register {
|
||||||
|
|
||||||
// Instance fields
|
// Instance fields
|
||||||
boolean expandable; // The expansion area can be shown
|
private boolean expandable; // The expansion area can be shown
|
||||||
boolean expanded; // The expanded area is being shown
|
private boolean expanded; // The expanded area is being shown
|
||||||
Font font; // Hexadecimal font
|
private int index; // Register index
|
||||||
int index; // Register index
|
private int mode; // Display mode for program registers
|
||||||
int mode; // Display mode for program registers
|
private String name; // Register name
|
||||||
MainWindow parent; // Containing window
|
private RegisterList parent; // Containing register list
|
||||||
int type; // Expansion controls type
|
private int type; // Expansion controls type
|
||||||
int value; // Current register value
|
private int value; // Current register value
|
||||||
|
|
||||||
// UI components
|
// UI components
|
||||||
private JPanel expansion; // Expansion area
|
JPanel expansion; // Expansion container
|
||||||
private JLabel btnExpand; // Expand button
|
JLabel btnExpand; // Expand button
|
||||||
private JLabel lblLastPC; // Last PC name
|
JPanel indent; // Expansion area indentation
|
||||||
private JLabel lblName; // Register name
|
JLabel lblName; // Register name
|
||||||
private JPanel list; // Containing element
|
JTextField txtValue; // Register value
|
||||||
private JPanel spacer; // Expansion area spacer
|
ArrayList<JComponent> controls; // Expansion controls
|
||||||
private JTextField txtJumpFrom; // Jump-from value
|
|
||||||
private JTextField txtJumpTo; // Jump-to value
|
|
||||||
private JTextField txtValue; // Register value
|
|
||||||
private ArrayList<JComponent> controls; // Expansion controls
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,8 +44,8 @@ class Register {
|
||||||
static final int UNSIGNED = 2;
|
static final int UNSIGNED = 2;
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
static final int PLAIN = -1;
|
static final int PLAIN = -2;
|
||||||
static final int PROGRAM = -2;
|
static final int PROGRAM = -3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,14 +54,15 @@ class Register {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Default constructor
|
// Default constructor
|
||||||
Register(MainWindow parent, JPanel list, String name, int index, int type){
|
Register(RegisterList parent, String name, int index, int type) {
|
||||||
|
parent.add(index, this);
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
controls = new ArrayList<JComponent>();
|
controls = new ArrayList<JComponent>();
|
||||||
expandable = type != PLAIN && index != 0 || index == VUE.PC;
|
expandable = type != PLAIN && index != 0;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.list = list;
|
mode = HEX;
|
||||||
this.mode = HEX;
|
this.name = name;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
|
@ -81,17 +78,17 @@ class Register {
|
||||||
var gbc = new GridBagConstraints();
|
var gbc = new GridBagConstraints();
|
||||||
gbc.anchor = GridBagConstraints.NORTH;
|
gbc.anchor = GridBagConstraints.NORTH;
|
||||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
list.add(btnExpand, gbc);
|
parent.add(gbc, btnExpand);
|
||||||
|
|
||||||
// Name label
|
// Name label
|
||||||
lblName = new JLabel(name);
|
lblName = new JLabel(" ");
|
||||||
if (expandable)
|
if (expandable)
|
||||||
lblName.addMouseListener(expand);
|
lblName.addMouseListener(expand);
|
||||||
gbc = new GridBagConstraints();
|
gbc = new GridBagConstraints();
|
||||||
gbc.anchor = GridBagConstraints.NORTH;
|
gbc.anchor = GridBagConstraints.NORTH;
|
||||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
gbc.weightx = 1;
|
gbc.weightx = 1;
|
||||||
list.add(lblName, gbc);
|
parent.add(gbc, lblName);
|
||||||
|
|
||||||
// Value text box
|
// Value text box
|
||||||
txtValue = new JTextField();
|
txtValue = new JTextField();
|
||||||
|
@ -101,7 +98,7 @@ class Register {
|
||||||
gbc = new GridBagConstraints();
|
gbc = new GridBagConstraints();
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
gbc.insets = new Insets(0, 4, 0, 0);
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
list.add(txtValue, gbc);
|
parent.add(gbc, txtValue);
|
||||||
|
|
||||||
// Value changed
|
// Value changed
|
||||||
txtValue.addActionListener(e->{
|
txtValue.addActionListener(e->{
|
||||||
|
@ -129,14 +126,14 @@ class Register {
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion spacer
|
// Expansion indentation
|
||||||
if (index != VUE.PC) {
|
if (index != VUE.PC) {
|
||||||
spacer = new JPanel(null);
|
indent = new JPanel(null);
|
||||||
spacer.setOpaque(false);
|
indent.setOpaque(false);
|
||||||
spacer.setPreferredSize(new Dimension(0, 0));
|
indent.setPreferredSize(new Dimension(0, 0));
|
||||||
spacer.setVisible(false);
|
indent.setVisible(false);
|
||||||
gbc = new GridBagConstraints();
|
gbc = new GridBagConstraints();
|
||||||
list.add(spacer, gbc);
|
parent.add(gbc, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion area
|
// Expansion area
|
||||||
|
@ -149,7 +146,11 @@ class Register {
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
gbc.insets = new Insets(0, 4, 0, 0);
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
gbc.weightx = 1;
|
gbc.weightx = 1;
|
||||||
list.add(expansion, gbc);
|
parent.add(gbc, expansion);
|
||||||
|
|
||||||
|
// Handling for PSW
|
||||||
|
if (index == VUE.PSW && type == VUE.PSW)
|
||||||
|
setExpanded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,14 +162,14 @@ class Register {
|
||||||
// Expansion controls for CHCW
|
// Expansion controls for CHCW
|
||||||
private void initCHCW() {
|
private void initCHCW() {
|
||||||
expansion = new JPanel(new GridBagLayout());
|
expansion = new JPanel(new GridBagLayout());
|
||||||
addCheckBox("ICE", 1, false); endRow();
|
addCheckBox("ICE", 1, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion controls for ECR
|
// Expansion controls for ECR
|
||||||
private void initECR() {
|
private void initECR() {
|
||||||
expansion = new JPanel(new GridBagLayout());
|
expansion = new JPanel(new GridBagLayout());
|
||||||
addTextBox("EICC", 0, 16, false, true); endRow();
|
addTextBox("EICC", 0, 16, false, true);
|
||||||
addTextBox("FECC", 16, 16, false, true); endRow();
|
addTextBox("FECC", 16, 16, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion controls for program registers
|
// Expansion controls for program registers
|
||||||
|
@ -189,38 +190,37 @@ class Register {
|
||||||
for (int x = 0; x < 2; x++) {
|
for (int x = 0; x < 2; x++) {
|
||||||
|
|
||||||
// Indentation
|
// Indentation
|
||||||
var spacer = new JPanel(null);
|
indent = new JPanel(null);
|
||||||
spacer.setOpaque(false);
|
indent.setOpaque(false);
|
||||||
spacer.setPreferredSize(new Dimension(0, 0));
|
indent.setPreferredSize(new Dimension(0, 0));
|
||||||
var gbc = new GridBagConstraints();
|
var gbc = new GridBagConstraints();
|
||||||
gbc.weightx = 1;
|
gbc.weightx = 1;
|
||||||
expansion.add(spacer, gbc);
|
expansion.add(indent, gbc);
|
||||||
|
|
||||||
// Name label
|
// Name label
|
||||||
var label = new JLabel();
|
var label = new JLabel();
|
||||||
parent.app.localizer.add(label,
|
parent.parent.parent.app.localizer.add(label,
|
||||||
x == 0 ? "cpu.jump_from" : "cpu.jump_to" );
|
x == 0 ? "cpu.jump_from" : "cpu.jump_to" );
|
||||||
gbc = new GridBagConstraints();
|
gbc = new GridBagConstraints();
|
||||||
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
expansion.add(label, gbc);
|
expansion.add(label, gbc);
|
||||||
|
controls.add(label);
|
||||||
|
|
||||||
// Value text box
|
// Value text box
|
||||||
var txt = new JTextField();
|
var txt = new JTextField();
|
||||||
txt.addActionListener(e->{
|
txt.addActionListener(e->{
|
||||||
txt.setText((String) txt.getClientProperty("text"));
|
txt.setText((String) txt.getClientProperty("text"));
|
||||||
list.requestFocus();
|
parent.requestFocus();
|
||||||
});
|
});
|
||||||
|
txt.putClientProperty("index",
|
||||||
|
x == 0 ? VUE.JUMP_FROM : VUE.JUMP_TO);
|
||||||
txt.setBorder(null);
|
txt.setBorder(null);
|
||||||
txt.setOpaque(false);
|
txt.setOpaque(false);
|
||||||
gbc = new GridBagConstraints();
|
gbc = new GridBagConstraints();
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
gbc.insets = new Insets(0, 4, 0, 0);
|
gbc.insets = new Insets(0, 4, 0, 0);
|
||||||
expansion.add(txt, gbc);
|
expansion.add(txt, gbc);
|
||||||
|
controls.add(txt);
|
||||||
// Initialize the corresponding component field
|
|
||||||
if (x == 0)
|
|
||||||
txtJumpFrom = txt;
|
|
||||||
else txtJumpTo = txt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -228,40 +228,40 @@ class Register {
|
||||||
// Expansion controls for PSW
|
// Expansion controls for PSW
|
||||||
private void initPSW() {
|
private void initPSW() {
|
||||||
expansion = new JPanel(new GridBagLayout());
|
expansion = new JPanel(new GridBagLayout());
|
||||||
addCheckBox("Z" , 0, false);
|
addCheckBox("Z" , 0, false, false);
|
||||||
addCheckBox("FRO", 9, false); endRow();
|
addCheckBox("FRO", 9, false, true );
|
||||||
addCheckBox("S" , 1, false);
|
addCheckBox("S" , 1, false, false);
|
||||||
addCheckBox("FIV", 8, false); endRow();
|
addCheckBox("FIV", 8, false, true );
|
||||||
addCheckBox("OV" , 2, false);
|
addCheckBox("OV" , 2, false, false);
|
||||||
addCheckBox("FZD", 7, false); endRow();
|
addCheckBox("FZD", 7, false, true );
|
||||||
addCheckBox("CY" , 3, false);
|
addCheckBox("CY" , 3, false, false);
|
||||||
addCheckBox("FOV", 6, false); endRow();
|
addCheckBox("FOV", 6, false, true );
|
||||||
addCheckBox("EP" , 14, false);
|
addCheckBox("EP" , 14, false, false);
|
||||||
addCheckBox("FUD", 5, false); endRow();
|
addCheckBox("FUD", 5, false, true );
|
||||||
addCheckBox("NP" , 15, false);
|
addCheckBox("NP" , 15, false, false);
|
||||||
addCheckBox("FPR", 4, false); endRow();
|
addCheckBox("FPR", 4, false, true );
|
||||||
addCheckBox("AE" , 13, false); endRow();
|
addCheckBox("AE" , 13, false, true );
|
||||||
addCheckBox("ID" , 12, false);
|
addCheckBox("ID" , 12, false, false);
|
||||||
addTextBox ("I" , 16, 4, false, false); endRow();
|
addTextBox ("I" , 16, 4, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion controls for PIR
|
// Expansion controls for PIR
|
||||||
private void initPIR() {
|
private void initPIR() {
|
||||||
expansion = new JPanel(new GridBagLayout());
|
expansion = new JPanel(new GridBagLayout());
|
||||||
addTextBox("PT", 0, 16, true, true); endRow();
|
addTextBox("PT", 0, 16, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion controls for TKCW
|
// Expansion controls for TKCW
|
||||||
private void initTKCW() {
|
private void initTKCW() {
|
||||||
expansion = new JPanel(new GridBagLayout());
|
expansion = new JPanel(new GridBagLayout());
|
||||||
addCheckBox("OTM", 8, true);
|
addCheckBox("OTM", 8, true, false);
|
||||||
addCheckBox("FVT", 5, true); endRow();
|
addCheckBox("FVT", 5, true, true );
|
||||||
addCheckBox("FIT", 7, true);
|
addCheckBox("FIT", 7, true, false);
|
||||||
addCheckBox("FUT", 4, true); endRow();
|
addCheckBox("FUT", 4, true, true );
|
||||||
addCheckBox("FZT", 6, true);
|
addCheckBox("FZT", 6, true, false);
|
||||||
addCheckBox("FPT", 3, true); endRow();
|
addCheckBox("FPT", 3, true, true );
|
||||||
addCheckBox("RDI", 2, true);
|
addCheckBox("RDI", 2, true, false);
|
||||||
addTextBox ("RD", 0, 2, true, false); endRow();
|
addTextBox ("RD", 0, 2, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,11 +270,61 @@ class Register {
|
||||||
// Package Methods //
|
// Package Methods //
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Refresh controls
|
// Apply configuration settings
|
||||||
void refresh() {
|
void configure() {
|
||||||
|
String name = null;
|
||||||
|
|
||||||
|
// System register
|
||||||
|
if (type != PROGRAM) {
|
||||||
|
name = this.name;
|
||||||
|
if (!Disassembler.systemCaps)
|
||||||
|
name = name.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Program register
|
||||||
|
else {
|
||||||
|
if (Disassembler.programNames)
|
||||||
|
name = this.name;
|
||||||
|
if (name == null)
|
||||||
|
name = "r" + index;
|
||||||
|
if (Disassembler.programCaps)
|
||||||
|
name = name.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name label
|
||||||
|
lblName.setText(name);
|
||||||
|
|
||||||
|
// Expand button
|
||||||
|
var size = btnExpand.getPreferredSize();
|
||||||
|
size.width = CPUWindow.regExpandWidth;
|
||||||
|
btnExpand.setPreferredSize(size);
|
||||||
|
|
||||||
// Value text box
|
// Value text box
|
||||||
value = parent.vue.getRegister(index, type != PROGRAM);
|
var fontSize = CPUWindow.regHexFontSize;
|
||||||
|
size = new Dimension(8 * fontSize.width + 4, fontSize.height);
|
||||||
|
txtValue.setFont(CPUWindow.regHexFont);
|
||||||
|
txtValue.setPreferredSize(size);
|
||||||
|
|
||||||
|
// Expansion controls
|
||||||
|
for (var ctrl : controls) {
|
||||||
|
if (!(ctrl instanceof JTextField))
|
||||||
|
continue;
|
||||||
|
if (type == VUE.PC || (Boolean) ctrl.getClientProperty("hex"))
|
||||||
|
((JTextField) ctrl).setFont(CPUWindow.regHexFont);
|
||||||
|
int digits = type == VUE.PC ? 8 :
|
||||||
|
(Integer) ctrl.getClientProperty("digits");
|
||||||
|
size = ctrl.getPreferredSize();
|
||||||
|
size.width = digits * fontSize.width + 4;
|
||||||
|
ctrl.setPreferredSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh controls
|
||||||
|
void refresh() {
|
||||||
|
var vue = parent.parent.parent.vue;
|
||||||
|
|
||||||
|
// Value text box
|
||||||
|
value = vue.getRegister(index, type != PROGRAM);
|
||||||
txtValue.setText(
|
txtValue.setText(
|
||||||
type != PROGRAM || mode == HEX ?
|
type != PROGRAM || mode == HEX ?
|
||||||
String.format("%08X", value) :
|
String.format("%08X", value) :
|
||||||
|
@ -283,18 +333,8 @@ class Register {
|
||||||
Float.toString(Float.intBitsToFloat(value))
|
Float.toString(Float.intBitsToFloat(value))
|
||||||
);
|
);
|
||||||
|
|
||||||
// PC expansion controls
|
// Expansion controls
|
||||||
if (index == VUE.PC) for (int x = 0; x < 2; x++) {
|
for (var control : controls) {
|
||||||
JTextField txt = x == 0 ? txtJumpFrom : txtJumpTo;
|
|
||||||
int index = x == 0 ? VUE.JUMP_FROM : VUE.JUMP_TO;
|
|
||||||
int value = parent.vue.getRegister(index, true);
|
|
||||||
String text = String.format("%08X", value);
|
|
||||||
txt.putClientProperty("text", text);
|
|
||||||
txt.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other expansion controls
|
|
||||||
else for (var control : controls) {
|
|
||||||
|
|
||||||
// Check box
|
// Check box
|
||||||
if (control instanceof JCheckBox) {
|
if (control instanceof JCheckBox) {
|
||||||
|
@ -306,13 +346,32 @@ class Register {
|
||||||
// Text box
|
// Text box
|
||||||
if (control instanceof JTextField) {
|
if (control instanceof JTextField) {
|
||||||
var ctrl = (JTextField) control;
|
var ctrl = (JTextField) control;
|
||||||
|
int digits; // Maximum digits that can be displayed
|
||||||
|
boolean hex; // The value is hexadecimal
|
||||||
|
int val; // The value to be displayed
|
||||||
|
|
||||||
|
// Jump history
|
||||||
|
if (type == VUE.PC) {
|
||||||
|
digits = 8;
|
||||||
|
hex = true;
|
||||||
|
val = vue.getRegister((Integer)
|
||||||
|
ctrl.getClientProperty("index"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other values
|
||||||
|
else {
|
||||||
int bit = (Integer) ctrl.getClientProperty("bit" );
|
int bit = (Integer) ctrl.getClientProperty("bit" );
|
||||||
int digits = (Integer) ctrl.getClientProperty("digits");
|
digits = (Integer) ctrl.getClientProperty("digits");
|
||||||
boolean hex = (Boolean) ctrl.getClientProperty("hex");
|
hex = (Boolean) ctrl.getClientProperty("hex");
|
||||||
int width = (Integer) ctrl.getClientProperty("width");
|
int width = (Integer) ctrl.getClientProperty("width");
|
||||||
int val = value >> bit & (1 << width) - 1;
|
val = value >> bit & (1 << width) - 1;
|
||||||
ctrl.setText(!hex ? Integer.toString(val) :
|
}
|
||||||
String.format("%0" + digits + "X", val));
|
|
||||||
|
// Update the text
|
||||||
|
String text = !hex ? Integer.toString(val) : String.format(
|
||||||
|
"%0" + digits + (Disassembler.hexCaps ? "X" : "x"), val);
|
||||||
|
ctrl.putClientProperty("text", text);
|
||||||
|
ctrl.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -329,52 +388,16 @@ class Register {
|
||||||
// Update controls
|
// Update controls
|
||||||
this.expanded = expanded;
|
this.expanded = expanded;
|
||||||
btnExpand.setText(expanded ? "-" : "+");
|
btnExpand.setText(expanded ? "-" : "+");
|
||||||
if (index != VUE.PC)
|
if (type != VUE.PC)
|
||||||
spacer.setVisible(expanded);
|
indent.setVisible(expanded);
|
||||||
expansion.setVisible(expanded);
|
expansion.setVisible(expanded);
|
||||||
list.revalidate();
|
parent.revalidate();
|
||||||
}
|
|
||||||
|
|
||||||
// Specify the width of the expand button
|
|
||||||
void setExpandWidth(int width) {
|
|
||||||
var size = btnExpand.getPreferredSize();
|
|
||||||
size.width = width;
|
|
||||||
btnExpand.setPreferredSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specify a new font
|
|
||||||
void setFont(Font font, int fontWidth, int fontHeight) {
|
|
||||||
this.font = font;
|
|
||||||
|
|
||||||
// Value text box
|
|
||||||
var size = new Dimension(8 * fontWidth + 4, fontHeight);
|
|
||||||
txtValue.setFont(font);
|
|
||||||
txtValue.setPreferredSize(size);
|
|
||||||
if (index == VUE.PC) {
|
|
||||||
txtJumpFrom.setFont(font);
|
|
||||||
txtJumpFrom.setPreferredSize(size);
|
|
||||||
txtJumpTo .setFont(font);
|
|
||||||
txtJumpTo .setPreferredSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expansion controls
|
|
||||||
for (var ctrl : controls) {
|
|
||||||
if (!(ctrl instanceof JTextField))
|
|
||||||
continue;
|
|
||||||
if ((Boolean) ctrl.getClientProperty("hex"))
|
|
||||||
((JTextField) ctrl).setFont(font);
|
|
||||||
int digits = (Integer) ctrl.getClientProperty("digits");
|
|
||||||
size = ctrl.getPreferredSize();
|
|
||||||
size.width = digits * fontWidth + 4;
|
|
||||||
ctrl.setPreferredSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the display mode of a program register
|
// Change the display mode of a program register
|
||||||
void setMode(int mode) {
|
void setMode(int mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
txtValue.setFont(mode == HEX ? font : null);
|
txtValue.setFont(mode == HEX ? CPUWindow.regHexFont : null);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +408,8 @@ class Register {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Add a check box to the expansion area
|
// Add a check box to the expansion area
|
||||||
private void addCheckBox(String name, int bit, boolean readOnly) {
|
private void addCheckBox(String name, int bit, boolean readOnly,
|
||||||
|
boolean last) {
|
||||||
int mask = 1 << bit;
|
int mask = 1 << bit;
|
||||||
|
|
||||||
// Configure control
|
// Configure control
|
||||||
|
@ -406,7 +430,7 @@ class Register {
|
||||||
// Configure expansion area
|
// Configure expansion area
|
||||||
var gbc = new GridBagConstraints();
|
var gbc = new GridBagConstraints();
|
||||||
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
gbc.gridwidth = 2;
|
gbc.gridwidth = last ? GridBagConstraints.REMAINDER : 2;
|
||||||
gbc.insets = new Insets(0, 4, 0, 4);
|
gbc.insets = new Insets(0, 4, 0, 4);
|
||||||
expansion.add(ctrl, gbc);
|
expansion.add(ctrl, gbc);
|
||||||
}
|
}
|
||||||
|
@ -416,7 +440,7 @@ class Register {
|
||||||
|
|
||||||
// Configure control
|
// Configure control
|
||||||
var ctrl = new JRadioButton();
|
var ctrl = new JRadioButton();
|
||||||
parent.app.localizer.add(ctrl, key);
|
parent.parent.parent.app.localizer.add(ctrl, key);
|
||||||
ctrl.setBorder(null);
|
ctrl.setBorder(null);
|
||||||
ctrl.setFocusable(false);
|
ctrl.setFocusable(false);
|
||||||
ctrl.setOpaque(false);
|
ctrl.setOpaque(false);
|
||||||
|
@ -469,23 +493,16 @@ class Register {
|
||||||
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
||||||
gbc.insets = new Insets(0, 4, 0, 4);
|
gbc.insets = new Insets(0, 4, 0, 4);
|
||||||
expansion.add(label, gbc);
|
expansion.add(label, gbc);
|
||||||
expansion.add(ctrl , gbc);
|
gbc = new GridBagConstraints();
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate a row of expansion controls
|
|
||||||
private void endRow() {
|
|
||||||
var spacer = new JPanel(null);
|
|
||||||
spacer.setOpaque(false);
|
|
||||||
spacer.setPreferredSize(new Dimension(0, 0));
|
|
||||||
var gbc = new GridBagConstraints();
|
|
||||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
expansion.add(spacer, gbc);
|
gbc.insets = new Insets(0, 4, 0, 4);
|
||||||
|
expansion.add(ctrl , gbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the register value
|
// Update the register value
|
||||||
private void setValue(int value) {
|
private void setValue(int value) {
|
||||||
list.requestFocus();
|
parent.requestFocus();
|
||||||
parent.vue.setRegister(index, type != PROGRAM, value);
|
parent.parent.parent.vue.setRegister(index, type != PROGRAM, value);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
package app;
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
// Project imports
|
||||||
|
import vue.*;
|
||||||
|
|
||||||
|
// List of CPU registers
|
||||||
|
class RegisterList extends JScrollPane {
|
||||||
|
|
||||||
|
// Package fields
|
||||||
|
CPUWindow parent; // Containing CPU window
|
||||||
|
|
||||||
|
// Private fields
|
||||||
|
private boolean shown; // Component has been shown
|
||||||
|
private HashMap<Integer, Register> registers; // Register items
|
||||||
|
|
||||||
|
// UI components
|
||||||
|
private JPanel client; // Client area
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructors //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Default constructor
|
||||||
|
RegisterList(CPUWindow parent, boolean system) {
|
||||||
|
super(VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
|
||||||
|
// Configure instance fields
|
||||||
|
this.parent = parent;
|
||||||
|
registers = new HashMap<Integer, Register>();
|
||||||
|
shown = true;
|
||||||
|
|
||||||
|
// Configure client area
|
||||||
|
client = new JPanel(new GridBagLayout()) {
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
var ret = super.getPreferredSize();
|
||||||
|
if (!shown) ret.height = system ? getInitialHeight() : 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
shown = true;
|
||||||
|
super.paintComponent(g);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
client.setBackground(SystemColor.window);
|
||||||
|
client.setFocusable(true);
|
||||||
|
|
||||||
|
// Initialize system registers
|
||||||
|
if (system) {
|
||||||
|
new Register(this, "PC" , VUE.PC , VUE.PC );
|
||||||
|
new Register(this, "PSW" , VUE.PSW , VUE.PSW );
|
||||||
|
new Register(this, "EIPC" , VUE.EIPC , Register.PLAIN);
|
||||||
|
new Register(this, "EIPSW", VUE.EIPSW, VUE.PSW );
|
||||||
|
new Register(this, "FEPC" , VUE.FEPC , Register.PLAIN);
|
||||||
|
new Register(this, "FEPSW", VUE.FEPSW, VUE.PSW );
|
||||||
|
new Register(this, "ECR" , VUE.ECR , VUE.ECR );
|
||||||
|
new Register(this, "ADTRE", VUE.ADTRE, Register.PLAIN);
|
||||||
|
new Register(this, "CHCW" , VUE.CHCW , VUE.CHCW );
|
||||||
|
new Register(this, "PIR" , VUE.PIR , VUE.PIR );
|
||||||
|
new Register(this, "TKCW" , VUE.TKCW , VUE.TKCW );
|
||||||
|
new Register(this, "29" , 29, Register.PLAIN);
|
||||||
|
new Register(this, "30" , 30, Register.PLAIN);
|
||||||
|
new Register(this, "31" , 31, Register.PLAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize program registers
|
||||||
|
else for (int x = 0; x < 32; x++) {
|
||||||
|
String name = null;
|
||||||
|
switch (x) {
|
||||||
|
case VUE.GP: name = "gp"; break;
|
||||||
|
case VUE.HP: name = "hp"; break;
|
||||||
|
case VUE.LP: name = "lp"; break;
|
||||||
|
case VUE.SP: name = "sp"; break;
|
||||||
|
case VUE.TP: name = "tp"; break;
|
||||||
|
}
|
||||||
|
new Register(this, name, x, Register.PROGRAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// List terminator
|
||||||
|
var spacer = new JPanel(null);
|
||||||
|
spacer.setOpaque(false);
|
||||||
|
spacer.setPreferredSize(new Dimension(0, 0));
|
||||||
|
var gbc = new GridBagConstraints();
|
||||||
|
gbc.gridheight = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
gbc.weighty = 1;
|
||||||
|
client.add(spacer, gbc);
|
||||||
|
|
||||||
|
// Configure component
|
||||||
|
shown = false;
|
||||||
|
setViewportView(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Draw the component
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
if (!shown) {
|
||||||
|
shown = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
super.paintComponent(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer focus to the client area
|
||||||
|
public void requestFocus() {
|
||||||
|
client.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate layout
|
||||||
|
public void revalidate() {
|
||||||
|
if (client != null)
|
||||||
|
client.revalidate();
|
||||||
|
super.revalidate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Package Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Add a register component to the client area
|
||||||
|
void add(GridBagConstraints gbc, JComponent comp) {
|
||||||
|
client.add(comp, gbc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Associate a register with its index
|
||||||
|
void add(int index, Register register) {
|
||||||
|
registers.put(index, register);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply configuration settings
|
||||||
|
void configure() {
|
||||||
|
|
||||||
|
// Configure registers
|
||||||
|
for (var reg : registers.values())
|
||||||
|
reg.configure();
|
||||||
|
|
||||||
|
// Configure component
|
||||||
|
getVerticalScrollBar().setUnitIncrement(
|
||||||
|
CPUWindow.regHexFontSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the display
|
||||||
|
void refresh() {
|
||||||
|
for (var reg : registers.values())
|
||||||
|
reg.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private Methods //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Determine the initial height upon first show
|
||||||
|
private int getInitialHeight() {
|
||||||
|
int height = 0;
|
||||||
|
var layout = (GridBagLayout) client.getLayout();
|
||||||
|
int ret = 0;
|
||||||
|
int row = 0;
|
||||||
|
|
||||||
|
// Process controls until the target row is found
|
||||||
|
for (var control : client.getComponents()) {
|
||||||
|
var ctrl = (JComponent) control;
|
||||||
|
|
||||||
|
// Track the tallest control on the row
|
||||||
|
if (ctrl.isVisible())
|
||||||
|
height = Math.max(height, ctrl.getPreferredSize().height);
|
||||||
|
|
||||||
|
// This is not the last control on the row
|
||||||
|
if (layout.getConstraints(control).gridwidth !=
|
||||||
|
GridBagConstraints.REMAINDER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Advance to the next row
|
||||||
|
ret += height;
|
||||||
|
height = 0;
|
||||||
|
row++;
|
||||||
|
|
||||||
|
// The target row has been reached
|
||||||
|
if (row == 4)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -104,7 +104,6 @@ public class Instruction {
|
||||||
|
|
||||||
// Decode by format
|
// Decode by format
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case 0: return; // Illegal opcode
|
|
||||||
case 1:
|
case 1:
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
reg1 = bits >> 16 & 31;
|
reg1 = bits >> 16 & 31;
|
||||||
|
|
|
@ -3,6 +3,9 @@ package vue;
|
||||||
// Java emulation core implementation
|
// Java emulation core implementation
|
||||||
class JavaVUE extends VUE {
|
class JavaVUE extends VUE {
|
||||||
|
|
||||||
|
// Instance fields
|
||||||
|
Instruction inst; // Instruction state
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
Bus bus; // Memory bus
|
Bus bus; // Memory bus
|
||||||
CPU cpu; // Processor
|
CPU cpu; // Processor
|
||||||
|
@ -26,6 +29,7 @@ class JavaVUE extends VUE {
|
||||||
JavaVUE() {
|
JavaVUE() {
|
||||||
bus = new Bus(this);
|
bus = new Bus(this);
|
||||||
cpu = new CPU(this);
|
cpu = new CPU(this);
|
||||||
|
inst = new Instruction();
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue