Revisions to CPU register interface

This commit is contained in:
Guy Perfect 2020-08-07 14:21:03 -05:00
parent 7d8d33158f
commit ddbde757ae
16 changed files with 212 additions and 114 deletions

View File

@ -39,12 +39,13 @@ console {
# CPU window
cpu {
float Float
hex Hex
last_pc Last PC
signed Signed
title CPU
unsigned Unsigned
float Float
hex Hex
jump_from From
jump_to To
signed Signed
title CPU
unsigned Unsigned
}
# Memory window

View File

@ -62,9 +62,9 @@ static int32_t busReadValue(VUE *vue, uint32_t address, int type) {
case 5: /* System WRAM */
return busReadMemory(vue->bus.wram, address & 0xFFFF, type);
case 6: return busReadMemory(vue->bus.sram, /* Cartridge RAM */
address & (vue->bus.sram_size - 1), type);
address & (vue->bus.sramSize - 1), type);
case 7: return busReadMemory(vue->bus.rom , /* Cartridge ROM */
address & (vue->bus.rom_size - 1), type);
address & (vue->bus.romSize - 1), type);
}
return 0; /* Unreachable */
}
@ -128,11 +128,11 @@ static void busWriteValue(VUE *vue, uint32_t address, int type, int32_t value){
break;
case 6: /* Cartridge RAM */
busWriteMemory(vue->bus.sram,
address & (vue->bus.sram_size - 1), type, value);
address & (vue->bus.sramSize - 1), type, value);
break;
case 7: /* Cartridge ROM */
busWriteMemory(vue->bus.rom ,
address & (vue->bus.rom_size - 1), type, value);
address & (vue->bus.romSize - 1), type, value);
break;
}
}

View File

@ -142,7 +142,8 @@ static void cpuReset(VUE *vue) {
/* Configure registers */
vue->cpu.ecr_eicc = 0xFFF0;
vue->cpu.lastPC = 0xFFFFFFF0;
vue->cpu.jumpFrom = 0xFFFFFFF0;
vue->cpu.jumpTo = 0xFFFFFFF0;
vue->cpu.pc = 0xFFFFFFF0;
vue->cpu.psw_np = 1;
}

View File

@ -38,11 +38,15 @@ extern "C" {
#define VUE_EIPSW 1
#define VUE_FEPC 2
#define VUE_FEPSW 3
#define VUE_PC -1
#define VUE_PIR 6
#define VUE_PSW 5
#define VUE_TKCW 7
/* Non-standard register indexes */
#define VUE_PC -1
#define VUE_JUMP_FROM -2
#define VUE_JUMP_TO -3
/* Program register indexes */
#define VUE_GP 4
#define VUE_HP 2
@ -65,18 +69,19 @@ typedef struct {
/* Memory bus */
struct {
uint8_t *rom; /* Cartridge ROM */
uint32_t rom_size; /* Number of bytes in cartridge ROM */
uint32_t romSize; /* Number of bytes in cartridge ROM */
uint8_t *sram; /* Cartridge RAM */
uint32_t sram_size; /* Number of bytes in cartridge RAM */
uint32_t sramSize; /* Number of bytes in cartridge RAM */
uint8_t wram[0x10000]; /* System memory */
} bus;
/* CPU state */
struct {
uint32_t cycles; /* Cycles until next stage */
int fetch; /* Fetch unit index */
int32_t lastPC; /* Previous value of PC */
int stage; /* Current processing stage */
uint32_t cycles; /* Cycles until next stage */
int fetch; /* Fetch unit index */
int32_t jumpFrom; /* Source PC of most recent jump */
int32_t jumpTo; /* Destination PC of most recent jump */
int stage; /* Current processing stage */
/* Program registers */
int32_t program[32];

View File

@ -26,8 +26,20 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
/* Retrieve the value of a register */
int32_t vueGetRegister(VUE *vue, int index, vbool system) {
return vue == NULL ? 0 :
index == VUE_PC && system ? vue->cpu.pc :
/* Error checking */
if (vue == NULL)
return 0;
/* Non-indexed registers */
if (system) switch (index) {
case VUE_PC : return vue->cpu.pc;
case VUE_JUMP_FROM: return vue->cpu.jumpFrom;
case VUE_JUMP_TO : return vue->cpu.jumpTo;
}
/* Indexed registers */
return
index < 0 || index > 31 ? 0 :
system ? cpuGetSystemRegister(vue, index) :
vue->cpu.program[index]
@ -66,13 +78,13 @@ vbool vueRead(VUE *vue, uint32_t address, uint8_t *dest, uint32_t length) {
busReadBytes(NULL, dest, address, 0, count);
break;
case 5: busReadBytes(vue->bus.wram, dest, /* System WRAM */
address, 0x10000 , count);
address, 0x10000 , count);
break;
case 6: busReadBytes(vue->bus.sram, dest, /* Cartridge RAM */
address, vue->bus.sram_size, count);
address, vue->bus.sramSize, count);
break;
case 7: busReadBytes(vue->bus.rom , dest, /* Cartridge ROM */
address, vue->bus.rom_size , count);
address, vue->bus.romSize , count);
break;
}
@ -110,8 +122,8 @@ vbool vueSetROM(VUE *vue, uint8_t *rom, uint32_t size) {
) return VUE_FALSE;
/* Accept the new ROM buffer */
vue->bus.rom = rom;
vue->bus.rom_size = size;
vue->bus.rom = rom;
vue->bus.romSize = size;
return VUE_TRUE;
}
@ -137,10 +149,10 @@ vbool vueWrite(VUE *vue, uint32_t address, uint8_t *src, uint32_t length) {
busWriteBytes(vue->bus.wram, src, address, 0x10000, count);
break;
case 6: busWriteBytes(vue->bus.sram, src, /* Cartridge RAM */
address, vue->bus.sram_size, count);
address, vue->bus.sramSize, count);
break;
case 7: busWriteBytes(vue->bus.rom , src, /* Cartridge ROM */
address, vue->bus.rom_size , count);
address, vue->bus.romSize , count);
break;
}

