Compare commits
2 commits
1fb7d52842
...
098766bb65
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
098766bb65 | ||
|
|
d3ab78e76c |
9 changed files with 195 additions and 32 deletions
|
|
@ -42,8 +42,13 @@ void MachineController::runLoop() {
|
||||||
try {
|
try {
|
||||||
if (m_machine) {
|
if (m_machine) {
|
||||||
m_machine->execute();
|
m_machine->execute();
|
||||||
m_machine->tick();
|
m_machine->tick();
|
||||||
emit tick();
|
emit tick();
|
||||||
|
|
||||||
|
if (m_machine->isStopped()) {
|
||||||
|
m_running.store(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
emit error(QString::fromStdString(e.what()));
|
emit error(QString::fromStdString(e.what()));
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
class Loader;
|
class Loader;
|
||||||
|
|
||||||
|
|
@ -69,8 +72,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||||
ui->regF_bin_field->setValidator(floatBinValidator);
|
ui->regF_bin_field->setValidator(floatBinValidator);
|
||||||
|
|
||||||
|
|
||||||
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateRegisterDisplays);
|
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateRegisterDisplays, Qt::QueuedConnection);
|
||||||
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateMemoryDisplay);
|
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateMemoryDisplay, Qt::QueuedConnection);
|
||||||
|
|
||||||
connectRegisterFields();
|
connectRegisterFields();
|
||||||
|
|
||||||
|
|
@ -95,15 +98,16 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||||
connect(ui->DisasmDec65536Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec256);
|
connect(ui->DisasmDec65536Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec256);
|
||||||
connect(ui->DisasmGoToStart, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToStart);
|
connect(ui->DisasmGoToStart, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToStart);
|
||||||
connect(ui->DisasmGoToEnd, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToEnd);
|
connect(ui->DisasmGoToEnd, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToEnd);
|
||||||
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateDisassemblyDisplay);
|
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateDisassemblyDisplay, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
// Connect menu actions
|
||||||
|
connect(ui->actionLoad_Object_File, &QAction::triggered, this, &MainWindow::loadObjectFile);
|
||||||
|
|
||||||
setupMemoryDisplay();
|
setupMemoryDisplay();
|
||||||
setupDisassemblyDisplay();
|
setupDisassemblyDisplay();
|
||||||
|
|
||||||
loadInstructionSet();
|
loadInstructionSet();
|
||||||
//loadDemoProgram();
|
// Don't load any program by default - user will load via File menu
|
||||||
Loader loader(m_machine, std::string(PATH_RESOURCES) + "print.obj");
|
|
||||||
loader.load();
|
|
||||||
|
|
||||||
updateRegisterDisplays();
|
updateRegisterDisplays();
|
||||||
updateMemoryDisplay();
|
updateMemoryDisplay();
|
||||||
|
|
@ -695,7 +699,18 @@ MainWindow::DisassembledInstruction MainWindow::disassembleAt(int address)
|
||||||
QString reg1Str = (r1 < 10) ? regNames[r1] : "?";
|
QString reg1Str = (r1 < 10) ? regNames[r1] : "?";
|
||||||
QString reg2Str = (r2 < 10) ? regNames[r2] : "?";
|
QString reg2Str = (r2 < 10) ? regNames[r2] : "?";
|
||||||
|
|
||||||
result.operand = QString("%1, %2").arg(reg1Str).arg(reg2Str);
|
// Check if this is a single-operand Format 2 instruction
|
||||||
|
QString mnem = result.mnemonic.toUpper();
|
||||||
|
if (mnem == "CLEAR" || mnem == "TIXR") {
|
||||||
|
result.operand = reg1Str;
|
||||||
|
} else if (mnem == "SVC") {
|
||||||
|
result.operand = QString::number(r1);
|
||||||
|
} else if (mnem == "SHIFTL" || mnem == "SHIFTR") {
|
||||||
|
result.operand = QString("%1, %2").arg(reg1Str).arg(r2);
|
||||||
|
} else {
|
||||||
|
// Two register operands (ADDR, SUBR, COMPR, etc.)
|
||||||
|
result.operand = QString("%1, %2").arg(reg1Str).arg(reg2Str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -760,7 +775,7 @@ MainWindow::DisassembledInstruction MainWindow::disassembleAt(int address)
|
||||||
QString addrMode = "";
|
QString addrMode = "";
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
ea += m_machine->getPC();
|
ea += (address + 3);
|
||||||
addrMode = " (PC)";
|
addrMode = " (PC)";
|
||||||
} else if (b) {
|
} else if (b) {
|
||||||
ea += m_machine->getB();
|
ea += m_machine->getB();
|
||||||
|
|
@ -849,7 +864,13 @@ void MainWindow::updateDisassemblyDisplay()
|
||||||
layout->addStretch();
|
layout->addStretch();
|
||||||
container->setLayout(layout);
|
container->setLayout(layout);
|
||||||
|
|
||||||
|
// Save scroll position before updating
|
||||||
|
int scrollPos = ui->DisasemblyScrollArea->verticalScrollBar()->value();
|
||||||
|
|
||||||
ui->DisasemblyScrollArea->setWidget(container);
|
ui->DisasemblyScrollArea->setWidget(container);
|
||||||
|
|
||||||
|
// Restore scroll position after updating
|
||||||
|
ui->DisasemblyScrollArea->verticalScrollBar()->setValue(scrollPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateMemoryDisplay()
|
void MainWindow::updateMemoryDisplay()
|
||||||
|
|
@ -916,5 +937,44 @@ void MainWindow::updateMemoryDisplay()
|
||||||
layout->addStretch();
|
layout->addStretch();
|
||||||
container->setLayout(layout);
|
container->setLayout(layout);
|
||||||
|
|
||||||
|
int scrollPos = ui->MemoryScrollArea->verticalScrollBar()->value();
|
||||||
|
|
||||||
ui->MemoryScrollArea->setWidget(container);
|
ui->MemoryScrollArea->setWidget(container);
|
||||||
|
|
||||||
|
ui->MemoryScrollArea->verticalScrollBar()->setValue(scrollPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::loadObjectFile()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getOpenFileName(this,
|
||||||
|
tr("Load Object File"),
|
||||||
|
QString(),
|
||||||
|
tr("Object Files (*.obj);;All Files (*)"));
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Stop execution if running
|
||||||
|
m_controller->stop();
|
||||||
|
|
||||||
|
// Reset machine state
|
||||||
|
m_machine->reset();
|
||||||
|
|
||||||
|
// Load the object file
|
||||||
|
Loader loader(m_machine, fileName.toStdString());
|
||||||
|
loader.load();
|
||||||
|
|
||||||
|
// Update displays
|
||||||
|
updateRegisterDisplays();
|
||||||
|
updateMemoryDisplay();
|
||||||
|
updateDisassemblyDisplay();
|
||||||
|
|
||||||
|
QMessageBox::information(this, tr("Success"),
|
||||||
|
tr("Object file loaded successfully"));
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
QMessageBox::critical(this, tr("Error"),
|
||||||
|
tr("Failed to load object file: %1").arg(e.what()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ private slots:
|
||||||
void onDisassemblyDec256();
|
void onDisassemblyDec256();
|
||||||
void onDisassemblyGoToStart();
|
void onDisassemblyGoToStart();
|
||||||
void onDisassemblyGoToEnd();
|
void onDisassemblyGoToEnd();
|
||||||
|
void loadObjectFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
|
|
|
||||||
|
|
@ -866,6 +866,18 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
|
|
@ -875,8 +887,43 @@
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionLoad_Object_File"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuMachine">
|
||||||
|
<property name="title">
|
||||||
|
<string>Machine</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionFrequency"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuHelp">
|
||||||
|
<property name="title">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionAbout"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuMachine"/>
|
||||||
|
<addaction name="menuHelp"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<action name="actionLoad_Object_File">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load Object File</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionFrequency">
|
||||||
|
<property name="text">
|
||||||
|
<string>Frequency</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAbout">
|
||||||
|
<property name="text">
|
||||||
|
<string>About</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ private:
|
||||||
std::fstream fileStream;
|
std::fstream fileStream;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool fileCreated;
|
bool fileCreated;
|
||||||
|
std::streampos readPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILE_DEVICE_H
|
#endif // FILE_DEVICE_H
|
||||||
|
|
@ -26,7 +26,7 @@ using std::cout;
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
Machine();
|
Machine();
|
||||||
Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; _instructionsTable = instructions; }
|
Machine(int speedHz) : Machine() { this->speedHz = speedHz; _instructionsTable = instructions; }
|
||||||
~Machine();
|
~Machine();
|
||||||
|
|
||||||
int getA() const { return A; }
|
int getA() const { return A; }
|
||||||
|
|
@ -84,11 +84,13 @@ public:
|
||||||
|
|
||||||
// Execution and speed control
|
// Execution and speed control
|
||||||
int getSpeed() const;
|
int getSpeed() const;
|
||||||
void setSpeed(int kHz);
|
void setSpeed(int Hz);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void tick();
|
void tick();
|
||||||
void halt();
|
void halt();
|
||||||
|
bool isStopped() const { return _stopped; }
|
||||||
|
void reset();
|
||||||
|
|
||||||
// error handling methods
|
// error handling methods
|
||||||
void notImplemented(string mnemonic);
|
void notImplemented(string mnemonic);
|
||||||
|
|
@ -128,7 +130,7 @@ private:
|
||||||
|
|
||||||
// Execution control
|
// Execution control
|
||||||
std::atomic<bool> running{false};
|
std::atomic<bool> running{false};
|
||||||
std::atomic<int> speedkHz{1}; // Default 1 kHz
|
std::atomic<int> speedHz{10}; // Default 10 Hz
|
||||||
|
|
||||||
bool execF1(int opcode);
|
bool execF1(int opcode);
|
||||||
bool execF2(int opcode, int operand);
|
bool execF2(int opcode, int operand);
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,8 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
FileDevice::FileDevice(const std::string &filename)
|
FileDevice::FileDevice(const std::string &filename)
|
||||||
: filename(filename), fileCreated(false)
|
: filename(filename), fileCreated(false), readPosition(0)
|
||||||
{
|
{
|
||||||
// Don't create the file yet - wait until first write
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDevice::~FileDevice()
|
FileDevice::~FileDevice()
|
||||||
|
|
@ -18,9 +17,16 @@ FileDevice::~FileDevice()
|
||||||
void FileDevice::ensureFileOpen()
|
void FileDevice::ensureFileOpen()
|
||||||
{
|
{
|
||||||
if (!fileStream.is_open()) {
|
if (!fileStream.is_open()) {
|
||||||
if (fileCreated) {
|
// Check if file exists
|
||||||
fileStream.open(filename, std::ios::in | std::ios::out);
|
std::ifstream checkFile(filename);
|
||||||
|
bool fileExists = checkFile.good();
|
||||||
|
checkFile.close();
|
||||||
|
|
||||||
|
if (fileExists) {
|
||||||
|
fileStream.open(filename, std::ios::in | std::ios::out | std::ios::ate);
|
||||||
|
fileCreated = true;
|
||||||
} else {
|
} else {
|
||||||
|
// Create new file
|
||||||
std::ofstream create(filename);
|
std::ofstream create(filename);
|
||||||
if (!create) {
|
if (!create) {
|
||||||
throw std::runtime_error("Failed to create file: " + filename);
|
throw std::runtime_error("Failed to create file: " + filename);
|
||||||
|
|
@ -41,9 +47,11 @@ unsigned char FileDevice::read()
|
||||||
unsigned char value = 0;
|
unsigned char value = 0;
|
||||||
ensureFileOpen();
|
ensureFileOpen();
|
||||||
if (fileStream.is_open()) {
|
if (fileStream.is_open()) {
|
||||||
|
fileStream.seekg(readPosition);
|
||||||
char ch;
|
char ch;
|
||||||
if (fileStream.get(ch)) {
|
if (fileStream.get(ch)) {
|
||||||
value = static_cast<unsigned char>(ch);
|
value = static_cast<unsigned char>(ch);
|
||||||
|
readPosition = fileStream.tellg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|
@ -53,6 +61,7 @@ void FileDevice::write(unsigned char value)
|
||||||
{
|
{
|
||||||
ensureFileOpen();
|
ensureFileOpen();
|
||||||
if (fileStream.is_open()) {
|
if (fileStream.is_open()) {
|
||||||
|
fileStream.seekp(0, std::ios::end);
|
||||||
fileStream.put(static_cast<char>(value));
|
fileStream.put(static_cast<char>(value));
|
||||||
fileStream.flush();
|
fileStream.flush();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "file_reader.h"
|
#include "file_reader.h"
|
||||||
|
#include "string_reader.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
Loader::~Loader()
|
Loader::~Loader()
|
||||||
{
|
{
|
||||||
|
|
@ -82,20 +84,24 @@ Loader::TextRecord Loader::readTextRecord()
|
||||||
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
|
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
|
||||||
|
|
||||||
// Read length (1 byte, 2 hex digits)
|
// Read length (1 byte, 2 hex digits)
|
||||||
int length = std::stoi(_file_reader->readString(2), nullptr, 16);
|
std::string lengthStr = _file_reader->readString(2);
|
||||||
if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte();
|
int length = std::stoi(lengthStr, nullptr, 16);
|
||||||
|
|
||||||
|
// Read the rest of the line (data bytes with spaces)
|
||||||
|
std::string dataLine = _file_reader->readLine();
|
||||||
|
|
||||||
|
// Remove all whitespace from the data line
|
||||||
|
dataLine.erase(std::remove_if(dataLine.begin(), dataLine.end(), ::isspace), dataLine.end());
|
||||||
|
|
||||||
|
// Now use StringReader to parse the hex bytes
|
||||||
|
StringReader stringReader(dataLine);
|
||||||
record.data.resize(length);
|
record.data.resize(length);
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
string byteStr = _file_reader->readLine();
|
|
||||||
// Remove spaces, newlines, and other whitespace characters
|
|
||||||
byteStr.erase(std::remove_if(byteStr.begin(), byteStr.end(), ::isspace), byteStr.end());
|
|
||||||
|
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
std::string byteHex = byteStr.substr(i * 2, 2);
|
std::string byteHex = stringReader.readString(2);
|
||||||
record.data[i] = static_cast<uint8_t>(std::stoi(byteHex, nullptr, 16));
|
record.data[i] = static_cast<uint8_t>(std::stoi(byteHex, nullptr, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,17 @@ string prefix = "Machine error: ";
|
||||||
|
|
||||||
Machine::Machine()
|
Machine::Machine()
|
||||||
{
|
{
|
||||||
|
// Initialize registers and memory to zero
|
||||||
|
A = B = X = L = S = T = PC = SW = 0;
|
||||||
|
F = 0.0;
|
||||||
|
for (int i = 0; i < MEMORY_SIZE; i++) {
|
||||||
|
memory[i] = 0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < VECTOR_REG_SIZE; i++) {
|
||||||
|
VA[i] = VS[i] = VT[i] = 0;
|
||||||
|
}
|
||||||
|
_stopped = false;
|
||||||
|
|
||||||
devices.resize(NUM_DEVICES);
|
devices.resize(NUM_DEVICES);
|
||||||
// device 0: standard input
|
// device 0: standard input
|
||||||
devices[0] = make_shared<InputDevice>(std::cin);
|
devices[0] = make_shared<InputDevice>(std::cin);
|
||||||
|
|
@ -45,12 +56,12 @@ Machine::~Machine()
|
||||||
|
|
||||||
int Machine::getSpeed() const
|
int Machine::getSpeed() const
|
||||||
{
|
{
|
||||||
return speedkHz.load();
|
return speedHz.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::setSpeed(int kHz)
|
void Machine::setSpeed(int Hz)
|
||||||
{
|
{
|
||||||
speedkHz.store(kHz);
|
speedHz.store(Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement errors
|
// TODO: implement errors
|
||||||
|
|
@ -138,10 +149,10 @@ void Machine::setVT(const int *values)
|
||||||
|
|
||||||
void Machine::tick()
|
void Machine::tick()
|
||||||
{
|
{
|
||||||
const int speed = speedkHz.load();
|
const int speed = speedHz.load();
|
||||||
if (speed <= 0) throw std::runtime_error("Invalid speed setting in Machine::tick");
|
if (speed <= 0) throw std::runtime_error("Invalid speed setting in Machine::tick");
|
||||||
|
|
||||||
const auto delay = std::chrono::microseconds(1000 / speed);
|
const auto delay = std::chrono::milliseconds(1000 / speed);
|
||||||
std::this_thread::sleep_for(delay);
|
std::this_thread::sleep_for(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,6 +161,27 @@ void Machine::halt()
|
||||||
_stopped = true;
|
_stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Machine::reset()
|
||||||
|
{
|
||||||
|
// Reset all registers
|
||||||
|
A = B = X = L = S = T = PC = SW = 0;
|
||||||
|
F = 0.0;
|
||||||
|
|
||||||
|
// Clear memory
|
||||||
|
for (int i = 0; i < MEMORY_SIZE; i++) {
|
||||||
|
memory[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset execution state
|
||||||
|
_stopped = false;
|
||||||
|
running.store(false);
|
||||||
|
|
||||||
|
// Reset vector registers
|
||||||
|
for (int i = 0; i < VECTOR_REG_SIZE; i++) {
|
||||||
|
VA[i] = VS[i] = VT[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Machine::getReg(int regNum) const
|
int Machine::getReg(int regNum) const
|
||||||
{
|
{
|
||||||
switch (regNum) {
|
switch (regNum) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue