Implementing disassembler interface
This commit is contained in:
parent
76c95b0523
commit
f8f4005e02
|
@ -27,13 +27,13 @@ static const int8_t LOOKUP_OPCODE[] = {
|
|||
VUE_SHL_REG, 1, VUE_SHR_REG, 1, VUE_JMP , 1, VUE_SAR_REG, 1,
|
||||
VUE_MUL , 1, VUE_DIV , 1, VUE_MULU , 1, VUE_DIVU , 1,
|
||||
VUE_OR , 1, VUE_AND , 1, VUE_XOR , 1, VUE_NOT , 1,
|
||||
-VUE_MOV_IMM, 2,-VUE_ADD_IMM, 2, VUE_SETF , 2,-VUE_CMP_IMM, 2,
|
||||
VUE_MOV_IMM,-2, VUE_ADD_IMM,-2, VUE_SETF , 2, VUE_CMP_IMM,-2,
|
||||
VUE_SHL_IMM, 2, VUE_SHR_IMM, 2, VUE_CLI , 2, VUE_SAR_IMM, 2,
|
||||
VUE_TRAP , 2, VUE_RETI , 2, VUE_HALT , 2, VUE_ILLEGAL, 0,
|
||||
VUE_LDSR , 2, VUE_STSR , 2, VUE_SEI , 2, BITSTRING , 2,
|
||||
VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3,
|
||||
VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3,
|
||||
-VUE_MOVEA , 5,-VUE_ADDI , 5, VUE_JR , 4, VUE_JAL , 4,
|
||||
VUE_MOVEA ,-5, VUE_ADDI ,-5, VUE_JR , 4, VUE_JAL , 4,
|
||||
VUE_ORI , 5, VUE_ANDI , 5, VUE_XORI , 5, VUE_MOVHI , 5,
|
||||
VUE_LD_B , 6, VUE_LD_H , 6, VUE_ILLEGAL, 0, VUE_LD_W , 6,
|
||||
VUE_ST_B , 6, VUE_ST_H , 6, VUE_ILLEGAL, 0, VUE_ST_W , 6,
|
||||
|
@ -71,10 +71,10 @@ static void cpuDecode(VUE_INST *inst, int32_t bits) {
|
|||
/* Configure instance fields */
|
||||
inst->bits = bits;
|
||||
inst->opcode = bits >> 26 & 63;
|
||||
x = inst->opcode << 1 | 1;
|
||||
extend = LOOKUP_OPCODE[x];
|
||||
inst->format = LOOKUP_OPCODE[x + 1];
|
||||
inst->id = extend < 0 ? -extend : extend;
|
||||
x = inst->opcode << 1;
|
||||
inst->id = LOOKUP_OPCODE[x ];
|
||||
extend = LOOKUP_OPCODE[x + 1];
|
||||
inst->format = extend < 0 ? -extend : extend;
|
||||
inst->size = inst->format < 4 ? 2 : 4;
|
||||
|
||||
/* Decode by format */
|
||||
|
|
|
@ -13,13 +13,11 @@ 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
|
||||
// Package fields
|
||||
MainWindow parent; // Containing window
|
||||
|
||||
// UI components
|
||||
private JPanel dasm; // Disassembler
|
||||
private DisassemblerPane panDasm; // Disassembler client
|
||||
private RegisterList lstProgram; // Program register list
|
||||
private RegisterList lstSystem; // System register list
|
||||
|
||||
|
@ -29,6 +27,8 @@ class CPUWindow extends ChildWindow {
|
|||
// Global Settings //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Font dasmFont; // Disassembler font
|
||||
static int dasmFontHeight; // Disassembler font line height
|
||||
static int regExpandWidth; // Width of register list expand button
|
||||
static Font regHexFont; // Register list hex font
|
||||
static Dimension regHexFontSize; // Max dimensions
|
||||
|
@ -64,7 +64,19 @@ class CPUWindow extends ChildWindow {
|
|||
regExpandWidth = label.getPreferredSize().width;
|
||||
label.setText("-");
|
||||
regExpandWidth = Math.max(regExpandWidth,
|
||||
label.getPreferredSize().width);
|
||||
label.getPreferredSize().width) + 4;
|
||||
|
||||
// Disassembler font
|
||||
setDasmFont(new Font(Util.fontFamily(new String[]
|
||||
{ "Consolas", Font.MONOSPACED } ), Font.PLAIN, 14));
|
||||
}
|
||||
|
||||
// Specify a font to use as the disassembler font
|
||||
static void setDasmFont(Font font) {
|
||||
dasmFont = font;
|
||||
var label = new JLabel("!");
|
||||
label.setFont(font);
|
||||
dasmFontHeight = label.getPreferredSize().height;
|
||||
}
|
||||
|
||||
// Specify a font to use as the register list hex font
|
||||
|
@ -84,25 +96,25 @@ class CPUWindow extends ChildWindow {
|
|||
super(parent, "cpu.title");
|
||||
instances.add(this);
|
||||
|
||||
var client = getContentPane();
|
||||
|
||||
dasm = new JPanel(null);
|
||||
dasm.setBackground(SystemColor.window);
|
||||
dasm.setFocusable(true);
|
||||
// Configure instance fields
|
||||
this.parent = parent;
|
||||
|
||||
// Configure child panes
|
||||
panDasm = new DisassemblerPane(this);
|
||||
lstSystem = new RegisterList(this, true);
|
||||
lstProgram = new RegisterList(this, false);
|
||||
|
||||
// Configure layout
|
||||
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.setLeftComponent(panDasm);
|
||||
outer.setRightComponent(inner);
|
||||
outer.setResizeWeight(1);
|
||||
|
||||
// Configure component
|
||||
var client = getContentPane();
|
||||
client.add(outer);
|
||||
client.setPreferredSize(new Dimension(480, 300));
|
||||
configure();
|
||||
|
@ -128,13 +140,15 @@ class CPUWindow extends ChildWindow {
|
|||
|
||||
// Apply configuration settings
|
||||
void configure() {
|
||||
panDasm .configure();
|
||||
lstProgram.configure();
|
||||
lstSystem .configure();
|
||||
}
|
||||
|
||||
// Update the display
|
||||
void refresh() {
|
||||
lstSystem.refresh();
|
||||
panDasm .refresh();
|
||||
lstSystem .refresh();
|
||||
lstProgram.refresh();
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ class Disassembler {
|
|||
row.mnemonic = "SETF" + CONDITIONS[inst.imm];
|
||||
|
||||
// All other mnemonics
|
||||
else row.mnemonic = MNEMONICS[inst.id];
|
||||
else row.mnemonic = MNEMONICS[inst.id + 1];
|
||||
|
||||
// Adjust mnemonic case
|
||||
if (!mnemonicCaps)
|
||||
|
@ -200,7 +200,7 @@ class Disassembler {
|
|||
|
||||
// Format the destination of a branch or jump
|
||||
private static String destination(Instruction inst, int address) {
|
||||
return !dispDest ? toHex(inst.disp, 1, immNumber) :
|
||||
return !dispDest ? toHex(inst.disp, 1, false) :
|
||||
String.format("%08" + (hexCaps ? "X" : "x"), address + inst.disp);
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,13 @@ class Disassembler {
|
|||
break;
|
||||
}
|
||||
|
||||
// LDSR
|
||||
if (inst.id == VUE.LDSR) {
|
||||
String temp = imm;
|
||||
imm = reg2;
|
||||
reg2 = temp;
|
||||
}
|
||||
|
||||
// Generic
|
||||
return String.format("%s, %s",
|
||||
destLast ? imm : reg2,
|
||||
|
@ -328,10 +335,10 @@ class Disassembler {
|
|||
"[%s %s %s]",
|
||||
src,
|
||||
inst.disp < 0 ? "-" : "+",
|
||||
toHex(Math.abs(inst.disp), 1, immNumber)
|
||||
toHex(Math.abs(inst.disp), 1, false)
|
||||
) : String.format(
|
||||
"%s[%s]",
|
||||
toHex(inst.disp, 1, immNumber),
|
||||
toHex(inst.disp, 1, false),
|
||||
src
|
||||
)
|
||||
;
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
package app;
|
||||
|
||||
// Java imports
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
|
||||
// Project imports
|
||||
import util.*;
|
||||
import vue.*;
|
||||
|
||||
// Disassembler UI
|
||||
class DisassemblerPane extends JScrollPane {
|
||||
|
||||
// Instance fields
|
||||
private int address; // Address of top row of output
|
||||
private CPUWindow parent; // Containing CPU window
|
||||
private boolean showBytes; // Display the bytes column
|
||||
private boolean shown; // Component has been shown
|
||||
private int[] widths; // Column widths
|
||||
|
||||
// UI components
|
||||
private JPanel client; // Client area
|
||||
private ArrayList<Row> rows; // Disassembler output
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Classes //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// One row of disassembler output
|
||||
private class Row extends Disassembler.Row {
|
||||
Instruction inst; // Decoded instruction
|
||||
JLabel[] labels; // Display text
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Constructors //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Default constructor
|
||||
DisassemblerPane(CPUWindow parent) {
|
||||
super(VERTICAL_SCROLLBAR_NEVER, HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
// Configure instance fields
|
||||
this.parent = parent;
|
||||
rows = new ArrayList<Row>();
|
||||
showBytes = true;
|
||||
widths = new int[5];
|
||||
|
||||
// Configure client area
|
||||
client = new JPanel(null) {
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
onPaint((Graphics2D) g, getWidth(), getHeight());
|
||||
}
|
||||
};
|
||||
client.addFocusListener(
|
||||
Util.onFocus(e->client.repaint(), e->client.repaint()));
|
||||
client.addKeyListener(Util.onKey(e->onKeyDown(e), null));
|
||||
client.addMouseListener(Util.onMouse(e->client.requestFocus(), null));
|
||||
client.setBackground(SystemColor.window);
|
||||
client.setFocusable(true);
|
||||
|
||||
// Configure component
|
||||
setViewportView(client);
|
||||
configure();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Package Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Apply configuration settings
|
||||
void configure() {
|
||||
client.repaint();
|
||||
}
|
||||
|
||||
// Update the display
|
||||
void refresh() {
|
||||
client.repaint();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Event Handlers //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Key down
|
||||
private void onKeyDown(KeyEvent e) {
|
||||
int code = e.getKeyCode();
|
||||
int count = tall(false);
|
||||
int mods = e.getModifiersEx();
|
||||
boolean alt = (mods & InputEvent.ALT_DOWN_MASK ) != 0;
|
||||
boolean ctrl = (mods & InputEvent.CTRL_DOWN_MASK) != 0;
|
||||
|
||||
// No Alt combinations
|
||||
if (alt) return;
|
||||
|
||||
// Goto
|
||||
if (ctrl && code == KeyEvent.VK_G) {
|
||||
String addr = JOptionPane.showInputDialog(
|
||||
this, "Goto:", "Goto", JOptionPane.PLAIN_MESSAGE);
|
||||
if (addr != null && addr.trim().length() != 0) {
|
||||
try { seek((int) Long.parseLong(addr, 16), count / 3); }
|
||||
catch (Exception x) { }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Seek
|
||||
switch (code) {
|
||||
case KeyEvent.VK_UP : seek(address, 1); break;
|
||||
case KeyEvent.VK_DOWN : seek(address, -1); break;
|
||||
case KeyEvent.VK_PAGE_UP : seek(address, count); break;
|
||||
case KeyEvent.VK_PAGE_DOWN: seek(address, -count); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Client paint
|
||||
private void onPaint(Graphics2D g, int width, int height) {
|
||||
var vue = parent.parent.vue;
|
||||
int pc = vue.getRegister(VUE.PC, true);
|
||||
|
||||
// The view is being shown for the first time
|
||||
if (!shown) {
|
||||
shown = true;
|
||||
seek(pc, tall(false) / 3);
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure working variables
|
||||
int address = this.address;
|
||||
int count = tall(true);
|
||||
var data = new byte[count * 4];
|
||||
int offset = 0;
|
||||
|
||||
// Disassemble from the current address
|
||||
vue.read(address, data, 0, data.length);
|
||||
widths[3] = widths[4] = 0;
|
||||
for (int y = 0; y < count; y++) {
|
||||
var row = y < rows.size() ? rows.get(y) : addRow();
|
||||
var color = SystemColor.windowText;
|
||||
|
||||
// Disassemble the instruction
|
||||
row.inst.decode(data, offset);
|
||||
Disassembler.disassemble(address, row.inst, row);
|
||||
updateRow(row);
|
||||
|
||||
// Highlight PC
|
||||
if (address == pc) {
|
||||
Color bg = SystemColor.control;
|
||||
if (client.isFocusOwner()) {
|
||||
bg = SystemColor.textHighlight;
|
||||
color = SystemColor.textHighlightText;
|
||||
}
|
||||
g.setColor(bg);
|
||||
g.fillRect(
|
||||
0, y * CPUWindow.dasmFontHeight,
|
||||
width, CPUWindow.dasmFontHeight
|
||||
);
|
||||
}
|
||||
|
||||
// Configure label text color
|
||||
for (var label : row.labels)
|
||||
label.setForeground(color);
|
||||
|
||||
// Advance to the next instruction
|
||||
int size = address + 2 == pc ? 2 : row.inst.size;
|
||||
address += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
// Configure all rows
|
||||
for (int y = 0; y < rows.size(); y++) {
|
||||
var row = rows.get(y);
|
||||
int top = y * CPUWindow.dasmFontHeight;
|
||||
|
||||
// Configure all labels
|
||||
for (int z = 0, x = 0; z < 5; z++) {
|
||||
var label = row.labels[z];
|
||||
|
||||
// The label is not part of the output
|
||||
if (y >= count || widths[z] == 0) {
|
||||
label.setVisible(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Configure the label
|
||||
label.setLocation(x, top);
|
||||
label.setSize(label.getPreferredSize());
|
||||
x += widths[z] + CPUWindow.dasmFontHeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Update the client's size
|
||||
var size = client.getPreferredSize();
|
||||
width = -CPUWindow.dasmFontHeight + 1;
|
||||
for (int x = 0; x < 5; x++)
|
||||
if (widths[x] != 0 && (x != 2 || showBytes))
|
||||
width += CPUWindow.dasmFontHeight + widths[x];
|
||||
if (width == size.width)
|
||||
return;
|
||||
client.setPreferredSize(new Dimension(width, 0));
|
||||
revalidate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create a new row object
|
||||
private Row addRow() {
|
||||
var row = new Row();
|
||||
row.inst = new Instruction();
|
||||
row.labels = new JLabel[5];
|
||||
|
||||
// Initialize columns
|
||||
for (int x = 0; x < 5; x++) {
|
||||
var label = row.labels[x] = new JLabel();
|
||||
if (x != 4)
|
||||
label.setFont(CPUWindow.dasmFont);
|
||||
client.add(label);
|
||||
}
|
||||
|
||||
rows.add(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
// Determine whether the instruction at an address is in the client view
|
||||
private boolean isVisible(int target) {
|
||||
int count = Math.max(1, tall(false));
|
||||
var data = new byte[count * 4];
|
||||
int offset = 0;
|
||||
var vue = parent.parent.vue;
|
||||
int pc = vue.getRegister(VUE.PC, true);
|
||||
target &= 0xFFFFFFFE;
|
||||
|
||||
// Load enough bytes to represent every fully visible instruction
|
||||
vue.read(address, data, 0, data.length);
|
||||
|
||||
// Iterate through instructions
|
||||
for (int x = 0, address = this.address; x < count; x++) {
|
||||
|
||||
// Determine the instruction's size
|
||||
int size = address + 2 == pc ? 2 :
|
||||
Instruction.size(data[offset + 1] >> 2 & 0x3F);
|
||||
|
||||
// The current instruction is the target
|
||||
if (address == target || size == 4 && address + 2 == target)
|
||||
return true;
|
||||
|
||||
// Advance to the next instruction
|
||||
address += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
// The instruction is not visible in the view
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine the address of the top row of output
|
||||
private void seek(int target, int row) {
|
||||
var data = new byte[(Math.abs(row) + 9) * 4];
|
||||
int offset = 0;
|
||||
var vue = parent.parent.vue;
|
||||
int pc = vue.getRegister(VUE.PC, true);
|
||||
target &= 0xFFFFFFFE;
|
||||
|
||||
// Scrolling down
|
||||
if (row <= 0) {
|
||||
|
||||
// Load bytes starting up to 8 instructions prior to the target
|
||||
address = target - 32;
|
||||
vue.read(address, data, 0, data.length);
|
||||
|
||||
// Iterate through instructions
|
||||
for (boolean found = false;;) {
|
||||
|
||||
// Determine the instruction's size
|
||||
int size = address + 2 == pc ? 2 :
|
||||
Instruction.size(data[offset + 1] >> 2 & 0x3F);
|
||||
|
||||
// The current instruction is the target
|
||||
if (address == target || size == 4 && address + 2 == target)
|
||||
found = true;
|
||||
if (found && row++ == 0)
|
||||
break;
|
||||
|
||||
// Advance to the next instruction
|
||||
address += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Scrolling up
|
||||
else {
|
||||
|
||||
// Load bytes starting up to 8 instructions prior to the top row
|
||||
address = target - data.length + 4;
|
||||
vue.read(address, data, 0, data.length);
|
||||
|
||||
// Iterate through instructions
|
||||
var addresses = new int[row]; // Circular buffer
|
||||
for (int index = 0;;) {
|
||||
|
||||
// Determine the instruction's size
|
||||
int size = pc == address + 2 ? 2 :
|
||||
Instruction.size(data[offset + 1] >> 2 & 63);
|
||||
|
||||
// The current instruction is the target
|
||||
if (address == target || size == 4 && address + 2 == target) {
|
||||
address = addresses[index];
|
||||
break;
|
||||
}
|
||||
|
||||
// Advance to the next instruction
|
||||
addresses[index] = address;
|
||||
if (++index == row)
|
||||
index = 0;
|
||||
address += size;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Common processing
|
||||
client.repaint();
|
||||
}
|
||||
|
||||
// Determine how many rows of output are visible
|
||||
private int tall(boolean partial) {
|
||||
return Math.max(1, (client.getHeight() +
|
||||
(partial ? CPUWindow.dasmFontHeight - 1 : 0)
|
||||
) / CPUWindow.dasmFontHeight);
|
||||
}
|
||||
|
||||
// Update a row with its text and measure the column widths
|
||||
private void updateRow(Row row) {
|
||||
|
||||
for (int x = 0; x < 5; x++) {
|
||||
var label = row.labels[x];
|
||||
|
||||
String text = null;
|
||||
switch (x) {
|
||||
case 0: text = row.address ; break;
|
||||
case 1: text = row.bytes ; break;
|
||||
case 2: text = row.mnemonic; break;
|
||||
case 3: text = row.operands; break;
|
||||
}
|
||||
|
||||
if (text != null) {
|
||||
label.setText(text);
|
||||
label.setVisible(x == 1 ? showBytes : true);
|
||||
widths[x] = Math.max(widths[x],label.getPreferredSize().width);
|
||||
} else label.setVisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import java.util.*;
|
|||
import javax.swing.*;
|
||||
|
||||
// Project imports
|
||||
import util.*;
|
||||
import vue.*;
|
||||
|
||||
// List of CPU registers
|
||||
|
@ -48,6 +49,7 @@ class RegisterList extends JScrollPane {
|
|||
super.paintComponent(g);
|
||||
}
|
||||
};
|
||||
client.addMouseListener(Util.onMouse(e->client.requestFocus(), null));
|
||||
client.setBackground(SystemColor.window);
|
||||
client.setFocusable(true);
|
||||
|
||||
|
|
|
@ -32,13 +32,13 @@ public class Instruction {
|
|||
VUE.SHL_REG, 1, VUE.SHR_REG, 1, VUE.JMP , 1, VUE.SAR_REG, 1,
|
||||
VUE.MUL , 1, VUE.DIV , 1, VUE.MULU , 1, VUE.DIVU , 1,
|
||||
VUE.OR , 1, VUE.AND , 1, VUE.XOR , 1, VUE.NOT , 1,
|
||||
-VUE.MOV_IMM, 2,-VUE.ADD_IMM, 2, VUE.SETF , 2,-VUE.CMP_IMM, 2,
|
||||
VUE.MOV_IMM,-2, VUE.ADD_IMM,-2, VUE.SETF , 2, VUE.CMP_IMM,-2,
|
||||
VUE.SHL_IMM, 2, VUE.SHR_IMM, 2, VUE.CLI , 2, VUE.SAR_IMM, 2,
|
||||
VUE.TRAP , 2, VUE.RETI , 2, VUE.HALT , 2, VUE.ILLEGAL, 0,
|
||||
VUE.LDSR , 2, VUE.STSR , 2, VUE.SEI , 2, BITSTRING , 2,
|
||||
VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3,
|
||||
VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3,
|
||||
-VUE.MOVEA , 5,-VUE.ADDI , 5, VUE.JR , 4, VUE.JAL , 4,
|
||||
VUE.MOVEA ,-5, VUE.ADDI ,-5, VUE.JR , 4, VUE.JAL , 4,
|
||||
VUE.ORI , 5, VUE.ANDI , 5, VUE.XORI , 5, VUE.MOVHI , 5,
|
||||
VUE.LD_B , 6, VUE.LD_H , 6, VUE.ILLEGAL, 0, VUE.LD_W , 6,
|
||||
VUE.ST_B , 6, VUE.ST_H , 6, VUE.ILLEGAL, 0, VUE.ST_W , 6,
|
||||
|
@ -70,7 +70,7 @@ public class Instruction {
|
|||
|
||||
// Determine the size of an instruction given its opcode
|
||||
public static int size(int opcode) {
|
||||
return LOOKUP_OPCODE[opcode << 1 | 1] < 4 ? 2 : 4;
|
||||
return Math.abs(LOOKUP_OPCODE[opcode << 1 | 1]) < 4 ? 2 : 4;
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class Instruction {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Default constructor
|
||||
Instruction() { }
|
||||
public Instruction() { }
|
||||
|
||||
|
||||
|
||||
|
@ -88,6 +88,14 @@ public class Instruction {
|
|||
// Public Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Decode an instruction from a byte array
|
||||
public void decode(byte[] data, int offset) {
|
||||
bits = (data[offset + 1] & 0xFF) << 24 | (data[offset] & 0xFF) << 16;
|
||||
if (size(bits >>> 26) == 4)
|
||||
bits |= (data[offset + 3] & 0xFF) << 8 | data[offset + 2] & 0xFF;
|
||||
decode(bits);
|
||||
}
|
||||
|
||||
// Decode an instruction from its binary encoding
|
||||
public void decode(int bits) {
|
||||
byte extend; // Sign-extend the immediate operand
|
||||
|
@ -96,10 +104,10 @@ public class Instruction {
|
|||
// Configure instance fields
|
||||
this.bits = bits;
|
||||
opcode = bits >> 26 & 63;
|
||||
x = opcode << 1 | 1;
|
||||
extend = LOOKUP_OPCODE[x];
|
||||
format = LOOKUP_OPCODE[x + 1];
|
||||
id = extend < 0 ? -extend : extend;
|
||||
x = opcode << 1;
|
||||
id = LOOKUP_OPCODE[x ];
|
||||
extend = LOOKUP_OPCODE[x + 1];
|
||||
format = extend < 0 ? -extend : extend;
|
||||
size = format < 4 ? 2 : 4;
|
||||
|
||||
// Decode by format
|
||||
|
|
Loading…
Reference in New Issue