View File

@ -11,11 +11,13 @@ import vue.*;
public class App {
// Instance fields
private Localizer localizer; // UI localization manager
private boolean useNative; // Produce native core contexts
private Localizer.Locale[] locales; // Language translations
private ArrayList<MainWindow> windows; // Application windows
// Configuration fields
Localizer localizer; // UI localization manager
///////////////////////////////////////////////////////////////////////////
@ -47,21 +49,11 @@ public class App {
windowsChanged();
}
// Retrieve the currently active locale
Localizer.Locale getLocale() {
return localizer.getLocale();
}
// Determine whether the native module is in use
boolean getUseNative() {
return useNative;
}
// Retrieve the localization manager
Localizer getLocalizer() {
return localizer;
}
// Retrieve a list of registered locales
Localizer.Locale[] listLocales() {
var ret = new Localizer.Locale[locales.length];
@ -80,11 +72,6 @@ public class App {
windowsChanged();
}
// Specify a new locale
void setLocale(Localizer.Locale locale) {
localizer.setLocale(locale);
}
// Specify whether using the native module
boolean setUseNative(boolean useNative) {
return this.useNative = useNative && VUE.isNativeLoaded();

View File

@ -56,7 +56,7 @@ class CPU extends ChildWindow {
outer.setResizeWeight(1);
client.add(outer);
client.setPreferredSize(new Dimension(640, 480));
client.setPreferredSize(new Dimension(480, 300));
setFont2(font);
pack();
}
@ -102,7 +102,8 @@ class CPU extends ChildWindow {
case VUE.SP: name = "sp"; break;
case VUE.TP: name = "tp"; break;
}
registers.add(new Register(parent,lst,name,x,Register.PROGRAM));
registers.add(new Register(
parent, lst, name, x, Register.PROGRAM));
}
endList(lst);
}
@ -142,7 +143,8 @@ class CPU extends ChildWindow {
system.putClientProperty("shown", true);
// Add the first two system registers and expand PSW
registers.add(new Register(parent, lst, "PC" , VUE.PC , VUE.PC ));
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);
@ -151,18 +153,18 @@ class CPU extends ChildWindow {
shown = false;
// Add the remaining system registers
registers.add(new Register(parent, lst, "EIPC" , VUE.EIPC , VUE.PC ));
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 , VUE.PC ));
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, VUE.PC ));
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, VUE.PC ));
registers.add(new Register(parent, lst, "30" , 30, VUE.PC ));
registers.add(new Register(parent, lst, "31" , 31, VUE.PC ));
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);
}

View File

@ -27,7 +27,7 @@ class ChildWindow extends JInternalFrame {
this.parent = parent;
// Configure component
parent.app.getLocalizer().add(this, key);
parent.app.localizer.add(this, key);
addInternalFrameListener(Util.onClose2(e->setVisible(false)));
setClosable(true);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

View File

@ -87,7 +87,7 @@ class MainWindow extends JFrame {
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setIconImage(APPICON);
setJMenuBar(initMenus());
app.getLocalizer().add(this, "app.title.default");
app.localizer.add(this, "app.title.default");
// Configure child windows
desktop = new JDesktopPane();
@ -112,7 +112,7 @@ class MainWindow extends JFrame {
// Produce the window's menu bar
private JMenuBar initMenus() {
var bar = new JMenuBar();
var loc = app.getLocalizer();
var loc = app.localizer;
bar.add(initMenuFile (loc));
bar.add(initMenuDebug(loc));
return bar;
@ -194,7 +194,7 @@ class MainWindow extends JFrame {
void windowsChanged(int number, boolean only) {
this.number = number;
this.only = only;
app.getLocalizer().put(this, "ctrl.number", "" + number);
app.localizer.put(this, "ctrl.number", "" + number);
updateTitle();
}
@ -239,7 +239,7 @@ class MainWindow extends JFrame {
// File -> Load ROM
private void onLoadROM() {
var loc = app.getLocalizer();
var loc = app.localizer;
// Prompt the user to select a file
var dlgFile = new JFileChooser(pwd);
@ -324,7 +324,7 @@ class MainWindow extends JFrame {
// Update the window title
private void updateTitle() {
app.getLocalizer().add(this,
app.localizer.add(this,
only ? romFile != null ?
"app.title.rom" :
"app.title.default"

View File

@ -57,7 +57,7 @@ class Memory extends ChildWindow {
client.addMouseWheelListener(e->onWheel(e));
client.setBackground(SystemColor.window);
client.setFocusable(true);
client.setPreferredSize(new Dimension(640, 480));
client.setPreferredSize(new Dimension(480, 360));
// Configure component
var content = new JPanel(new BorderLayout());

View File

@ -14,21 +14,25 @@ import vue.*;
class Register {
// Instance fields
boolean expanded; // The expanded area is being shown
Font font; // Hexadecimal font
int index; // Register index
int mode; // Display mode for program registers
MainWindow parent; // Containing window
int type; // Expansion controls type
int value; // Current register value
boolean expandable; // The expansion area can be shown
boolean expanded; // The expanded area is being shown
Font font; // Hexadecimal font
int index; // Register index
int mode; // Display mode for program registers
MainWindow parent; // Containing window
int type; // Expansion controls type
int value; // Current register value
// UI components
private JPanel expansion; // Expansion area
private JLabel btnExpand; // Expand button
private JLabel lblName; // Register name
private JPanel list; // Containing element
private JPanel spacer; // Expansion area spacer
private JTextField txtValue; // Register value
private JPanel expansion; // Expansion area
private JLabel btnExpand; // Expand button
private JLabel lblLastPC; // Last PC name
private JLabel lblName; // Register name
private JPanel list; // Containing element
private JPanel spacer; // Expansion area spacer
private JTextField txtJumpFrom; // Jump-from value
private JTextField txtJumpTo; // Jump-to value
private JTextField txtValue; // Register value
private ArrayList<JComponent> controls; // Expansion controls
@ -44,6 +48,7 @@ class Register {
static final int UNSIGNED = 2;
// Types
static final int PLAIN = -1;
static final int PROGRAM = -2;
@ -57,6 +62,7 @@ class Register {
// Configure instance fields
controls = new ArrayList<JComponent>();
expandable = type != PLAIN && index != 0 || index == VUE.PC;
this.index = index;
this.list = list;
this.mode = HEX;
@ -64,13 +70,13 @@ class Register {
this.type = type;
// Click handler for expand and name controls
MouseListener expand = type == VUE.PC ? null : Util.onMouse(
e->{ if (e.getButton() == 1) setExpanded(!expanded); }, null);
MouseListener expand = !expandable ? null : Util.onMouse(e->{
if (e.getButton() == 1) setExpanded(!expanded); }, null);
// Expand button
btnExpand = new JLabel(expand != null ? "+" : " ");
btnExpand = new JLabel(expandable ? "+" : " ");
btnExpand.setHorizontalAlignment(SwingConstants.CENTER);
if (expand != null)
if (expandable)
btnExpand.addMouseListener(expand);
var gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
@ -79,7 +85,7 @@ class Register {
// Name label
lblName = new JLabel(name);
if (expand != null)
if (expandable)
lblName.addMouseListener(expand);
gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
@ -94,7 +100,7 @@ class Register {
txtValue.setText("00000000");
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 4, 0, 0);
gbc.insets = new Insets(0, 4, 0, 0);
list.add(txtValue, gbc);
// Value changed
@ -116,6 +122,7 @@ class Register {
case PROGRAM : initProgram(); break;
case VUE.CHCW: initCHCW (); break;
case VUE.ECR : initECR (); break;
case VUE.PC : initPC (); break;
case VUE.PIR : initPIR (); break;
case VUE.PSW : initPSW (); break;
case VUE.TKCW: initTKCW (); break;
@ -123,19 +130,25 @@ class Register {
}
// Expansion spacer
spacer = new JPanel(null);
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
spacer.setVisible(false);
list.add(spacer, new GridBagConstraints());
if (index != VUE.PC) {
spacer = new JPanel(null);
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
spacer.setVisible(false);
gbc = new GridBagConstraints();
list.add(spacer, gbc);
}
// Expansion area
expansion.setOpaque(false);
expansion.setVisible(false);
gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
if (index == VUE.PC)
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 4, 0, 0);
gbc.weightx = 1;
list.add(expansion, gbc);
}
@ -168,6 +181,50 @@ class Register {
group.add(addRadioButton("cpu.float" , FLOAT ));
}
// Expansion controls for PC
private void initPC() {
expansion = new JPanel(new GridBagLayout());
// Configure controls
for (int x = 0; x < 2; x++) {
// Indentation
var spacer = new JPanel(null);
spacer.setOpaque(false);
spacer.setPreferredSize(new Dimension(0, 0));
var gbc = new GridBagConstraints();
gbc.weightx = 1;
expansion.add(spacer, gbc);
// Name label
var label = new JLabel();
parent.app.localizer.add(label,
x == 0 ? "cpu.jump_from" : "cpu.jump_to" );
gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
expansion.add(label, gbc);
// Value text box
var txt = new JTextField();
txt.addActionListener(e->{
txt.setText((String) txt.getClientProperty("text"));
list.requestFocus();
});
txt.setBorder(null);
txt.setOpaque(false);
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 4, 0, 0);
expansion.add(txt, gbc);
// Initialize the corresponding component field
if (x == 0)
txtJumpFrom = txt;
else txtJumpTo = txt;
}
}
// Expansion controls for PSW
private void initPSW() {
expansion = new JPanel(new GridBagLayout());
@ -221,13 +278,23 @@ class Register {
txtValue.setText(
type != PROGRAM || mode == HEX ?
String.format("%08X", value) :
mode == SIGNED ? Integer.toString(value) :
mode == SIGNED ? Integer.toString(value) :
mode == UNSIGNED ? Long.toString(value & 0xFFFFFFFFL) :
Float.toString(Float.intBitsToFloat(value))
);
// Expansion controls
for (var control : controls) {
// PC expansion controls
if (index == VUE.PC) for (int x = 0; x < 2; x++) {
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
if (control instanceof JCheckBox) {
@ -256,16 +323,16 @@ class Register {
void setExpanded(boolean expanded) {
// Error checking
if (type == VUE.PC)
if (!expandable)
return;
// Update controls
this.expanded = expanded;
btnExpand.setText (expanded ? "-" : "+");
btnExpand.setText(expanded ? "-" : "+");
if (index != VUE.PC)
spacer.setVisible(expanded);
expansion.setVisible(expanded);
spacer .setVisible(expanded);
list.revalidate();
list.repaint();
}
// Specify the width of the expand button
@ -280,9 +347,15 @@ class Register {
this.font = font;
// Value text box
var size = new Dimension(8 * fontWidth + 4, fontHeight);
txtValue.setFont(font);
txtValue.setPreferredSize(
new Dimension(8 * fontWidth + 4, fontHeight));
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) {
@ -291,7 +364,7 @@ class Register {
if ((Boolean) ctrl.getClientProperty("hex"))
((JTextField) ctrl).setFont(font);
int digits = (Integer) ctrl.getClientProperty("digits");
var size = ctrl.getPreferredSize();
size = ctrl.getPreferredSize();
size.width = digits * fontWidth + 4;
ctrl.setPreferredSize(size);
}
@ -334,7 +407,7 @@ class Register {
var gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.gridwidth = 2;
gbc.insets = new Insets(0, 4, 0, 0);
gbc.insets = new Insets(0, 4, 0, 4);
expansion.add(ctrl, gbc);
}
@ -343,7 +416,7 @@ class Register {
// Configure control
var ctrl = new JRadioButton();
parent.app.getLocalizer().add(ctrl, key);
parent.app.localizer.add(ctrl, key);
ctrl.setBorder(null);
ctrl.setFocusable(false);
ctrl.setOpaque(false);

View File

@ -314,6 +314,7 @@ public class Localizer {
control instanceof AbstractButton ||
control instanceof JFrame ||
control instanceof JInternalFrame ||
control instanceof JLabel ||
control instanceof JPanel || // TitledBorder
control instanceof JTextComponent
)) return false;
@ -490,6 +491,8 @@ public class Localizer {
((JFrame ) control).setTitle(values[0]);
if (control instanceof JInternalFrame)
((JInternalFrame) control).setTitle(values[0]);
if (control instanceof JLabel )
((JLabel ) control).setText (values[0]);
if (control instanceof JTextComponent)
((JTextComponent) control).setText (values[0]);

View File

@ -7,10 +7,11 @@ class CPU {
private JavaVUE vue; // Emulation state
// Package fields
int cycles; // Cycles until next stage
int fetch; // Fetch unit index
int lastPC; // Previous value of PC
int stage; // Current processing stage
int cycles; // Cycles until next stage
int fetch; // Fetch unit index
int jumpFrom; // Source PC of most recent jump
int jumpTo; // Destination PC of most recent jump
int stage; // Current processing stage
// Program registers
int[] program;
@ -149,7 +150,8 @@ class CPU {
// Configure registers
ecr_eicc = 0xFFF0;
lastPC = 0xFFFFFFF0;
jumpFrom = 0xFFFFFFF0;
jumpTo = 0xFFFFFFF0;
pc = 0xFFFFFFF0;
psw_np = 1;
}

View File

@ -40,8 +40,16 @@ class JavaVUE extends VUE {
// Retrieve a register value
public int getRegister(int index, boolean system) {
// Non-indexed registers
if (system) switch (index) {
case VUE.PC : return cpu.pc;
case VUE.JUMP_FROM: return cpu.jumpFrom;
case VUE.JUMP_TO : return cpu.jumpTo;
}
// Indexed registers
return
index == VUE.PC && system ? cpu.pc :
index < 0 || index > 31 ? 0 :
system ? cpu.getSystemRegister(index) :
cpu.program[index]

View File

@ -99,9 +99,9 @@ JNIEXPORT jbyteArray JNICALL Java_vue_NativeVUE_getROM
return NULL;
// Copy the ROM data
jbyteArray ret = (*env)->NewByteArray(env, (jint)core->vue.bus.rom_size);
jbyteArray ret = (*env)->NewByteArray(env, (jint)core->vue.bus.romSize);
jbyte *elems = (*env)->GetByteArrayElements(env, ret, NULL);
memcpy(elems, core->vue.bus.rom, core->vue.bus.rom_size);
memcpy(elems, core->vue.bus.rom, core->vue.bus.romSize);
(*env)->ReleaseByteArrayElements(env, ret, elems, 0);
return ret;
}

View File

@ -20,17 +20,21 @@ public abstract class VUE {
public static final int S32 = 4;
// System register indexes
public static final int ADTRE = 25;
public static final int CHCW = 24;
public static final int ECR = 4;
public static final int EIPC = 0;
public static final int EIPSW = 1;
public static final int FEPC = 2;
public static final int FEPSW = 3;
public static final int PC = -1;
public static final int PIR = 6;
public static final int PSW = 5;
public static final int TKCW = 7;
public static final int ADTRE = 25;
public static final int CHCW = 24;
public static final int ECR = 4;
public static final int EIPC = 0;
public static final int EIPSW = 1;
public static final int FEPC = 2;
public static final int FEPSW = 3;
public static final int PIR = 6;
public static final int PSW = 5;
public static final int TKCW = 7;
// Non-standard register indexes
public static final int PC = -1;
public static final int JUMP_FROM = -2;
public static final int JUMP_TO = -3;
// Program register indexes
public static final int GP = 4;