diff --git a/.gitignore b/.gitignore index dbda62e..7be8ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,7 @@ node_modules/ __pycache__/ *.pyc + +*.dev autotester sictools.jar diff --git a/ass1/arith.asm b/ass1/arith.asm new file mode 100644 index 0000000..24354b0 --- /dev/null +++ b/ass1/arith.asm @@ -0,0 +1,49 @@ +arith START 0 + + . seštevek: sum = x + y + LDA x + ADD y + STA sum + + . razlika: diff = x - y + LDA x + SUB y + STA diff + + . produkt: prod = x * y + LDA x + MUL y + STA prod + + . količnik: quot = x / y + LDA x + DIV y . + STA quot + + . ostanek: mod = x - y * (x / y) + STA qtemp + + LDA y + MUL qtemp + STA prodtmp + + LDA x + SUB prodtmp + STA mod + +HALT J HALT + +.data +x WORD 5 +y WORD 2 + +sum RESW 1 +diff RESW 1 +prod RESW 1 +quot RESW 1 +mod RESW 1 + +qtemp RESW 1 +prodtmp RESW 1 + + END arith diff --git a/ass1/arithr.asm b/ass1/arithr.asm new file mode 100644 index 0000000..69453f4 --- /dev/null +++ b/ass1/arithr.asm @@ -0,0 +1,59 @@ +.code +arithr START 0 + + LDA x ; A = x + LDB y ; B = y + + RMO A,S ; S = x + RMO B,T ; T = y + +. sum = x + y + RMO S,A ; A = x + ADDR T,A ; A = x + y + STA sum + +. diff = x - y + RMO S,A ; A = x + SUBR T,A ; A = x - y + STA diff + +. prod = x * y + RMO S,A ; A = x + RMO T,B ; B = y + MULR B,A ; A = x * y + STA prod + +. quot = x / y + RMO S,A ; A = x + RMO T,B ; B = y + DIVR B,A ; A = x / y + STA quot + + +. mod = x % y = x - (x / y)*y + RMO S,A + RMO T,B + DIVR B,A ; A = q = x/y + RMO A,L ; L = q (shrani) + + RMO T,A ; A = y + RMO L,B ; B = q + MULR B,A ; A = y*q = produkt + + RMO S,B ; B = x + SUBR A,B ; B = x - (y*q) + STB mod + +HALT J HALT + +.data +x WORD 5 +y WORD 2 + +sum RESW 1 +diff RESW 1 +prod RESW 1 +quot RESW 1 +mod RESW 1 + + END arithr diff --git a/vhod_izhod/cat.asm b/ass1/cat.asm similarity index 99% rename from vhod_izhod/cat.asm rename to ass1/cat.asm index 32b9908..6bb74d4 100644 --- a/vhod_izhod/cat.asm +++ b/ass1/cat.asm @@ -3,6 +3,7 @@ cat START 0 CLEAR X + read RD #0 STCH BUFF, X diff --git a/ass1/poly.asm b/ass1/poly.asm new file mode 100644 index 0000000..6fcddae --- /dev/null +++ b/ass1/poly.asm @@ -0,0 +1,57 @@ +poly START 0 + + . potence x^1 .. x^4 + LDA x + STA x1 + + MUL x + STA x2 + + MUL x + STA x3 + + MUL x + STA x4 + + + . x3 = 2 * x^3 + LDA x3 + LDB #2 + MULR A,B + STB x3 + + . x2 = 3 * x^2 + LDA x2 + LDB #3 + MULR A,B + STB x2 + + . x1 = 4 * x + LDA x1 + LDB #4 + MULR A,B + STB x1 + + . vsota vseh + LDA x0 + ADD x1 + ADD x2 + ADD x3 + ADD x4 + STA result + + +HALT J HALT + END poly +.data +x WORD 2 ; vrednost x + +x4 RESW 1 +x3 RESW 1 +x2 RESW 1 +x1 RESW 1 +x0 WORD 5 ; konstanta + +result RESW 1 + + END poly diff --git a/ass1/print.asm b/ass1/print.asm new file mode 100644 index 0000000..4b7d0ae --- /dev/null +++ b/ass1/print.asm @@ -0,0 +1,23 @@ +.code +prog START 0 + + LDX #0 + +loop LDCH msg,X + WD #0xAA + + TIX msglen + JLT loop + + LDA #0x0D + WD #0xAA + LDA #0x0A + WD #0xAA + +halt J halt + +.data +msg BYTE C'SIC/XE' +msglen WORD 6 + + END prog diff --git a/ass1/rec.asm b/ass1/rec.asm new file mode 100644 index 0000000..212bf23 --- /dev/null +++ b/ass1/rec.asm @@ -0,0 +1,223 @@ +prog START 0 + +.------------------------------------------- +. MAIN LOOP +. +. Psevdo: +. sp = 0 +. while true: +. n = readFA() +. if n == 0: halt +. acc = 1 +. fact() ; rekurzivno: acc = n! +. printStdout(acc) +.------------------------------------------- + CLEAR A + STA sp + +loop JSUB readFA + COMP #0 + JEQ halt + + STA n + LDA #1 + STA acc + + JSUB fact + LDA acc + JSUB printStdout + + J loop + +halt J halt + +.------------------------------------------- +. readFA +. +. Psevdo: +. B = 0 +. while true: +. ch = RD(FA) +. if ch == CR or ch == LF: break +. digit = ch - '0' +. B = B * 10 + digit +. return B +.------------------------------------------- +readFA CLEAR B + LDS #10 + +rd_loopFA RD #0xFA + COMP #0x0D . CR? + JEQ rd_doneCR_FA + COMP #0x0A . LF? + JEQ rd_doneFA + + SUB #0x30 + MULR S,B . B = B * 10 + ADDR A,B . B = B + digit + J rd_loopFA + +rd_doneCR_FA RD #0xFA . pogoltni LF po CR +rd_doneFA CLEAR A + RMO B,A + RSUB + +.------------------------------------------- +. fact +. +. Psevdo (globalni n, acc, sklad L): +. fact(): +. push(L) +. if n <= 1: +. pop(L); return +. acc = acc * n +. n = n - 1 +. fact() +. pop(L); return +.------------------------------------------- +fact . push L + LDA sp + ADD #3 + STA sp + LDX sp + STL stackL,X + + LDA n + COMP #1 + JGT fact_rec + + . base case: n <= 1 + LDX sp + LDL stackL,X + LDA sp + SUB #3 + STA sp + RSUB + +fact_rec . recursive case: acc *= n; n--; fact() + + LDB acc + LDS n + MULR S,B + STB acc + + LDA n + SUB #1 + STA n + + JSUB fact + + . pop L in return to caller + LDX sp + LDL stackL,X + LDA sp + SUB #3 + STA sp + RSUB + +.------------------------------------------- +. printStdout +. +. Psevdo: +. if A == 0: +. print "0\n" +. return +. ps_val = A +. ps_len = 0 +. while ps_val > 0: +. q = ps_val / 10 +. r = ps_val % 10 +. buf[ps_len] = '0' + r +. ps_len++ +. ps_val = q +. for i = ps_len-1 .. 0: +. print buf[i] +. print "\r\n" +.------------------------------------------- +printStdout COMP #0 + JEQ ps_zero + + STA ps_val + LDA #0 + STA ps_len + LDS #10 + LDT #0x30 . '0' + +ps_div LDA ps_val + COMP #0 + JEQ ps_divdone + + RMO A,B + DIVR S,B . kvocient v B + RMO B,X . X = kvocient + + MULR S,B + SUBR B,A . A = ostanek + ADDR T,A . A = '0' + ostanek + STA psdigit + + LDA ps_len + STA ps_idx + LDA #psbuf + ADD ps_idx + STA ps_ptr + LDA psdigit + STCH @ps_ptr + + LDA ps_len + ADD #1 + STA ps_len + + RMO X,A + STA ps_val + J ps_div + +ps_divdone LDA ps_len + SUB #1 + STA ps_idx + +ps_print LDA ps_idx + COMP #0 + JLT ps_end + + LDA #psbuf + ADD ps_idx + STA ps_ptr + LDCH @ps_ptr + WD #1 + + LDA ps_idx + SUB #1 + STA ps_idx + J ps_print + +ps_end LDA #0x0D . CR + WD #1 + LDA #0x0A . LF + WD #1 + RSUB + +ps_zero LDA #0x30 . "0" + WD #1 + LDA #0x0D + WD #1 + LDA #0x0A + WD #1 + RSUB + +.data +. rekurzija faktoriala +sp WORD 0 . stack pointer +n WORD 0 +acc WORD 0 . akumulator za faktorial +stackL RESB 60 + +. printStdout +ps_val WORD 0 +ps_len WORD 0 +ps_idx WORD 0 +psdigit WORD 0 +ps_ptr WORD 0 +psbuf RESB 12 + + END prog diff --git a/ass1/stack.asm b/ass1/stack.asm new file mode 100644 index 0000000..a61cbea --- /dev/null +++ b/ass1/stack.asm @@ -0,0 +1,56 @@ +.code + +stack START 0 + + LDA #9 + STA @stackptr + JSUB stackpush + + JSUB stackpop + LDA @stackptr + +halt J halt + + +stackinit + STA stacktmp + + LDA #STACK + STA stackptr + + LDA stacktmp + RSUB + + +stackpush + STA stacktmp + + LDA stackptr + ADD #3 + STA stackptr + + LDA stacktmp + RSUB + + +stackpop + STA stacktmp + + LDA stackptr + SUB #3 + STA stackptr + + LDA stacktmp + RSUB + + +.data + +stackptr WORD 0 + +stacktmp WORD 0 + +STACKSIZE EQU 50 +STACK RESW STACKSIZE + + END stack diff --git a/simulator_SIC_XE/.gitignore b/simulator_SIC_XE/.gitignore index 4cbe372..6b70294 100644 --- a/simulator_SIC_XE/.gitignore +++ b/simulator_SIC_XE/.gitignore @@ -7,6 +7,7 @@ CMakeCache.txt CMakeFiles/ CMakeScripts/ cmake_install.cmake +Makefile *.cmake !CMakeLists.txt @@ -70,7 +71,6 @@ xcuserdata/ *.moc.cpp *.qm *.prl -CMakeLists.txt.user # OS generated files .DS_Store diff --git a/simulator_SIC_XE/CMakeLists.txt b/simulator_SIC_XE/CMakeLists.txt index c6c37e1..242ebd3 100644 --- a/simulator_SIC_XE/CMakeLists.txt +++ b/simulator_SIC_XE/CMakeLists.txt @@ -4,7 +4,7 @@ project(simulator_SIC_XE VERSION 1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Put all build outputs under target/bin +# Put all build outputs under target/bin as requested set(OUTPUT_DIR ${CMAKE_SOURCE_DIR}/target/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR}) @@ -28,7 +28,8 @@ if(EXISTS "${PROJECT_SOURCE_DIR}/src/main.cpp") target_link_libraries(simulator_exec PRIVATE simulator_lib) endif() - +# Convenience target: `cmake --build build --target run` +# This target will build `simulator_exec` (if present) and then execute it. if(TARGET simulator_exec) add_custom_target(run DEPENDS simulator_exec @@ -42,19 +43,3 @@ endif() message(STATUS "Project: ${PROJECT_NAME}") message(STATUS "Sources found: ${SOURCES}") message(STATUS "Output directory: ${OUTPUT_DIR}") - -if(EXISTS "${CMAKE_SOURCE_DIR}/gui/qt/CMakeLists.txt") - add_subdirectory(gui/qt) -endif() - -# Copy resources directory (if present) to target/res so build output includes them -if(EXISTS "${CMAKE_SOURCE_DIR}/res") - add_custom_target(copy_resources - COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/target/res - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res ${CMAKE_SOURCE_DIR}/target/res - COMMENT "Copying resources from res/ to target/res/" - ) - if(TARGET simulator_exec) - add_dependencies(simulator_exec copy_resources) - endif() -endif() diff --git a/simulator_SIC_XE/Makefile b/simulator_SIC_XE/Makefile deleted file mode 100644 index 92ab3cc..0000000 --- a/simulator_SIC_XE/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -# Simple Makefile wrapper to configure, build and run the CMake project. -# Usage: -# make # builds (default) -# make build # configure + build -# make run # build (if needed) and run the executable -# make clean # run CMake clean (or remove build files) -# make distclean # remove build dir and generated targets - -CMAKE ?= cmake -BUILD_DIR := build -CMAKE_BUILD_TYPE ?= Release -TARGET := target/bin/simulator_exec -GUI_TARGET := target/bin/simulator_qt - -.PHONY: all configure build run clean distclean - -all: build - -configure: - @echo "Configuring (build dir: $(BUILD_DIR), type: $(CMAKE_BUILD_TYPE))" - $(CMAKE) -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) - -build: configure - @echo "Building..." - $(CMAKE) --build $(BUILD_DIR) -j$(shell nproc) - -run: build - @echo "Running primary target..." - # Prefer GUI if avail able, otherwise fall back to console executable - @if [ -x "$(GUI_TARGET)" ]; then \ - echo "Launching GUI: $(GUI_TARGET)"; \ - sh -c 'nohup env QT_QPA_PLATFORM=xcb ./$(GUI_TARGET) >/dev/null 2>&1 & echo $! > "$(BUILD_DIR)/simulator_qt.pid"'; \ - elif [ -x "$(TARGET)" ]; then \ - @./$(TARGET); \ - else \ - echo "No runnable target found (tried $(GUI_TARGET) and $(TARGET))."; exit 1; \ - fi - -.PHONY: run-gui -run-gui: build - @echo "Running GUI target ($(GUI_TARGET))" - @if [ -x "$(GUI_TARGET)" ]; then \ - echo "Starting GUI..."; ./$(GUI_TARGET) -platform xcb; \ - else \ - echo "GUI executable not found: $(GUI_TARGET)"; exit 1; \ - fi - -.PHONY: build-gui -build-gui: configure - @echo "Building GUI (and core)..." - $(CMAKE) --build $(BUILD_DIR) -j$(shell nproc) --target simulator_qt || true - -clean: - @echo "Cleaning build (CMake clean)..." - -$(CMAKE) --build $(BUILD_DIR) --target clean || true - -distclean: - @echo "Removing build artifacts and generated files..." - -rm -rf $(BUILD_DIR) CMakeFiles CMakeCache.txt cmake_install.cmake target/bin/* diff --git a/simulator_SIC_XE/gui/qt/CMakeLists.txt b/simulator_SIC_XE/gui/qt/CMakeLists.txt deleted file mode 100644 index cf8072a..0000000 --- a/simulator_SIC_XE/gui/qt/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(simulator_qt LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - -# Prefer Qt6, fall back to Qt5 -find_package(Qt6 COMPONENTS Widgets QUIET) -if(NOT Qt6_FOUND) - # Try explicitly the system Qt6 cmake prefix on Debian/Ubuntu - find_package(Qt6 COMPONENTS Widgets QUIET PATHS /usr/lib/x86_64-linux-gnu) -endif() - -if(NOT Qt6_FOUND) - # Fallback: try Qt5 if Qt6 is unavailable - find_package(Qt5 COMPONENTS Widgets QUIET) -endif() - -if(Qt6_FOUND) - set(QT_LIB Qt6::Widgets) -elseif(Qt5_FOUND) - set(QT_LIB Qt5::Widgets) -else() - message(FATAL_ERROR "Qt6 or Qt5 not found. Install Qt development packages or set CMAKE_PREFIX_PATH to your Qt installation.") -endif() - -set(GUI_SRCS - main.cpp - mainwindow.cpp - MachineController.cpp -) - -set(GUI_HDRS - mainwindow.h - MachineController.h -) - -add_executable(simulator_qt ${GUI_SRCS} ${GUI_HDRS}) - -# Allow the generated UI headers (from AUTOUIC) to be found in the build dir -# and also include the top-level include folder (works when added with add_subdirectory) -target_include_directories(simulator_qt PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include) - -# Link to core library target (must be defined by top-level CMake) -target_link_libraries(simulator_qt PRIVATE simulator_lib ${QT_LIB}) - -# Place runtime binary under repo/target/bin to match project layout -set_target_properties(simulator_qt PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/target/bin -) \ No newline at end of file diff --git a/simulator_SIC_XE/gui/qt/MachineController.cpp b/simulator_SIC_XE/gui/qt/MachineController.cpp deleted file mode 100644 index 0ea4178..0000000 --- a/simulator_SIC_XE/gui/qt/MachineController.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "MachineController.h" -#include "../../include/machine.h" -#include -#include - -MachineController::MachineController(std::shared_ptr machine, QObject *parent) - : QObject(parent), m_machine(std::move(machine)) -{ - if (!m_machine) { - m_machine = std::make_shared(); - } -} - -MachineController::~MachineController() { - stop(); -} - -void MachineController::start() { - if (m_running.exchange(true)) return; - m_thread = std::thread([this]{ runLoop(); }); -} - -void MachineController::stop() { - if (!m_running.exchange(false)) return; - if (m_thread.joinable()) m_thread.join(); -} - -void MachineController::step() { - try { - if (m_machine) { - m_machine->execute(); - m_machine->tick(); - emit tick(); - } - } catch (const std::exception &e) { - emit error(QString::fromStdString(e.what())); - } -} - -void MachineController::runLoop() { - while (m_running.load()) { - try { - if (m_machine) { - m_machine->execute(); - m_machine->tick(); - emit tick(); - } - } catch (const std::exception &e) { - emit error(QString::fromStdString(e.what())); - // Stop on fatal error - m_running.store(false); - break; - } - } -} diff --git a/simulator_SIC_XE/gui/qt/MachineController.h b/simulator_SIC_XE/gui/qt/MachineController.h deleted file mode 100644 index fa904a3..0000000 --- a/simulator_SIC_XE/gui/qt/MachineController.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MACHINECONTROLLER_H -#define MACHINECONTROLLER_H - -#include -#include -#include -#include - -class Machine; - -class MachineController : public QObject { - Q_OBJECT -public: - explicit MachineController(std::shared_ptr machine = nullptr, QObject *parent = nullptr); - ~MachineController() override; - - void start(); - void stop(); - void step(); - -signals: - void tick(); - void error(const QString &msg); - -private: - void runLoop(); - std::atomic m_running{false}; - std::thread m_thread; - std::shared_ptr m_machine; -}; - -#endif // MACHINECONTROLLER_H diff --git a/simulator_SIC_XE/gui/qt/main.cpp b/simulator_SIC_XE/gui/qt/main.cpp deleted file mode 100644 index f9b6517..0000000 --- a/simulator_SIC_XE/gui/qt/main.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include "mainwindow.h" -#include "../../include/opcode.h" - -int main(int argc, char **argv) { - loadInstructionSet(); - QApplication app(argc, argv); - MainWindow w; - w.show(); - return app.exec(); -} \ No newline at end of file diff --git a/simulator_SIC_XE/gui/qt/mainwindow.cpp b/simulator_SIC_XE/gui/qt/mainwindow.cpp deleted file mode 100644 index afc464c..0000000 --- a/simulator_SIC_XE/gui/qt/mainwindow.cpp +++ /dev/null @@ -1,918 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include "MachineController.h" -#include "../../include/machine.h" -#include "../../include/instructions.h" -#include "../../include/opcode.h" -#include "../../include/constants.h" -#include "../../../include/loader.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Loader; - -std::shared_ptr g_loader; - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - m_machine(std::make_shared()), - m_controller(std::make_unique(m_machine, this)) -{ - ui->setupUi(this); - - ui->regA_dec_field->setValidator(new QIntValidator(-8388608, 8388607, this)); - ui->regB_dec_field->setValidator(new QIntValidator(-8388608, 8388607, this)); - ui->regS_dec_field->setValidator(new QIntValidator(-8388608, 8388607, this)); - ui->regT_dec_field->setValidator(new QIntValidator(-8388608, 8388607, this)); - ui->regX_dec_field->setValidator(new QIntValidator(-8388608, 8388607, this)); - // unsigned 24 bit - ui->regL_dec_field->setValidator(new QIntValidator(0, 16777215, this)); - ui->regPC_dec_field->setValidator(new QIntValidator(0, 16777215, this)); - ui->regSW_dec_field->setValidator(new QIntValidator(0, 16777215, this)); - // float - ui->regF_dec_field->setValidator(new QDoubleValidator(-3.402823e38, 3.402823e38, 6, this)); - - QRegularExpressionValidator* hexValidator = new QRegularExpressionValidator(QRegularExpression("^(0x)?[0-9A-Fa-f]{1,6}$"), this); - ui->regA_hex_field->setValidator(hexValidator); - ui->regB_hex_field->setValidator(hexValidator); - ui->regX_hex_field->setValidator(hexValidator); - ui->regS_hex_field->setValidator(hexValidator); - ui->regT_hex_field->setValidator(hexValidator); - ui->regL_hex_field->setValidator(hexValidator); - ui->regPC_hex_field->setValidator(hexValidator); - ui->regSW_hex_field->setValidator(hexValidator); - - QRegularExpressionValidator* binValidator = new QRegularExpressionValidator(QRegularExpression("^[01]{1,24}$"), this); - ui->regA_bin_field->setValidator(binValidator); - ui->regB_bin_field->setValidator(binValidator); - ui->regX_bin_field->setValidator(binValidator); - ui->regS_bin_field->setValidator(binValidator); - ui->regT_bin_field->setValidator(binValidator); - ui->regL_bin_field->setValidator(binValidator); - ui->regPC_bin_field->setValidator(binValidator); - ui->regSW_bin_field->setValidator(binValidator); - - QRegularExpressionValidator* floatHexValidator = new QRegularExpressionValidator(QRegularExpression("^(0x)?[0-9A-Fa-f]{1,12}$"), this); - ui->regF_hex_field->setValidator(floatHexValidator); - - QRegularExpressionValidator* floatBinValidator = new QRegularExpressionValidator(QRegularExpression("^[01]{1,48}$"), this); - ui->regF_bin_field->setValidator(floatBinValidator); - - - connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateRegisterDisplays); - connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateMemoryDisplay); - - connectRegisterFields(); - - connect(ui->StartBtn, &QPushButton::clicked, this, &MainWindow::startExecution); - connect(ui->StopBtn, &QPushButton::clicked, this, &MainWindow::stopExecution); - connect(ui->StepBtn, &QPushButton::clicked, this, &MainWindow::stepExecution); - - connect(ui->MemoryInc256Btn, &QPushButton::clicked, this, &MainWindow::onMemoryInc256); - connect(ui->MemoryInc4096Btn, &QPushButton::clicked, this, &MainWindow::onMemoryInc4096); - connect(ui->MemoryInc65536Btn, &QPushButton::clicked, this, &MainWindow::onMemoryInc65536); - connect(ui->MemoryDec256Btn, &QPushButton::clicked, this, &MainWindow::onMemoryDec256); - connect(ui->MemoryDec4096Btn, &QPushButton::clicked, this, &MainWindow::onMemoryDec4096); - connect(ui->MemoryDec65536Btn, &QPushButton::clicked, this, &MainWindow::onMemoryDec65536); - connect(ui->MemoryGoToStart_2, &QPushButton::clicked, this, &MainWindow::onMemoryGoToStart); - connect(ui->MemoryGoToEnd, &QPushButton::clicked, this, &MainWindow::onMemoryGoToEnd); - - connect(ui->DisasmInc256Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyInc); - connect(ui->DisasmInc4096Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyInc16); - connect(ui->DisasmInc65536Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyInc256); - connect(ui->DisasmDec256Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec); - connect(ui->DisasmDec4096Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec16); - connect(ui->DisasmDec65536Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec256); - connect(ui->DisasmGoToStart, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToStart); - connect(ui->DisasmGoToEnd, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToEnd); - connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateDisassemblyDisplay); - - setupMemoryDisplay(); - setupDisassemblyDisplay(); - //loadDemoProgram(); - g_loader = std::make_shared(machine(), std::string(PATH_RESOURCES) + "demo_program.obj"); - g_loader->load(); - - updateRegisterDisplays(); - updateMemoryDisplay(); - updateDisassemblyDisplay(); -} - -MainWindow::~MainWindow() -{ - delete ui; -} - -void MainWindow::updateRegisterDisplays() -{ - if (!m_machine) return; - - // Update all register display formats (decimal, hex, binary) - updateAllFormatsForRegister("regA", m_machine->getA()); - updateAllFormatsForRegister("regB", m_machine->getB()); - updateAllFormatsForRegister("regX", m_machine->getX()); - updateAllFormatsForRegister("regS", m_machine->getS()); - updateAllFormatsForRegister("regT", m_machine->getT()); - updateAllFormatsForRegister("regL", m_machine->getL()); - updateAllFormatsForRegister("regPC", m_machine->getPC()); - updateAllFormatsForRegister("regSW", m_machine->getSW()); - updateFloatRegisterFormats("regF", m_machine->getF()); -} - -void MainWindow::updateSingleRegisterDisplay(const QString& fieldName, int value) -{ - QLineEdit* field = findChild(fieldName); - if (field) { - // Only update if the field doesn't have focus (to avoid interfering with user input) - if (!field->hasFocus()) { - field->setText(QString::number(value)); - } - } -} - -void MainWindow::updateAllFormatsForRegister(const QString& regPrefix, int value) -{ - // Update decimal field - QLineEdit* decField = findChild(regPrefix + "_dec_field"); - if (decField && !decField->hasFocus()) { - decField->setText(QString::number(value)); - } - - // Update hex field - QLineEdit* hexField = findChild(regPrefix + "_hex_field"); - if (hexField && !hexField->hasFocus()) { - // Convert to 24-bit representation, handle negative numbers - unsigned int unsignedValue = static_cast(value) & 0xFFFFFF; - hexField->setText(QString("0x%1").arg(unsignedValue, 6, 16, QChar('0')).toUpper()); - } - - // Update binary field - QLineEdit* binField = findChild(regPrefix + "_bin_field"); - if (binField && !binField->hasFocus()) { - // Convert to 24-bit binary representation - unsigned int unsignedValue = static_cast(value) & 0xFFFFFF; - QString binaryStr = QString::number(unsignedValue, 2); - // Pad to 24 bits - binaryStr = binaryStr.rightJustified(24, '0'); - binField->setText(binaryStr); - } -} - -void MainWindow::updateFloatRegisterFormats(const QString& regPrefix, double value) -{ - // Update decimal field - QLineEdit* decField = findChild(regPrefix + "_dec_field"); - if (decField && !decField->hasFocus()) { - decField->setText(QString::number(value, 'g', 10)); - } - - // Update hex field (48-bit float representation) - QLineEdit* hexField = findChild(regPrefix + "_hex_field"); - if (hexField && !hexField->hasFocus()) { - // Convert double to 48-bit hex representation - // For SIC/XE, we need to convert to the 48-bit float format - uint64_t* intPtr = reinterpret_cast(&value); - uint64_t bits48 = (*intPtr) & 0xFFFFFFFFFFFFULL; // Mask to 48 bits - hexField->setText(QString("0x%1").arg(bits48, 12, 16, QChar('0')).toUpper()); - } - - // Update binary field (48-bit float representation) - QLineEdit* binField = findChild(regPrefix + "_bin_field"); - if (binField && !binField->hasFocus()) { - // Convert double to 48-bit binary representation - uint64_t* intPtr = reinterpret_cast(&value); - uint64_t bits48 = (*intPtr) & 0xFFFFFFFFFFFFULL; // Mask to 48 bits - QString binaryStr = QString::number(bits48, 2); - // Pad to 48 bits - binaryStr = binaryStr.rightJustified(48, '0'); - binField->setText(binaryStr); - } -} - -void MainWindow::connectRegisterFields() -{ - // Connect decimal register fields to update machine registers when changed - connect(ui->regA_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regB_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regX_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regS_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regT_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regL_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regPC_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regSW_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - connect(ui->regF_dec_field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - - // Connect hex register fields - QLineEdit* hexFields[] = { - ui->regA_hex_field, ui->regB_hex_field, ui->regX_hex_field, - ui->regS_hex_field, ui->regT_hex_field, ui->regL_hex_field, - ui->regPC_hex_field, ui->regSW_hex_field, ui->regF_hex_field - }; - for (auto* field : hexFields) { - if (field) { - connect(field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - } - } - - // Connect binary register fields - QLineEdit* binFields[] = { - ui->regA_bin_field, ui->regB_bin_field, ui->regX_bin_field, - ui->regS_bin_field, ui->regT_bin_field, ui->regL_bin_field, - ui->regPC_bin_field, ui->regSW_bin_field, ui->regF_bin_field - }; - for (auto* field : binFields) { - if (field) { - connect(field, &QLineEdit::editingFinished, this, &MainWindow::onRegisterFieldChanged); - } - } -} - -void MainWindow::onRegisterFieldChanged() -{ - if (!m_machine) return; - - QLineEdit* field = qobject_cast(sender()); - if (!field) return; - - QString objectName = field->objectName(); - QString regName = objectName.split('_')[0]; - - - if (regName == "regF") { - handleFloatRegisterFieldChanged(field, objectName); - return; - } - - // Handle integer registers - int value = 0; - bool ok = false; - - // Parse value based on field type - if (objectName.contains("_dec_field")) { - value = field->text().toInt(&ok); - } else if (objectName.contains("_hex_field")) { - QString hexText = field->text(); - // Remove 0x prefix if present - if (hexText.startsWith("0x", Qt::CaseInsensitive)) { - hexText = hexText.mid(2); - } - value = hexText.toInt(&ok, 16); - - if (ok && (regName == "regA" || regName == "regB" || regName == "regX" || - regName == "regS" || regName == "regT")) { - if (value > 0x7FFFFF) { - value = value - 0x1000000; - } - } - } else if (objectName.contains("_bin_field")) { - value = field->text().toInt(&ok, 2); - - if (ok && (regName == "regA" || regName == "regB" || regName == "regX" || - regName == "regS" || regName == "regT")) { - if (value > 0x7FFFFF) { - value = value - 0x1000000; - } - } - } - - if (!ok) { - - updateRegisterDisplays(); - return; - } - - if (regName == "regA") { - m_machine->setA(value); - updateAllFormatsForRegister("regA", m_machine->getA()); - } else if (regName == "regB") { - m_machine->setB(value); - updateAllFormatsForRegister("regB", m_machine->getB()); - } else if (regName == "regX") { - m_machine->setX(value); - updateAllFormatsForRegister("regX", m_machine->getX()); - } else if (regName == "regS") { - m_machine->setS(value); - updateAllFormatsForRegister("regS", m_machine->getS()); - } else if (regName == "regT") { - m_machine->setT(value); - updateAllFormatsForRegister("regT", m_machine->getT()); - } else if (regName == "regL") { - m_machine->setL(value); - updateAllFormatsForRegister("regL", m_machine->getL()); - } else if (regName == "regPC") { - m_machine->setPC(value); - updateAllFormatsForRegister("regPC", m_machine->getPC()); - } else if (regName == "regSW") { - m_machine->setSW(value); - updateAllFormatsForRegister("regSW", m_machine->getSW()); - } -} - -void MainWindow::handleFloatRegisterFieldChanged(QLineEdit* field, const QString& objectName) -{ - double value = 0.0; - bool ok = false; - - if (objectName.contains("_dec_field")) { - value = field->text().toDouble(&ok); - } else if (objectName.contains("_hex_field")) { - QString hexText = field->text(); - if (hexText.startsWith("0x", Qt::CaseInsensitive)) { - hexText = hexText.mid(2); - } - - uint64_t intValue = hexText.toULongLong(&ok, 16); - if (ok) { - intValue &= 0xFFFFFFFFFFFFULL; - double* floatPtr = reinterpret_cast(&intValue); - value = *floatPtr; - } - } else if (objectName.contains("_bin_field")) { - uint64_t intValue = field->text().toULongLong(&ok, 2); - if (ok) { - intValue &= 0xFFFFFFFFFFFFULL; - double* floatPtr = reinterpret_cast(&intValue); - value = *floatPtr; - } - } - - if (!ok) { - updateRegisterDisplays(); - return; - } - - m_machine->setF(value); - updateFloatRegisterFormats("regF", m_machine->getF()); -} - -void MainWindow::setTestRegisterValues() -{ - if (!m_machine) return; - - // Set some test values to demonstrate the register updating - m_machine->setA(12345); // Decimal: 12345, Hex: 0x003039, Binary: 000000011000000111001 - m_machine->setB(-1000); // Negative value to test signed representation - m_machine->setX(0xABCDEF); // Hex value to test various formats - m_machine->setS(255); // Simple power of 2 minus 1 - m_machine->setT(0x7FFFFF); // Maximum positive 24-bit value - - // Update all displays - updateRegisterDisplays(); -} - -void MainWindow::startExecution() -{ - if (m_controller) { - m_controller->start(); - } -} - -void MainWindow::stopExecution() -{ - if (m_controller) { - m_controller->stop(); - } -} - -void MainWindow::stepExecution() -{ - if (m_controller) { - m_controller->step(); - } -} - -void MainWindow::loadDemoProgram() -{ - if (!m_machine) return; - - // Load the instruction set first - loadInstructionSet(); - - qDebug() << "Loading SIC/XE Demo Program: Array Sum with Indirect Addressing"; - - // Memory layout - const int ARRAY_ADDR = 0x100; // Array of 3 numbers - const int PTR_ADDR = 0x200; // Pointer to array - const int SUM_ADDR = 0x300; // Result storage - const int COUNTER_ADDR = 0x310; // Loop counter - - // Initialize array with values: 10, 20, 30 - m_machine->setWord(ARRAY_ADDR, 10); - m_machine->setWord(ARRAY_ADDR + 3, 20); - m_machine->setWord(ARRAY_ADDR + 6, 30); - - // Initialize pointer to point to array - m_machine->setWord(PTR_ADDR, ARRAY_ADDR); - - // Initialize counter to 3 - m_machine->setWord(COUNTER_ADDR, 3); - - // Initialize sum to 0 - m_machine->setWord(SUM_ADDR, 0); - - int addr = 0x00; - - // Program: Sum array elements using indirect addressing - // 0x00: LDA #0 ; Initialize accumulator to 0 - m_machine->setByte(addr++, 0x01); // LDA with immediate (n=0,i=1) - m_machine->setByte(addr++, 0x00); - m_machine->setByte(addr++, 0x00); - - // 0x03: STA SUM_ADDR ; Store 0 in SUM - m_machine->setByte(addr++, 0x0F); // STA - m_machine->setByte(addr++, (SUM_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, SUM_ADDR & 0xFF); - - // 0x06: LDX #0 ; Initialize index to 0 - m_machine->setByte(addr++, 0x05); // LDX with immediate - m_machine->setByte(addr++, 0x00); - m_machine->setByte(addr++, 0x00); - - // LOOP (0x09): - const int LOOP_START = addr; - - // 0x09: LDA @PTR_ADDR ; Load value indirectly through pointer - m_machine->setByte(addr++, 0x02); // LDA with indirect (n=1,i=0) - m_machine->setByte(addr++, (PTR_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, PTR_ADDR & 0xFF); - - // 0x0C: ADD SUM_ADDR ; Add to sum - m_machine->setByte(addr++, 0x1B); // ADD - m_machine->setByte(addr++, (SUM_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, SUM_ADDR & 0xFF); - - // 0x0F: STA SUM_ADDR ; Store result back - m_machine->setByte(addr++, 0x0F); // STA - m_machine->setByte(addr++, (SUM_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, SUM_ADDR & 0xFF); - - // 0x12: LDA PTR_ADDR ; Load current pointer value - m_machine->setByte(addr++, 0x03); // LDA - m_machine->setByte(addr++, (PTR_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, PTR_ADDR & 0xFF); - - // 0x15: ADD #3 ; Add 3 to move to next array element - m_machine->setByte(addr++, 0x19); // ADD with immediate - m_machine->setByte(addr++, 0x00); - m_machine->setByte(addr++, 0x03); - - // 0x18: STA PTR_ADDR ; Store updated pointer - m_machine->setByte(addr++, 0x0F); // STA - m_machine->setByte(addr++, (PTR_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, PTR_ADDR & 0xFF); - - // 0x1B: LDA COUNTER_ADDR ; Load counter - m_machine->setByte(addr++, 0x03); // LDA - m_machine->setByte(addr++, (COUNTER_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, COUNTER_ADDR & 0xFF); - - // 0x1E: ADD #-1 ; Decrement counter (add -1) - m_machine->setByte(addr++, 0x19); // ADD with immediate - m_machine->setByte(addr++, 0x0F); // -1 in 12-bit two's complement - m_machine->setByte(addr++, 0xFF); - - // 0x21: STA COUNTER_ADDR ; Store counter - m_machine->setByte(addr++, 0x0F); // STA - m_machine->setByte(addr++, (COUNTER_ADDR >> 8) & 0xFF); - m_machine->setByte(addr++, COUNTER_ADDR & 0xFF); - - // 0x24: COMP #0 ; Compare with 0 - m_machine->setByte(addr++, 0x29); // COMP with immediate - m_machine->setByte(addr++, 0x00); - m_machine->setByte(addr++, 0x00); - - // 0x27: JGT LOOP ; Jump if greater than 0 - m_machine->setByte(addr++, 0x37); // JGT - m_machine->setByte(addr++, (LOOP_START >> 8) & 0xFF); - m_machine->setByte(addr++, LOOP_START & 0xFF); - - // 0x2A: J 0x2A ; Infinite loop (halt) - m_machine->setByte(addr++, 0x3F); // J - m_machine->setByte(addr++, 0x00); - m_machine->setByte(addr++, 0x2A); - - // Set PC to start of program - m_machine->setPC(0x00); - - qDebug() << "Program loaded:"; - qDebug() << " Array at 0x" << QString::number(ARRAY_ADDR, 16).toUpper() << " = [10, 20, 30]"; - qDebug() << " Pointer at 0x" << QString::number(PTR_ADDR, 16).toUpper(); - qDebug() << " Sum will be stored at 0x" << QString::number(SUM_ADDR, 16).toUpper(); - qDebug() << " Expected result: 60 (0x3C)"; -} - -void MainWindow::setupMemoryDisplay() -{ - // Set the title - ui->MemorygroupBox->setTitle("Memory (RAM)"); -} - -void MainWindow::onMemoryInc256() -{ - m_memoryOffset += 256; - if (m_memoryOffset > 1048576 - 256) { - m_memoryOffset = 1048576 - 256; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryInc4096() -{ - m_memoryOffset += 4096; - if (m_memoryOffset > 1048576 - 256) { - m_memoryOffset = 1048576 - 256; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryInc65536() -{ - m_memoryOffset += 65536; - if (m_memoryOffset > 1048576 - 256) { - m_memoryOffset = 1048576 - 256; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryDec256() -{ - m_memoryOffset -= 256; - if (m_memoryOffset < 0) { - m_memoryOffset = 0; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryDec4096() -{ - m_memoryOffset -= 4096; - if (m_memoryOffset < 0) { - m_memoryOffset = 0; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryDec65536() -{ - m_memoryOffset -= 65536; - if (m_memoryOffset < 0) { - m_memoryOffset = 0; - } - updateMemoryDisplay(); -} - -void MainWindow::onMemoryGoToStart() -{ - m_memoryOffset = 0; - updateMemoryDisplay(); -} - -void MainWindow::onMemoryGoToEnd() -{ - m_memoryOffset = 1048576 - 256; - updateMemoryDisplay(); -} - -void MainWindow::setupDisassemblyDisplay() -{ - ui->MemorygroupBox_3->setTitle("Disassembly"); -} - -void MainWindow::onDisassemblyInc() -{ - // Move forward by 1 instruction - auto instr = disassembleAt(m_disassemblyOffset); - m_disassemblyOffset += instr.size; - if (m_disassemblyOffset > 1048576 - 16) { - m_disassemblyOffset = 1048576 - 16; - } - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyInc16() -{ - // Move forward by 16 instructions - for (int i = 0; i < 16 && m_disassemblyOffset < 1048576 - 16; i++) { - auto instr = disassembleAt(m_disassemblyOffset); - m_disassemblyOffset += instr.size; - } - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyInc256() -{ - // Move forward by 256 instructions - for (int i = 0; i < 256 && m_disassemblyOffset < 1048576 - 16; i++) { - auto instr = disassembleAt(m_disassemblyOffset); - m_disassemblyOffset += instr.size; - } - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyDec() -{ - // Move back by trying to find previous instruction (assume max 4 bytes) - m_disassemblyOffset = std::max(0, m_disassemblyOffset - 4); - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyDec16() -{ - // Move back by approximately 16 instructions (16*3 = 48 bytes avg) - m_disassemblyOffset = std::max(0, m_disassemblyOffset - 48); - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyDec256() -{ - // Move back by approximately 256 instructions (256*3 = 768 bytes avg) - m_disassemblyOffset = std::max(0, m_disassemblyOffset - 768); - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyGoToStart() -{ - m_disassemblyOffset = 0; - updateDisassemblyDisplay(); -} - -void MainWindow::onDisassemblyGoToEnd() -{ - m_disassemblyOffset = std::max(0, 1048576 - 1024); - updateDisassemblyDisplay(); -} - -MainWindow::DisassembledInstruction MainWindow::disassembleAt(int address) -{ - DisassembledInstruction result; - result.address = address; - result.size = 1; - result.mnemonic = "???"; - result.operand = ""; - result.effectiveAddr = -1; - result.isImmediate = false; - result.isIndirect = false; - - if (address >= 1048576) { - return result; - } - - int byte1 = m_machine->getByte(address); - int opcode = byte1 & 0xFC; // Mask off lower 2 bits (n, i flags) - - if (opcode >= 0xff || instructions[opcode].type == InstructionType::INVALID) { - result.mnemonic = QString("BYTE 0x%1").arg(byte1, 2, 16, QChar('0')).toUpper(); - return result; - } - - result.mnemonic = QString(instructions[opcode].name); - - switch (instructions[opcode].type) { - case InstructionType::TYPE1: - result.size = 1; - break; - - case InstructionType::TYPE2: { - result.size = 2; - if (address + 1 < 1048576) { - int byte2 = m_machine->getByte(address + 1); - int r1 = (byte2 >> 4) & 0xF; - int r2 = byte2 & 0xF; - - const char* regNames[] = {"A", "X", "L", "B", "S", "T", "F", "?", "PC", "SW"}; - QString reg1Str = (r1 < 10) ? regNames[r1] : "?"; - QString reg2Str = (r2 < 10) ? regNames[r2] : "?"; - - result.operand = QString("%1, %2").arg(reg1Str).arg(reg2Str); - } - break; - } - - case InstructionType::TYPE3_4: { - if (address + 2 >= 1048576) { - result.size = 3; - break; - } - - int byte2 = m_machine->getByte(address + 1); - int byte3 = m_machine->getByte(address + 2); - - int ni = (byte1 >> 0) & 0x3; - int x = (byte2 >> 7) & 0x1; - int b = (byte2 >> 6) & 0x1; - int p = (byte2 >> 5) & 0x1; - int e = (byte2 >> 4) & 0x1; - - if (e) { - // Format 4 - add + prefix to mnemonic - result.mnemonic = "+" + result.mnemonic; - result.size = 4; - if (address + 3 < 1048576) { - int byte4 = m_machine->getByte(address + 3); - int addr = ((byte2 & 0xF) << 16) | (byte3 << 8) | byte4; - - result.isImmediate = (ni == 0x1); - result.isIndirect = (ni == 0x2); - - if (!result.isImmediate) { - result.effectiveAddr = addr; - } - - QString prefix = ""; - if (ni == 0x1) prefix = "#"; // Immediate - else if (ni == 0x2) prefix = "@"; // Indirect - - result.operand = QString("%1%2").arg(prefix).arg(addr, 5, 16, QChar('0')).toUpper(); - if (x) result.operand += ",X"; - } - } else { - result.size = 3; - int disp = ((byte2 & 0xF) << 8) | byte3; - - if (disp & 0x800) { - disp |= 0xFFFFF000; - } - - result.isImmediate = (ni == 0x1); - result.isIndirect = (ni == 0x2); - - QString prefix = ""; - if (ni == 0x1) prefix = "#"; // Immediate - else if (ni == 0x2) prefix = "@"; // Indirect - - if (ni == 0x1 && !p && !b) { - result.operand = QString("#%1").arg(disp & 0xFFF); - } else { - // Calculate effective address for display - int ea = disp; - QString addrMode = ""; - - if (p) { - ea += m_machine->getPC(); - addrMode = " (PC)"; - } else if (b) { - ea += m_machine->getB(); - addrMode = " (B)"; - } - - if (!result.isImmediate && !x) { - result.effectiveAddr = ea & 0xFFFFF; - } - - result.operand = QString("%1%2%3").arg(prefix).arg(ea & 0xFFFFF, 4, 16, QChar('0')).toUpper().arg(addrMode); - if (x) result.operand += ",X"; - } - } - break; - } - - default: - break; - } - - return result; -} - -void MainWindow::updateDisassemblyDisplay() -{ - if (!m_machine) return; - - QWidget* container = new QWidget(); - QVBoxLayout* layout = new QVBoxLayout(container); - layout->setSpacing(1); - layout->setContentsMargins(5, 5, 5, 5); - - QFont monoFont("Courier New"); - monoFont.setPointSize(9); - - // Header - QString headerText = QString("Address Mnemonic Operand *var **var"); - QLabel* header = new QLabel(headerText); - QFont headerFont = monoFont; - headerFont.setBold(true); - header->setFont(headerFont); - layout->addWidget(header); - - int pc = m_machine->getPC(); - int currentAddr = m_disassemblyOffset; - - // Disassemble up to 255 instructions - for (int i = 0; i < 255 && currentAddr < 1048576; i++) { - auto instr = disassembleAt(currentAddr); - - QString varCol = ""; - QString varVar = ""; - - // *var column - show value at effective address (if not immediate) - if (instr.effectiveAddr >= 0 && instr.effectiveAddr < 1048576) { - int value = m_machine->getWord(instr.effectiveAddr); - varCol = QString("0x%1").arg(value & 0xFFFFFF, 6, 16, QChar('0')).toUpper(); - - // **var column - if indirect (@), dereference again - if (instr.isIndirect && value >= 0 && value < 1048576) { - int derefValue = m_machine->getWord(value); - varVar = QString("0x%1").arg(derefValue & 0xFFFFFF, 6, 16, QChar('0')).toUpper(); - } - } - - QString line = QString("0x%1 %2 %3 %4 %5") - .arg(instr.address, 5, 16, QChar('0')).toUpper() - .arg(instr.mnemonic, -9) - .arg(instr.operand, -14) - .arg(varCol, -9) - .arg(varVar, -9); - - QLabel* instrLine = new QLabel(line); - instrLine->setFont(monoFont); - - // Highlight current PC - if (pc == instr.address) { - instrLine->setStyleSheet("background-color: #FFFF99; font-weight: bold;"); - } - - layout->addWidget(instrLine); - currentAddr += instr.size; - } - - layout->addStretch(); - container->setLayout(layout); - - ui->DisasemblyScrollArea->setWidget(container); -} - -void MainWindow::updateMemoryDisplay() -{ - if (!m_machine) return; - - // Create a widget to hold the memory display - QWidget* container = new QWidget(); - QVBoxLayout* layout = new QVBoxLayout(container); - layout->setSpacing(1); - layout->setContentsMargins(5, 5, 5, 5); - - // Create monospace font for memory display - QFont monoFont("Courier New"); - monoFont.setPointSize(9); - - // Header with current offset range - QString headerText = QString("Address Hex Value Char [0x%1 - 0x%2]") - .arg(m_memoryOffset, 5, 16, QChar('0')).toUpper() - .arg(m_memoryOffset + 255, 5, 16, QChar('0')).toUpper(); - QLabel* header = new QLabel(headerText); - QFont headerFont = monoFont; - headerFont.setBold(true); - header->setFont(headerFont); - layout->addWidget(header); - - // Get PC for highlighting - int pc = m_machine->getPC(); - - // Display memory byte by byte - ONLY 256 bytes from current offset - for (int i = 0; i < 256; i++) { - int addr = m_memoryOffset + i; - int byte = m_machine->getByte(addr); - - QString addressStr = QString("0x%1").arg(addr, 5, 16, QChar('0')).toUpper(); - - // Hex value column - QString hexStr = QString("0x%1").arg(byte, 2, 16, QChar('0')).toUpper(); - - // Char representation - QString charStr; - if (byte >= 32 && byte <= 126) { - charStr = QChar(byte); - } else { - charStr = '.'; - } - - QString line = QString("%1 %2 %3") - .arg(addressStr, -12) - .arg(hexStr, -12) - .arg(charStr); - - QLabel* memLine = new QLabel(line); - memLine->setFont(monoFont); - - // Highlight the current PC address - if (pc == addr) { - memLine->setStyleSheet("background-color: #FFFF99; font-weight: bold;"); - } - - layout->addWidget(memLine); - } - - layout->addStretch(); - container->setLayout(layout); - - ui->MemoryScrollArea->setWidget(container); -} diff --git a/simulator_SIC_XE/gui/qt/mainwindow.h b/simulator_SIC_XE/gui/qt/mainwindow.h deleted file mode 100644 index 1e39a7d..0000000 --- a/simulator_SIC_XE/gui/qt/mainwindow.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include - -class MachineController; -class Machine; -class QLineEdit; - -namespace Ui { -class MainWindow; -} - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - - std::shared_ptr machine() const { return m_machine; } - MachineController* controller() const { return m_controller.get(); } - - void startExecution(); - void stopExecution(); - void stepExecution(); - - void setTestRegisterValues(); - -private slots: - void updateRegisterDisplays(); - void updateMemoryDisplay(); - void updateDisassemblyDisplay(); - void onRegisterFieldChanged(); - void onMemoryInc256(); - void onMemoryInc4096(); - void onMemoryInc65536(); - void onMemoryDec256(); - void onMemoryDec4096(); - void onMemoryDec65536(); - void onMemoryGoToStart(); - void onMemoryGoToEnd(); - void onDisassemblyInc(); - void onDisassemblyInc16(); - void onDisassemblyInc256(); - void onDisassemblyDec(); - void onDisassemblyDec16(); - void onDisassemblyDec256(); - void onDisassemblyGoToStart(); - void onDisassemblyGoToEnd(); - -private: - Ui::MainWindow *ui; - std::shared_ptr m_machine; - std::unique_ptr m_controller; - int m_memoryOffset = 0; - int m_disassemblyOffset = 0; - - void connectRegisterFields(); - void updateSingleRegisterDisplay(const QString& fieldName, int value); - void updateAllFormatsForRegister(const QString& regPrefix, int value); - void updateFloatRegisterFormats(const QString& regPrefix, double value); - void handleFloatRegisterFieldChanged(QLineEdit* field, const QString& objectName); - void loadDemoProgram(); - void setupMemoryDisplay(); - void setupDisassemblyDisplay(); - - struct DisassembledInstruction { - int address; - int size; - QString mnemonic; - QString operand; - int effectiveAddr; - bool isImmediate; - bool isIndirect; - }; - DisassembledInstruction disassembleAt(int address); -}; - -#endif // MAINWINDOW_H diff --git a/simulator_SIC_XE/gui/qt/mainwindow.ui b/simulator_SIC_XE/gui/qt/mainwindow.ui deleted file mode 100644 index 2fad622..0000000 --- a/simulator_SIC_XE/gui/qt/mainwindow.ui +++ /dev/null @@ -1,883 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 1172 - 649 - - - - MainWindow - - - - - - 10 - 0 - 431 - 601 - - - - - - 0 - 80 - 431 - 321 - - - - Register values - - - - - 70 - 40 - 113 - 23 - - - - - - - 10 - 40 - 57 - 20 - - - - - 10 - - - - Reg A - - - - - - 190 - 40 - 113 - 23 - - - - - - - 310 - 40 - 113 - 23 - - - - - - - 110 - 20 - 57 - 20 - - - - - 10 - - - - Bin - - - - - - 230 - 20 - 57 - 20 - - - - - 10 - - - - Hex - - - - - - 350 - 20 - 57 - 20 - - - - - 10 - - - - Dec - - - - - - 310 - 70 - 113 - 23 - - - - - - - 10 - 70 - 57 - 20 - - - - - 10 - - - - Reg B - - - - - - 190 - 70 - 113 - 23 - - - - - - - 70 - 70 - 113 - 23 - - - - - - - 310 - 100 - 113 - 23 - - - - - - - 10 - 100 - 57 - 20 - - - - - 10 - - - - Reg X - - - - - - 190 - 100 - 113 - 23 - - - - - - - 70 - 100 - 113 - 23 - - - - - - - 310 - 130 - 113 - 23 - - - - - - - 10 - 130 - 57 - 20 - - - - - 10 - - - - Reg S - - - - - - 190 - 130 - 113 - 23 - - - - - - - 70 - 130 - 113 - 23 - - - - - - - 310 - 160 - 113 - 23 - - - - - - - 10 - 160 - 57 - 20 - - - - - 10 - - - - Reg T - - - - - - 190 - 160 - 113 - 23 - - - - - - - 70 - 160 - 113 - 23 - - - - - - - 190 - 190 - 113 - 23 - - - - - - - 70 - 190 - 113 - 23 - - - - - - - 10 - 190 - 57 - 20 - - - - - 10 - - - - Reg L - - - - - - 310 - 190 - 113 - 23 - - - - - - - 10 - 220 - 57 - 20 - - - - - 10 - - - - Reg PC - - - - - - 310 - 220 - 113 - 23 - - - - - - - 70 - 220 - 113 - 23 - - - - - - - 190 - 220 - 113 - 23 - - - - - - - 10 - 249 - 57 - 20 - - - - - 10 - - - - Reg SW - - - - - - 310 - 249 - 113 - 23 - - - - - - - 70 - 249 - 113 - 23 - - - - - - - 190 - 249 - 113 - 23 - - - - - - - 10 - 280 - 57 - 20 - - - - - 10 - - - - Reg L - - - - - - 310 - 280 - 113 - 23 - - - - - - - 70 - 280 - 113 - 23 - - - - - - - 190 - 280 - 113 - 23 - - - - - - - - 0 - 0 - 431 - 81 - - - - Control - - - - - 30 - 40 - 80 - 23 - - - - Start - - - - - - 170 - 40 - 80 - 23 - - - - Stop - - - - - - 310 - 40 - 80 - 23 - - - - Step - - - - - - - - 450 - 0 - 721 - 601 - - - - - - 0 - 0 - 711 - 291 - - - - Memory - - - - - 0 - 20 - 711 - 221 - - - - true - - - - - 0 - 0 - 709 - 219 - - - - - - - - 450 - 250 - 71 - 23 - - - - >> - - - - - - 370 - 250 - 71 - 23 - - - - > - - - - - - 530 - 250 - 71 - 23 - - - - >>> - - - - - - 290 - 250 - 71 - 23 - - - - < - - - - - - 210 - 250 - 71 - 23 - - - - << - - - - - - 130 - 250 - 71 - 21 - - - - <<< - - - - - - 50 - 250 - 71 - 21 - - - - O - - - - - - 610 - 250 - 71 - 21 - - - - | - - - - - - - 0 - 300 - 711 - 301 - - - - Disasembly - - - - - 0 - 20 - 711 - 221 - - - - true - - - - - 0 - 0 - 709 - 219 - - - - - - - - 440 - 250 - 71 - 23 - - - - >> - - - - - - 360 - 250 - 71 - 23 - - - - > - - - - - - 520 - 250 - 71 - 23 - - - - >>> - - - - - - 280 - 250 - 71 - 23 - - - - < - - - - - - 200 - 250 - 71 - 23 - - - - << - - - - - - 120 - 250 - 71 - 21 - - - - <<< - - - - - - 40 - 250 - 71 - 21 - - - - O - - - - - - 600 - 250 - 71 - 21 - - - - | - - - - - - - - - 0 - 0 - 1172 - 20 - - - - - - - - diff --git a/simulator_SIC_XE/include/constants.h b/simulator_SIC_XE/include/constants.h deleted file mode 100644 index 6f2195a..0000000 --- a/simulator_SIC_XE/include/constants.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CONSTANTS_H -#define CONSTANTS_H - -#include -// ============================== -// SIC/XE Architecture Constants -// ============================== - -// Memory and system constants -constexpr int MEMORY_SIZE = 1 << 20; // 1 MB memory -constexpr int NUM_DEVICES = 256; -constexpr int WORD_SIZE = 24; -constexpr int WORD_MASK = 0xFFFFFF; - -// SIC/XE floating point constants -constexpr int SICF_BITS = 48; -constexpr int SICF_FRAC_BITS = 40; -constexpr int SICF_EXP_BITS = 7; -constexpr int SICF_EXP_BIAS = 64; -constexpr unsigned long long SICF_FRAC_MASK = (1ULL << SICF_FRAC_BITS) - 1; - -// SW register condition codes -constexpr int CC_LT = 0x0; // 00 -constexpr int CC_EQ = 0x1; // 01 -constexpr int CC_GT = 0x2; // 10 -constexpr int CC_MASK = 0x3; // mask for 2 bits - -// Instruction format bit masks -constexpr int TYPE3_4_SIC_MASK = 0xFC; -constexpr int NI_MASK = 0x03; // mask for n and i bits -constexpr int NI_SIC = 0x0; - -constexpr int BP_BASE_REL_MASK = 0b10; -constexpr int BP_PC_REL_MASK = 0b01; -constexpr int BP_DIRECT_MASK = 0b00; - -constexpr int BIT_E_MASK = 0x10; // mask for e bit in F4 and F3 instructions - -//SIC/XE/XE -constexpr bool USE_EXTENDED_MODE = true; -constexpr int VECTOR_REG_SIZE = 4; - -/* if structure is -/target/ - |-> bin/simulator_exec - |-> res/ -*/ -// When running from project root (./target/bin/simulator_exec), resources are in ./target/res/ -constexpr char PATH_RESOURCES[] = "./target/res/"; -constexpr bool FILE_CONTAINS_WHITE_SPACES = true; - -#endif // CONSTANTS_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/file_reader.h b/simulator_SIC_XE/include/file_reader.h deleted file mode 100644 index 87b8a17..0000000 --- a/simulator_SIC_XE/include/file_reader.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FILE_READER_H -#define FILE_READER_H - -#include "reader.h" -#include -#include - -class FileReader : public Reader { -public: - explicit FileReader(const std::string &path, std::ios::openmode m = std::ios::binary); - ~FileReader() override; - - int readByte() override; - - bool readBytes(uint8_t* buf, size_t len) override; - std::string readString(size_t len) override; - std::string readLine() override; - - bool good() const; - -private: - std::ifstream in; -}; - -#endif // FILE_READER_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/instructions.h b/simulator_SIC_XE/include/instructions.h index 5bef303..ff2e532 100644 --- a/simulator_SIC_XE/include/instructions.h +++ b/simulator_SIC_XE/include/instructions.h @@ -1,26 +1,11 @@ #ifndef INSTRUCTIONS_H #define INSTRUCTIONS_H -#include "utils.h" - -class Machine; // forward declaration - -// Type 1 instruction handlers -void fix_handler(Machine& m); -void float_handler(Machine& m); -void hio_handler(Machine& m); -void norm_handler(Machine& m); -void sio_handler(Machine& m); -void tio_handler(Machine& m); -void nop_handler(Machine& m); - -/* IDEJE ZA SIC_XE_XE :)*/ -// void nop(Machine& m); +#include "opcode.h" // Type 2 instruction handlers void addr_handler(Machine& m, int r1, int r2); void clear_handler(Machine& m, int r, int unused); -void compr_handler(Machine& m, int r1, int r2); void divr_handler(Machine& m, int r1, int r2); void mulr_handler(Machine& m, int r1, int r2); void rmo_handler(Machine& m, int r1, int r2); @@ -31,71 +16,5 @@ void svc_handler(Machine& m, int n, int unused); void tixr_handler(Machine& m, int r1, int unused); -// Type 3/4 instruction handlers -void add_handler(Machine& m, int ea, AddressingMode mode); -void addf_handler(Machine& m, int ea, AddressingMode mode); -void and_handler(Machine& m, int ea, AddressingMode mode); -void comp_handler(Machine& m, int ea, AddressingMode mode); -void compf_handler(Machine& m, int ea, AddressingMode mode); -void div_handler(Machine& m, int ea, AddressingMode mode); -void divf_handler(Machine& m, int ea, AddressingMode mode); -void j_handler(Machine& m, int ea, AddressingMode mode); -void jeq_handler(Machine& m, int ea, AddressingMode mode); -void jgt_handler(Machine& m, int ea, AddressingMode mode); -void jlt_handler(Machine& m, int ea, AddressingMode mode); -void jsub_handler(Machine& m, int ea, AddressingMode mode); -void lda_handler(Machine& m, int ea, AddressingMode mode); -void ldb_handler(Machine& m, int ea, AddressingMode mode); -void ldch_handler(Machine& m, int ea, AddressingMode mode); -void ldf_handler(Machine& m, int ea, AddressingMode mode); -void ldl_handler(Machine& m, int ea, AddressingMode mode); -void lds_handler(Machine& m, int ea, AddressingMode mode); -void ldt_handler(Machine& m, int ea, AddressingMode mode); -void ldx_handler(Machine& m, int ea, AddressingMode mode); -void lps_handler(Machine& m, int ea, AddressingMode mode); -void mul_handler(Machine& m, int ea, AddressingMode mode); -void mulf_handler(Machine& m, int ea, AddressingMode mode); -void or_handler(Machine& m, int ea, AddressingMode mode); -void rd_handler(Machine& m, int ea, AddressingMode mode); -void rsub_handler(Machine& m, int ea, AddressingMode mode); -void ssk_handler(Machine& m, int ea, AddressingMode mode); -void sta_handler(Machine& m, int ea, AddressingMode mode); -void stb_handler(Machine& m, int ea, AddressingMode mode); -void stch_handler(Machine& m, int ea, AddressingMode mode); -void stf_handler(Machine& m, int ea, AddressingMode mode); -void sti_handler(Machine& m, int ea, AddressingMode mode); -void stl_handler(Machine& m, int ea, AddressingMode mode); -void sts_handler(Machine& m, int ea, AddressingMode mode); -void stsw_handler(Machine& m, int ea, AddressingMode mode); -void stt_handler(Machine& m, int ea, AddressingMode mode); -void stx_handler(Machine& m, int ea, AddressingMode mode); -void sub_handler(Machine& m, int ea, AddressingMode mode); -void subf_handler(Machine& m, int ea, AddressingMode mode); -void td_handler(Machine& m, int ea, AddressingMode mode); -void tix_handler(Machine& m, int ea, AddressingMode mode); -void wd_handler(Machine& m, int ea, AddressingMode mode); - - -// SIC/XE/XE Extended instruction handlers -void xexe_handler(Machine& m); -void halt_handler(Machine& m); -void nop_handler(Machine& m); - -void vaddr_handler(Machine& m, int r1, int r2); -void vsubr_handler(Machine& m, int r1, int r2); -void vmulr_handler(Machine& m, int r1, int r2); -void vdivr_handler(Machine& m, int r1, int r2); - -void vadd_handler(Machine& m, int ea, AddressingMode mode); -void vsub_handler(Machine& m, int ea, AddressingMode mode); -void vmul_handler(Machine& m, int ea, AddressingMode mode); -void vdiv_handler(Machine& m, int ea, AddressingMode mode); -void stva_handler(Machine& m, int ea, AddressingMode mode); -void stvs_handler(Machine& m, int ea, AddressingMode mode); -void stvt_handler(Machine& m, int ea, AddressingMode mode); -void ldva_handler(Machine& m, int ea, AddressingMode mode); -void ldvs_handler(Machine& m, int ea, AddressingMode mode); -void ldvt_handler(Machine& m, int ea, AddressingMode mode); - #endif // INSTRUCTIONS_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/loader.h b/simulator_SIC_XE/include/loader.h deleted file mode 100644 index 41899c2..0000000 --- a/simulator_SIC_XE/include/loader.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef LOADER_H -#define LOADER_H - -#include -#include -#include -#include "file_reader.h" -#include - -class Machine; - -using std::shared_ptr; -using std::string; - - -class Loader { -public: - Loader( shared_ptr machine, string filename) : _machine(machine), _filename(filename) { - _file_reader = std::make_shared(filename, std::ios::in); - if (!_file_reader->good()) { - throw std::runtime_error("Loader: failed to open file: " + filename); - } - } - ~Loader(); - - - enum class RecordType { - HEADER, - TEXT, - END, - UNKNOWN - }; - - struct HeaderMetadata { - string program_name; - int start_address; - int length; - }; - struct TextRecord { - int start_address; - std::vector data; - }; - struct EndRecord { - int execution_start_address; - }; - - void load(); - -private : - - static RecordType parseRecordType(char c); - - - shared_ptr _machine; - string _filename; - shared_ptr _file_reader; - HeaderMetadata readHeader(); - TextRecord readTextRecord(); - EndRecord readEndRecord(); - bool load_into_memory(int start_address, const std::vector& data); - -}; - - - - - -#endif // LOADER_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/machine.h b/simulator_SIC_XE/include/machine.h index 8e80669..e0920da 100644 --- a/simulator_SIC_XE/include/machine.h +++ b/simulator_SIC_XE/include/machine.h @@ -4,18 +4,18 @@ #include #include #include -#include -#include -#include - -#include "constants.h" #include "device.h" #include "input_device.h" #include "output_device.h" #include "file_device.h" #include "opcode.h" -#include "utils.h" + +#include + +#define MEMORY_SIZE 65536 +#define NUM_DEVICES 256 + using std::string; using std::cerr; @@ -26,32 +26,30 @@ using std::cout; class Machine { public: Machine(); - Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; _instructionsTable = instructions; } ~Machine(); + // Accessor methods for registers int getA() const { return A; } - void setA(int value) { A = toSIC24(value); } + void setA(int value) { A = value; } int getB() const { return B; } - void setB(int value) { B = toSIC24(value); } + void setB(int value) { B = value; } int getX() const { return X; } - void setX(int value) { X = toSIC24(value); } + void setX(int value) { X = value; } int getL() const { return L; } - void setL(int value) { L = toSIC24(value); } + void setL(int value) { L = value; } int getS() const { return S; } - void setS(int value) { S = toSIC24(value); } + void setS(int value) { S = value; } int getT() const { return T; } - void setT(int value) { T = toSIC24(value); } + void setT(int value) { T = value; } - // PC is an address → don't mask to 24 unless you want 24-bit addressing int getPC() const { return PC; } void setPC(int value) { PC = value; } - // status word: keep as-is int getSW() const { return SW; } void setSW(int value) { SW = value; } @@ -78,17 +76,14 @@ public: // Set a file device at index `num` using the provided filename. void setFileDevice(int num, const std::string &filename); + // Fetch and execute instructions int fetch(); void execute(); - // Execution and speed control - int getSpeed() const; - void setSpeed(int kHz); - void start(); - void stop(); - void tick(); - void halt(); + bool execF1(int opcode); + bool execF2(int opcode, int operand); + bool execSICF3F4(int opcode, int ni, int operand); // error handling methods void notImplemented(string mnemonic); @@ -97,22 +92,6 @@ public: void divisionByZero(int opcode); void undefinedHandler(int opcode); - bool getExtendedMode() const { return _exex_mode; } - void enableExtendedMode(); - void disableExtendedMode(); - - - int* getVectorRegister(int regNum); - void setVectorRegister(int regNum, const int* values); - - const int* getVA() const { return VA; } - const int* getVS() const { return VS; } - const int* getVT() const { return VT; } - void setVA(const int* values); - void setVS(const int* values); - void setVT(const int* values); - - private: // registers int A, B, X, L, S, T, PC, SW; @@ -125,23 +104,42 @@ private: std::vector> devices; // fallback device returned when device slot is empty/invalid Device fallbackDevice; - - // Execution control - std::atomic running{false}; - std::atomic speedkHz{1}; // Default 1 kHz - - bool execF1(int opcode); - bool execF2(int opcode, int operand); - bool execSICF3F4(int opcode, int ni, int x, int b, int p, int e, int operand); - - - // Extended mode - bool _stopped{false}; - bool _exex_mode{false}; - InstructionInfo* _instructionsTable; - int VA[VECTOR_REG_SIZE], VS[VECTOR_REG_SIZE], VT[VECTOR_REG_SIZE]; // vector operation registers }; + // Convert integer to 24-bit signed SIC representation +inline int toSIC24(int value) { + value &= 0xFFFFFF; + if (value & 0x800000) { + value -= 0x1000000; + } + return value; +} + +inline int setCC(int sw, int cc) { + sw &= ~CC_MASK; + sw |= (cc & CC_MASK); + return sw; +} + +inline int sic_comp(int a, int b, int sw) { + int sa = toSIC24(a); + int sb = toSIC24(b); + + int cc; + if (sa < sb) { + cc = CC_LT; + } else if (sa == sb) { + cc = CC_EQ; + } else { + cc = CC_GT; + } + + return setCC(sw, cc); +} + +inline int getCC(int sw) { + return sw & CC_MASK; +} #endif // MACHINE_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/opcode.h b/simulator_SIC_XE/include/opcode.h index a467488..93df629 100644 --- a/simulator_SIC_XE/include/opcode.h +++ b/simulator_SIC_XE/include/opcode.h @@ -1,8 +1,6 @@ #ifndef OPCODE_H #define OPCODE_H -#include "utils.h" - // ============================== // Opcode definitions (SIC/XE) // ============================== @@ -66,26 +64,13 @@ #define TIXR 0xB8 #define WD 0xDC -// ============================== -// Extended opcodes (SIC/XE/XE) -// ============================== -#define NOP 0xF1 -#define HALT 0xF2 -#define XEXE 0xEE // Enable extended mode -#define VADD 0x18 -#define VADDR 0x90 -#define VSUB 0x1C -#define VSUBR 0x94 -#define VMUL 0x20 -#define VMULR 0x98 -#define VDIV 0x24 -#define VDIVR 0x9C -#define STVA 0x0C -#define STVS 0x7C -#define STVT 0x84 -#define LDVA 0x00 -#define LDVS 0x68 -#define LDVT 0x04 + + +// SW register condition codes +constexpr int CC_LT = 0x0; // 00 +constexpr int CC_EQ = 0x1; // 01 +constexpr int CC_GT = 0x2; // 10 +constexpr int CC_MASK = 0x3; // mask for 2 bits @@ -108,7 +93,6 @@ struct InstructionInfo { }; extern InstructionInfo instructions[]; -extern InstructionInfo instructionsEXEX[]; // Initialize the instruction table void loadInstructionSet(); diff --git a/simulator_SIC_XE/include/reader.h b/simulator_SIC_XE/include/reader.h deleted file mode 100644 index e582161..0000000 --- a/simulator_SIC_XE/include/reader.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef READER_H -#define READER_H - -#include -#include - -// Abstract Reader class: read bytes/strings from a source (file, string, etc.) -class Reader { -public: - virtual ~Reader() = default; - // return 0..255 on success, -1 on EOF/error - virtual int readByte() = 0; - // read exactly len bytes into buf; return true on success - virtual bool readBytes(uint8_t* buf, size_t len) = 0; - // read up to len bytes into a std::string; may return shorter string on EOF - virtual std::string readString(size_t len) = 0; - // read a line (up to newline), return empty string on EOF - virtual std::string readLine() = 0; -}; - -#endif // READER_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/string_reader.h b/simulator_SIC_XE/include/string_reader.h deleted file mode 100644 index 71c3da9..0000000 --- a/simulator_SIC_XE/include/string_reader.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef STRING_READER_H -#define STRING_READER_H - -#include "reader.h" -#include -#include - -class StringReader : public Reader { -public: - explicit StringReader(const std::string &s); - ~StringReader() override; - - int readByte() override; - bool readBytes(uint8_t* buf, size_t len) override; - std::string readString(size_t len) override; - std::string readLine() override; - -private: - std::istringstream in; -}; - -#endif // STRING_READER_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/utils.h b/simulator_SIC_XE/include/utils.h deleted file mode 100644 index 3197a95..0000000 --- a/simulator_SIC_XE/include/utils.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include "constants.h" - -#include - -// ============================== -// SIC/XE Utility Functions -// ============================== - -// Instruction bit extraction utilities -inline int getXBit(int b2) { - return (b2 & 0x80) ? 1 : 0; -} - -inline int getBPBits(int b2) { - return (b2 >> 5) & 0x03; -} - -enum class AddressingMode { - IMMEDIATE, - INDIRECT, - SIMPLE, - SIC_DIRECT, - INVALID -}; - -// Get addressing mode from ni bits -AddressingMode getAddressingMode(int ni); - - -// convert to signed 24-bit integer -inline int toSIC24(int value) { - value &= 0xFFFFFF; - if (value & 0x800000) { - value -= 0x1000000; - } - return value; -} - -inline int setCC(int sw, int cc) { - sw &= ~CC_MASK; - sw |= (cc & CC_MASK); - return sw; -} - -inline int sic_comp(int a, int b, int sw) { - int sa = toSIC24(a); - int sb = toSIC24(b); - - int cc; - if (sa < sb) { - cc = CC_LT; - } else if (sa == sb) { - cc = CC_EQ; - } else { - cc = CC_GT; - } - - return setCC(sw, cc); -} - -inline int sic_comp(double a, double b, int sw) { - int cc; - if (a < b) { - cc = CC_LT; - } else if (a == b) { - cc = CC_EQ; - } else { - cc = CC_GT; - } - - return setCC(sw, cc); -} - - -inline int getCC(int sw) { - return sw & CC_MASK; -} - -inline double normaliseFloat(double value) -{ - if (value == 0.0 )return 0.0; - if (!std::isfinite(value)) return value; - double mantissa = value; - while (std::fabs(mantissa) >= 10.0) mantissa /= 10.0; - while (std::fabs(mantissa) < 1.0) mantissa *= 10.0; - return mantissa; -} - - - - -#endif // UTILS_H \ No newline at end of file diff --git a/simulator_SIC_XE/src/file_reader.cpp b/simulator_SIC_XE/src/file_reader.cpp deleted file mode 100644 index 2a800cc..0000000 --- a/simulator_SIC_XE/src/file_reader.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "file_reader.h" - -FileReader::FileReader(const std::string &path, std::ios::openmode m) - : in(path, m) -{} - -FileReader::~FileReader() = default; - -int FileReader::readByte() { - char c; - if (!in.get(c)) return -1; - return static_cast(c); -} - - -bool FileReader::readBytes(uint8_t* buf, size_t len) { - in.read(reinterpret_cast(buf), static_cast(len)); - return static_cast(in.gcount()) == len; -} - -std::string FileReader::readString(size_t len) { - std::string s; - s.resize(len); - in.read(reinterpret_cast(&s[0]), static_cast(len)); - std::streamsize got = in.gcount(); - if (static_cast(got) < len) s.resize(static_cast(got)); - return s; -} - -bool FileReader::good() const { return static_cast(in); } - -std::string FileReader::readLine() { - std::string s; - if (!std::getline(in, s)) return std::string(); - return s; -} diff --git a/simulator_SIC_XE/src/instructions.cpp b/simulator_SIC_XE/src/instructions.cpp index 9a88a68..364fed1 100644 --- a/simulator_SIC_XE/src/instructions.cpp +++ b/simulator_SIC_XE/src/instructions.cpp @@ -1,96 +1,16 @@ #include "instructions.h" #include "machine.h" -#include "utils.h" - -inline int resolveWordOperand(Machine& m, int ea, AddressingMode mode) -{ - switch (mode) - { - case AddressingMode::IMMEDIATE: return ea; - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: return m.getWord(ea); - case AddressingMode::INDIRECT: return m.getWord(m.getWord(ea)); - default: m.invalidAddressing(); return 0; - } -} - -inline double resolveFloatOperand(Machine& m, int ea, AddressingMode mode) -{ - switch (mode) - { - case AddressingMode::IMMEDIATE: return static_cast(ea); - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: return m.getFloat(ea); - case AddressingMode::INDIRECT: return m.getFloat(m.getWord(ea)); - default: m.invalidAddressing(); return 0.0; - } -} -inline void writeWordOperand(Machine& m, int ea, AddressingMode mode, int value) -{ - switch (mode) - { - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: m.setWord(ea, value); break; // direct store - case AddressingMode::INDIRECT: m.setWord(m.getWord(ea), value); break; // store via pointer - default: m.invalidAddressing(); break; - } -} - -inline void writeFloatOperand(Machine& m, int ea, AddressingMode mode, double value) -{ - switch (mode) - { - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: m.setFloat(ea, value); break; - case AddressingMode::INDIRECT: m.setFloat(m.getWord(ea), value); break; - default: m.invalidAddressing(); break; - } -} - - -// For jump-like ops: what PC should become? -inline int resolveJumpTarget(Machine& m, int ea, AddressingMode mode) -{ - switch (mode) - { - case AddressingMode::IMMEDIATE: - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: return ea; // jump to EA (normal case) - case AddressingMode::INDIRECT: return m.getWord(ea); // jump via pointer - default: m.invalidAddressing(); return m.getPC(); - } -} - -void fix_handler(Machine &m) -{ - m.setA(static_cast(m.getF())); -} - -void float_handler(Machine &m) -{ - m.setF(static_cast(m.getA())); -} - -void norm_handler(Machine &m) -{ - m.setF(normaliseFloat(m.getF())); -} - -void addr_handler(Machine &m, int r1, int r2) -{ +void addr_handler(Machine& m, int r1, int r2) { m.setReg(r2, m.getReg(r1) + m.getReg(r2)); } +// CLEAR instruction: clears register r (first nibble), second nibble unused void clear_handler(Machine& m, int r, int unused) { m.setReg(r, 0); } -void compr_handler(Machine &m, int r1, int r2) -{ - m.setSW(sic_comp(m.getReg(r1), m.getReg(r2), m.getSW())); -} void divr_handler(Machine& m, int r1, int r2) { @@ -111,33 +31,15 @@ void rmo_handler(Machine &m, int r1, int r2) m.setReg(r2, m.getReg(r1)); } - -// SHIFTL r1, n → left *circular* shift n bits void shiftl_handler(Machine &m, int r1, int n) { - unsigned int v = m.getReg(r1) & WORD_MASK; - n %= WORD_SIZE; - unsigned int res = ((v << n) | (v >> (WORD_SIZE - n))) & WORD_MASK; - m.setReg(r1, res); + m.setReg(r1, m.getReg(r1) << n); } -// SHIFTR r1, n → right shift n bits, fill with original leftmost bit void shiftr_handler(Machine &m, int r1, int n) { - unsigned int v = m.getReg(r1) & WORD_MASK; - n %= WORD_SIZE; - unsigned int msb = (v & 0x800000) ? 1u : 0u; - unsigned int shifted = v >> n; - unsigned int fill = 0; - if (msb) { - fill = (~0u) << (WORD_SIZE - n); - fill &= WORD_MASK; - } - - unsigned int res = (shifted | fill) & WORD_MASK; - m.setReg(r1, res); + m.setReg(r1, m.getReg(r1) >> n); } - void subr_handler(Machine &m, int r1, int r2) { m.setReg(r2, m.getReg(r2) - m.getReg(r1)); @@ -156,433 +58,3 @@ void tixr_handler(Machine &m, int r1, int unused) int valR1 = m.getReg(r1); m.setSW(sic_comp(valX, valR1, m.getSW())); } - -void add_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA(m.getA() + val); -} - -void addf_handler(Machine &m, int ea, AddressingMode mode) -{ - double val = resolveFloatOperand(m, ea, mode); - m.setA(m.getA() + val); -} - -void and_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA(m.getA() & val); -} - -void comp_handler(Machine &m, int ea, AddressingMode mode) -{ - int operand = resolveWordOperand(m, ea, mode); - m.setSW(sic_comp(m.getA(), operand, m.getSW())); -} - -void compf_handler(Machine &m, int ea, AddressingMode mode) -{ - double operand = resolveFloatOperand(m, ea, mode); - m.setSW(sic_comp(m.getF(), operand, m.getSW())); -} - -void div_handler(Machine &m, int ea, AddressingMode mode) -{ - int divisor = resolveWordOperand(m, ea, mode); - if (divisor == 0) { - m.divisionByZero(DIV); - return; - } - m.setA(m.getA() / divisor); -} - -void divf_handler(Machine &m, int ea, AddressingMode mode) -{ - double divisor = resolveFloatOperand(m, ea, mode); - if (divisor == 0.0) { - m.divisionByZero(DIVF); - return; - } - m.setF(m.getF() / divisor); -} - -void j_handler(Machine &m, int ea, AddressingMode mode) -{ - int target = resolveJumpTarget(m, ea, mode); - m.setPC(target); -} - -void jeq_handler(Machine &m, int ea, AddressingMode mode) -{ - int sw = m.getSW(); - int cc = getCC(sw); - if (cc == CC_EQ) { - int target = resolveJumpTarget(m, ea, mode); - m.setPC(target); - } -} - -void jgt_handler(Machine &m, int ea, AddressingMode mode) -{ - int sw = m.getSW(); - int cc = getCC(sw); - if (cc == CC_GT) { - int target = resolveJumpTarget(m, ea, mode); - m.setPC(target); - } -} - -void jlt_handler(Machine &m, int ea, AddressingMode mode) -{ - int sw = m.getSW(); - int cc = getCC(sw); - if (cc == CC_LT) { - int target = resolveJumpTarget(m, ea, mode); - m.setPC(target); - } -} - -void jsub_handler(Machine &m, int ea, AddressingMode mode) -{ - int target = resolveJumpTarget(m, ea, mode); - m.setL(m.getPC()); - m.setPC(target); -} - -void lda_handler(Machine& m, int ea, AddressingMode mode) -{ - m.setA(resolveWordOperand(m, ea, mode)); -} - -void ldb_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setB(resolveWordOperand(m, ea, mode)); -} - -void ldch_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA((m.getA() & 0xFFFF00) | (val & 0xFF)); -} - -void ldf_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setF(resolveFloatOperand(m, ea, mode)); -} - -void ldl_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setL(resolveWordOperand(m, ea, mode)); -} - -void lds_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setS(resolveWordOperand(m, ea, mode)); -} - -void ldt_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setT(resolveWordOperand(m, ea, mode)); -} - -void ldx_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setX(resolveWordOperand(m, ea, mode)); -} - -void mul_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA(m.getA() * val); -} - -void mulf_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setF(m.getF() * resolveFloatOperand(m, ea, mode)); -} - -void or_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA(m.getA() | val); -} - -void rd_handler(Machine &m, int ea, AddressingMode mode) -{ - int deviceNum = resolveWordOperand(m, ea, mode); - Device& device = m.getDevice(deviceNum); - // Load byte into rightmost byte of A register - m.setA((m.getA() & 0xFFFF00) | device.read()); -} - -void rsub_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setPC(m.getL()); -} - -void sta_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getA()); -} - -void stb_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getB()); -} -// Rightmost byte of A register is stored -void stch_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = m.getA() & 0xFF; - switch (mode) - { - case AddressingMode::SIMPLE: - case AddressingMode::SIC_DIRECT: m.setByte(ea, val); break; // direct store - case AddressingMode::INDIRECT: m.setByte(m.getWord(ea), val); break; // store via pointer - default: m.invalidAddressing(); break; - } -} - -void stf_handler(Machine &m, int ea, AddressingMode mode) -{ - writeFloatOperand(m, ea, mode, m.getF()); -} - -void stl_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getL()); -} - -void sts_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getS()); -} - -void stsw_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getSW()); -} - -void stt_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getT()); -} - -void stx_handler(Machine &m, int ea, AddressingMode mode) -{ - writeWordOperand(m, ea, mode, m.getX()); -} - -void sub_handler(Machine &m, int ea, AddressingMode mode) -{ - int val = resolveWordOperand(m, ea, mode); - m.setA(m.getA() - val); -} - -void subf_handler(Machine &m, int ea, AddressingMode mode) -{ - double val = resolveFloatOperand(m, ea, mode); - m.setF(m.getF() - val); -} - -void td_handler(Machine &m, int ea, AddressingMode mode) -{ - int deviceNum = resolveWordOperand(m, ea, mode); - Device& device = m.getDevice(deviceNum); - // Test device and set SW accordingly - if (device.test()) { - m.setSW(setCC(m.getSW(), CC_EQ)); - } else { - m.setSW(setCC(m.getSW(), CC_LT)); - } -} - -void tix_handler(Machine &m, int ea, AddressingMode mode) -{ - m.setX(m.getX() + 1); - int valX = m.getX(); - int memVal = resolveWordOperand(m, ea, mode); - m.setSW(sic_comp(valX, memVal, m.getSW())); -} - -void wd_handler(Machine &m, int ea, AddressingMode mode) -{ - int deviceNum = resolveWordOperand(m, ea, mode); - Device& device = m.getDevice(deviceNum); - // Write rightmost byte of A register to device - device.write(static_cast(m.getA() & 0xFF)); -} - -void xexe_handler(Machine &m) -{ - m.enableExtendedMode(); - m.execute(); - m.disableExtendedMode(); -} - -void halt_handler(Machine &m) -{ - m.halt(); -} - -void nop_handler(Machine &m) -{ - // Do nothing -} - -void vaddr_handler(Machine &m, int r1, int r2) -{ - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVectorRegister(r1)[i] + m.getVectorRegister(r2)[i]; - } - m.setVectorRegister(r2, result); -} - -void vsubr_handler(Machine &m, int r1, int r2) -{ - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVectorRegister(r2)[i] - m.getVectorRegister(r1)[i]; - } - m.setVectorRegister(r2, result); -} - -void vmulr_handler(Machine &m, int r1, int r2) -{ - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVectorRegister(r1)[i] * m.getVectorRegister(r2)[i]; - } - m.setVectorRegister(r2, result); -} - -void vdivr_handler(Machine &m, int r1, int r2) -{ - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - if (m.getVectorRegister(r1)[i] == 0) { - m.divisionByZero(VDIVR); - return; - } - result[i] = m.getVectorRegister(r2)[i] / m.getVectorRegister(r1)[i]; - } - m.setVT(result); -} - -void vadd_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVA()[i] + vec[i]; - } - m.setVA(result); -} - -void vsub_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVA()[i] - vec[i]; - } - m.setVA(result); -} - -void vmul_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - result[i] = m.getVA()[i] * vec[i]; - } - m.setVA(result); -} - -void vdiv_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - int result[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - if (vec[i] == 0) { - m.divisionByZero(VDIV); - return; - } - result[i] = m.getVA()[i] / vec[i]; - } - m.setVA(result); -} - -void stva_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - const int* vec = m.getVA(); - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - m.setWord(baseAddr + i * 3, vec[i]); - } -} - -void stvs_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - const int* vec = m.getVS(); - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - m.setWord(baseAddr + i * 3, vec[i]); - } -} - -void stvt_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - const int* vec = m.getVT(); - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - m.setWord(baseAddr + i * 3, vec[i]); - } -} - -void ldva_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - m.setVA(vec); -} - -void ldvs_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - m.setVS(vec); -} - -void ldvt_handler(Machine &m, int ea, AddressingMode mode) -{ - int baseAddr = resolveWordOperand(m, ea, mode); - int vec[VECTOR_REG_SIZE]; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - vec[i] = m.getWord(baseAddr + i * 3); - } - m.setVT(vec); -} diff --git a/simulator_SIC_XE/src/loader.cpp b/simulator_SIC_XE/src/loader.cpp deleted file mode 100644 index 9b3d293..0000000 --- a/simulator_SIC_XE/src/loader.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "loader.h" -#include "file_reader.h" -#include "machine.h" -#include "constants.h" -#include - -Loader::~Loader() -{ - _machine.reset(); -} - - - - -void Loader::load() -{ - HeaderMetadata header = readHeader(); - - while(true) { - RecordType type = parseRecordType(static_cast(_file_reader->readByte())); - switch (type) { - case RecordType::TEXT: { - TextRecord textRecord = readTextRecord(); - if (!load_into_memory(textRecord.start_address, textRecord.data)) { - throw std::runtime_error("Failed to load text record into memory"); - } - break; - } - case RecordType::END: { - EndRecord endRecord = readEndRecord(); - _machine->setPC(endRecord.execution_start_address); - return; // Loading complete - } - case RecordType::UNKNOWN: - default: - throw std::runtime_error("Unknown record type encountered"); - } - } -} - -Loader::RecordType Loader::parseRecordType(char c) -{ - switch (c) { - case 'H': return RecordType::HEADER; - case 'T': return RecordType::TEXT; - case 'E': return RecordType::END; - default: return RecordType::UNKNOWN; // fallback; adjust as needed - } -} - -Loader::HeaderMetadata Loader::readHeader() -{ - - RecordType type = parseRecordType(static_cast(_file_reader->readByte())); - if (type != RecordType::HEADER) { - throw std::runtime_error("Expected HEADER record"); - } - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - - HeaderMetadata header; - // Read program name (6 bytes) - header.program_name = _file_reader->readString(6); - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - - // Read start address (6 hex digits) - header.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - - // Read length (6 hex digits) - header.length = std::stoi(_file_reader->readString(6), nullptr, 16); - // consume newline - _file_reader->readLine(); - return header; -} - -Loader::TextRecord Loader::readTextRecord() -{ - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - TextRecord record; - // Assume 'T' has already been read - record.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - - // Read length (1 byte, 2 hex digits) - int length = std::stoi(_file_reader->readString(2), nullptr, 16); - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - - 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) { - std::string byteHex = byteStr.substr(i * 2, 2); - record.data[i] = static_cast(std::stoi(byteHex, nullptr, 16)); - } - return record; -} - -Loader::EndRecord Loader::readEndRecord() -{ - EndRecord record; - if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); - // Assume 'E' has already been read - std::string addrStr = _file_reader->readString(6); - if (!addrStr.empty()) { - record.execution_start_address = std::stoi(addrStr, nullptr, 16); - } else { - record.execution_start_address = 0; - } - // consume newline - _file_reader->readLine(); - return record; -} - -bool Loader::load_into_memory(int start_address, const std::vector &data) -{ - for(size_t i = 0; i < data.size(); ++i) { - int addr = start_address + static_cast(i); - if (addr < 0 || addr >= MEMORY_SIZE) { - return false; - } - _machine->setByte(addr, data[i]); - } - return true; -} diff --git a/simulator_SIC_XE/src/machine.cpp b/simulator_SIC_XE/src/machine.cpp index 9570054..d190f6d 100644 --- a/simulator_SIC_XE/src/machine.cpp +++ b/simulator_SIC_XE/src/machine.cpp @@ -4,8 +4,6 @@ #include "opcode.h" #include "instructions.h" -#include -#include using std::make_shared; @@ -21,8 +19,6 @@ Machine::Machine() devices[1] = make_shared(std::cout); // device 2: standard error devices[2] = make_shared(std::cerr); - _exex_mode = false; - _instructionsTable = instructions; } Machine::~Machine() @@ -32,17 +28,6 @@ Machine::~Machine() } } -int Machine::getSpeed() const -{ - return speedkHz.load(); -} - -void Machine::setSpeed(int kHz) -{ - speedkHz.store(kHz); -} - -// TODO: implement errors void Machine::notImplemented(string mnemonic) { cout << prefix << "Not implemented: " << mnemonic << endl; @@ -53,7 +38,6 @@ void Machine::invalidOpcode(int opcode) cout << prefix << "Invalid opcode: " << opcode << endl; } - void Machine::invalidAddressing() { cout << prefix << "Invalid addressing mode" << endl; @@ -69,76 +53,6 @@ void Machine::undefinedHandler(int opcode) cout << prefix << "Undefined handler for opcode: " << opcode << endl; } -void Machine::enableExtendedMode() -{ - if(!USE_EXTENDED_MODE) return; - _exex_mode = true; - _instructionsTable = instructionsEXEX; -} - -void Machine::disableExtendedMode() -{ - if(!USE_EXTENDED_MODE) return; - _exex_mode = false; - _instructionsTable = instructions; -} - -int *Machine::getVectorRegister(int regNum) -{ - switch (regNum) { - case 0: return VA; - case 4: return VS; - case 5: return VT; - default: - cerr << prefix << "Invalid register number: " << regNum << endl; - return nullptr; - } -} - -void Machine::setVectorRegister(int regNum, const int *values) -{ - int* targetReg = getVectorRegister(regNum); - if (targetReg == nullptr) return; - for (int i = 0; i < VECTOR_REG_SIZE; i++) { - targetReg[i] = toSIC24(values[i]); - } -} - -void Machine::setVA(const int *values) -{ - for (int i = 0; i < VECTOR_REG_SIZE; i++) { - VA[i] = toSIC24(values[i]); - } -} - -void Machine::setVS(const int *values) -{ - for (int i = 0; i < VECTOR_REG_SIZE; i++) { - VS[i] = toSIC24(values[i]); - } -} - -void Machine::setVT(const int *values) -{ - for (int i = 0; i < VECTOR_REG_SIZE; i++) { - VT[i] = toSIC24(values[i]); - } -} - -void Machine::tick() -{ - const int speed = speedkHz.load(); - if (speed <= 0) throw std::runtime_error("Invalid speed setting in Machine::tick"); - - const auto delay = std::chrono::microseconds(1000 / speed); - std::this_thread::sleep_for(delay); -} - -void Machine::halt() -{ - _stopped = true; -} - int Machine::getReg(int regNum) const { switch (regNum) { @@ -214,93 +128,23 @@ void Machine::setWord(int address, int value) cerr << prefix << "Invalid memory address: " << address << endl; return; } - value &= 0xFFFFFF; memory[address] = static_cast(value & 0xFF); memory[address + 1] = static_cast((value >> 8) & 0xFF); memory[address + 2] = static_cast((value >> 16) & 0xFF); } +// TODO: implement proper float storage and retrieval double Machine::getFloat(int address) { - if (address < 0 || address + 5 >= MEMORY_SIZE) { - cerr << prefix << "Invalid float address: " << address << endl; - return 0.0; - } - - // load 6 bytes, little-endian → 48-bit word - unsigned long long raw = - (unsigned long long)memory[address] | - ((unsigned long long)memory[address+1] << 8) | - ((unsigned long long)memory[address+2] << 16) | - ((unsigned long long)memory[address+3] << 24) | - ((unsigned long long)memory[address+4] << 32) | - ((unsigned long long)memory[address+5] << 40); - - int sign = (raw >> 47) & 0x1; - int exponent = (raw >> 40) & 0x7F; - unsigned long long frac = raw & SICF_FRAC_MASK; // 40 bits - - if (raw == 0) return 0.0; - - // value = (1 + frac/2^40) * 2^(exp - 64) - double mant = 1.0 + (double)frac / (double)(1ULL << SICF_FRAC_BITS); - int e = exponent - SICF_EXP_BIAS; - double val = std::ldexp(mant, e); // ldexp is fast enough here - return sign ? -val : val; + return 0.0; } void Machine::setFloat(int address, double value) { - if (address < 0 || address + 5 >= MEMORY_SIZE) { - cerr << prefix << "Invalid float address: " << address << endl; - return; - } - - if (value == 0.0) { - memory[address] = 0; - memory[address+1] = 0; - memory[address+2] = 0; - memory[address+3] = 0; - memory[address+4] = 0; - memory[address+5] = 0; - return; - } - - int sign = value < 0; - double x = sign ? -value : value; - - // normalize x to [1, 2) - int exp2 = 0; - x = std::frexp(x, &exp2); - x *= 2.0; - exp2 -= 1; - - int exp_field = exp2 + SICF_EXP_BIAS; - if (exp_field < 0) exp_field = 0; - if (exp_field > 127) exp_field = 127; - - // mantissa = (x - 1) * 2^40 - double frac_d = (x - 1.0) * (double)(1ULL << SICF_FRAC_BITS); - unsigned long long frac = (unsigned long long)(frac_d + 0.5); // round - frac &= SICF_FRAC_MASK; - - unsigned long long raw = - ((unsigned long long)sign << 47) | - ((unsigned long long)exp_field << 40) | - frac; - - // store 6 bytes little-endian - memory[address] = (unsigned char)( raw & 0xFF); - memory[address+1] = (unsigned char)((raw >> 8) & 0xFF); - memory[address+2] = (unsigned char)((raw >> 16) & 0xFF); - memory[address+3] = (unsigned char)((raw >> 24) & 0xFF); - memory[address+4] = (unsigned char)((raw >> 32) & 0xFF); - memory[address+5] = (unsigned char)((raw >> 40) & 0xFF); + // TODO: implement proper float storage } - - Device &Machine::getDevice(int num) { if(num < 0 || num >= static_cast(devices.size()) || !devices[num]) { @@ -351,55 +195,49 @@ int Machine::fetch() return getByte(PC++); } -void Machine::execute() { - if (_stopped) return; - int b1 = fetch(); - - InstructionInfo &info = _instructionsTable[b1]; - - if (info.type == InstructionType::TYPE1) { execF1(b1); return; } - if (info.type == InstructionType::TYPE2) { execF2(b1, fetch()); return; } - - int opcode = b1 & TYPE3_4_SIC_MASK; - InstructionInfo &info34 = _instructionsTable[opcode]; - int ni = b1 & NI_MASK; - - if (info34.type == InstructionType::TYPE3_4) { - int b2 = fetch(), b3 = fetch(); - int x = (b2 & 0x80) ? 1 : 0; - int b = (b2 & 0x40) ? 1 : 0; - int p = (b2 & 0x20) ? 1 : 0; - int e = (b2 & 0x10) ? 1 : 0; - - int operand; - if (ni == NI_SIC) { - // PURE SIC - operand = ((b2 & 0x7F) << 8) | b3; - } else { - // SIC/XE - operand = e - ? (((b2 & 0x0F) << 16) | (b3 << 8) | fetch()) // F4: 20-bit - : (((b2 & 0x0F) << 8) | b3); // F3: 12-bit - } - - execSICF3F4(opcode, ni, x, b, p, e, operand); - return; +void Machine::execute() +{ + int opcode = fetch(); + InstructionType type = instructions[opcode].type; + switch (type) { + case InstructionType::TYPE1: execF1(opcode);break; + case InstructionType::TYPE2: execF2(opcode, fetch());break; + case InstructionType::TYPE3_4: // extract n and i bits + { + int ni = opcode & 0x3; + int operand = fetch(); + execSICF3F4(opcode, ni, operand); + } + break; + default: invalidOpcode(opcode); break; } - - invalidOpcode(b1); } - - - bool Machine::execF1(int opcode) { - if (_instructionsTable[opcode].handler) { - auto handler = reinterpret_cast(_instructionsTable[opcode].handler); - handler(*this); + switch (opcode) + { + case FIX: + setA(static_cast(getF())); return true; + case FLOAT: + setF(static_cast(getA())); + return true; + case HIO: + notImplemented("HIO"); + return true; + case NORM: + notImplemented("NORM"); + return true; + case SIO: + notImplemented("SIO"); + return true; + case TIO: + notImplemented("TIO"); + return true; + default: + break; } - undefinedHandler(opcode); return false; } @@ -408,8 +246,8 @@ bool Machine::execF2(int opcode, int operand) int r1 = (operand >> 4) & 0xF; int r2 = operand & 0xF; - if (_instructionsTable[opcode].handler) { - auto handler = reinterpret_cast(_instructionsTable[opcode].handler); + if (instructions[opcode].handler) { + auto handler = reinterpret_cast(instructions[opcode].handler); handler(*this, r1, r2); return true; } @@ -417,63 +255,7 @@ bool Machine::execF2(int opcode, int operand) return false; } - -bool Machine::execSICF3F4(int opcode, int ni, int x, int b, int p, int e, int operand) +bool Machine::execSICF3F4(int opcode, int ni, int operand) { - int ea_part = operand; - int base = 0; - AddressingMode mode = getAddressingMode(ni); - - // --- PURE SIC --- - if (mode == AddressingMode::SIC_DIRECT) { - int ea = ea_part + (x ? getX() : 0); - if (_instructionsTable[opcode].handler) { - auto h = reinterpret_cast(_instructionsTable[opcode].handler); - h(*this, ea, mode); - return true; - } - undefinedHandler(opcode); - return false; - } - - // --- SIC/XE EA calc --- - - if (!e) { // format 3 - if (b && !p) { - base = getB(); // base-relative, unsigned 12-bit - } else if (p && !b) { - // PC-relative, signed 12-bit - if (ea_part & 0x800) // bit 11 set? - ea_part |= 0xFFFFF000; // sign-extend - base = getPC(); - } - } - // format 4 (e=1): b/p ignored, ea_part is 20-bit absolute - int ea = base + ea_part + (x ? getX() : 0); - - if (_instructionsTable[opcode].handler) { - auto h = reinterpret_cast(_instructionsTable[opcode].handler); - h(*this, ea, mode); - return true; - } - - undefinedHandler(opcode); return false; } - -void Machine::start() -{ - running.store(true); - - // Main execution loop - // TODO: consider running in separate thread - while (running.load()) { - execute(); - tick(); - } -} - -void Machine::stop() -{ - running.store(false); -} diff --git a/simulator_SIC_XE/src/main.cpp b/simulator_SIC_XE/src/main.cpp index bd7a9e7..1c285b9 100644 --- a/simulator_SIC_XE/src/main.cpp +++ b/simulator_SIC_XE/src/main.cpp @@ -1,110 +1,27 @@ #include -#include -#include #include "machine.h" #include "file_device.h" #include "opcode.h" #include "instructions.h" -#include "constants.h" -#include "loader.h" using std::cout; using std::endl; -struct VectorAddProgram { - int x, y; -}; - - - int main() { - /* loadInstructionSet(); Machine machine; - cout << "SIC/XE Program: Accumulator Loop" << endl; - - const int TEMP_ADDR = 0x50; - const int LOOP_ADDR = 0x03; - - // clear TEMP - machine.setByte(TEMP_ADDR, 0); - loadInstructionSet(); - - cout << "SIC/XE Program: Vector add test" << endl; - - const int VA_ADDR = 0x100; // source vector A - const int VB_ADDR = 0x200; // source vector B - const int VR_ADDR = 0x300; // result store (STVA) - - // Prepare two 4-element vectors (WORD = 3 bytes) for VA and VB - int a_vals[VECTOR_REG_SIZE] = {1,2,3,4}; - int b_vals[VECTOR_REG_SIZE] = {5,6,7,8}; - - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - machine.setWord(VA_ADDR + i * 3, a_vals[i]); - machine.setWord(VB_ADDR + i * 3, b_vals[i]); - } - - // Assemble program at address 0x000 (we use XEXE before each extended op) - // Offsets and bytes (hex): - // 0x00: XEXE -> 0xEE - // 0x01: LDVA (format 4) -> b1=0x03 (LDVA|ni=0x00|0x03), b2=0x10 (e=1), b3=0x01, b4=0x00 (addr 0x100) - // 0x05: XEXE -> 0xEE - // 0x06: LDVS (format 4) -> b1=0x6B (0x68|0x03), b2=0x10, b3=0x02, b4=0x00 (addr 0x200) - // 0x0A: XEXE -> 0xEE - // 0x0B: VADDR B->A (type 2) -> opcode 0x90, operand r1=4 (VS), r2=0 (VA) => operand=(4<<4)|0=0x40 - // 0x0D: XEXE -> 0xEE - // 0x0E: STVA (format4) -> b1=0x0F (0x0C|0x03), b2=0x10, b3=0x03, b4=0x00 (addr 0x300) - // 0x12: J (format4) to self -> b1=0x3F (0x3C|0x03), b2=0x10, b3=0x00, b4=0x12 - - unsigned char prog[] = { - 0xEE, - 0x01, 0x10, 0x01, 0x00, // LDVA (format 4) with ni=IMMEDIATE -> b1=0x01 - 0xEE, - 0x69, 0x10, 0x02, 0x00, // LDVS (format 4) with ni=IMMEDIATE -> b1=0x69 (0x68|0x01) - 0xEE, - 0x90, 0x40, // VADDR VS->VA (type2) - 0xEE, - 0x0D, 0x10, 0x03, 0x00, // STVA (format4) with ni=IMMEDIATE -> b1=0x0D - 0x3F, 0x10, 0x00, 0x12 // J (format4) loop to 0x12 - }; - - const int PROG_START = 0x00; - for (size_t i = 0; i < sizeof(prog); ++i) { - machine.setByte(PROG_START + static_cast(i), prog[i]); - } - - machine.setPC(PROG_START); - - cout << "Program loaded. VA@0x" << std::hex << VA_ADDR << " VB@0x" << VB_ADDR << " -> store@0x" << VR_ADDR << std::dec << endl; + cout << "Machine initialized successfully." << endl; - const int MAX_STEPS = 100; - for (int i = 0; i < MAX_STEPS; ++i) { - machine.execute(); - } - - // Read back result vector stored at VR_ADDR - cout << "Result vector at 0x" << std::hex << VR_ADDR << std::dec << ": "; - for (int i = 0; i < VECTOR_REG_SIZE; ++i) { - int val = machine.getWord(VR_ADDR + i * 3); - cout << val << (i + 1 < VECTOR_REG_SIZE ? ", " : "\n"); - } - */ - - loadInstructionSet(); - std::shared_ptr machine = std::make_shared(); - Loader loader(machine, std::string(PATH_RESOURCES) + "test.obj"); - loader.load(); - machine->execute(); - machine->execute(); - machine->execute(); - machine->execute(); - machine->execute(); - machine->execute(); - cout << "Register A after execution: " << machine->getA() << endl; - + // COMPUTE A + B and store result in B + machine.setA(10); + machine.setB(20); + machine.setByte(0, ADDR); + machine.setByte(1, 0x03); // r1 = 0 (A), r2 = 3 (B) + cout << "Before ADDR: A = " << machine.getA() << ", B = " << machine.getB() << endl; + machine.execute(); + cout << "After ADDR: A = " << machine.getA() << ", B = " << machine.getB() << endl; return 0; } \ No newline at end of file diff --git a/simulator_SIC_XE/src/opcode.cpp b/simulator_SIC_XE/src/opcode.cpp index 0b63ce8..febc489 100644 --- a/simulator_SIC_XE/src/opcode.cpp +++ b/simulator_SIC_XE/src/opcode.cpp @@ -1,109 +1,75 @@ #include "opcode.h" #include "instructions.h" -#include "utils.h" #include InstructionInfo instructions[0xff]; -InstructionInfo instructionsEXEX[0xff]; void loadInstructionSet() { - instructions[ADD] = {"ADD", InstructionType::TYPE3_4, reinterpret_cast(add_handler)}; - instructions[ADDF] = {"ADDF", InstructionType::TYPE3_4, reinterpret_cast(addf_handler)}; - instructions[ADDR] = {"ADDR", InstructionType::TYPE2, reinterpret_cast(addr_handler)}; - instructions[AND] = {"AND", InstructionType::TYPE3_4, reinterpret_cast(and_handler)}; - instructions[CLEAR] = {"CLEAR", InstructionType::TYPE2, reinterpret_cast(clear_handler)}; - instructions[COMP] = {"COMP", InstructionType::TYPE3_4, reinterpret_cast(comp_handler)}; - instructions[COMPF] = {"COMPF", InstructionType::TYPE3_4, reinterpret_cast(compf_handler)}; - instructions[COMPR] = {"COMPR", InstructionType::TYPE2, reinterpret_cast(compr_handler)}; - instructions[DIV] = {"DIV", InstructionType::TYPE3_4, reinterpret_cast(div_handler)}; - instructions[DIVF] = {"DIVF", InstructionType::TYPE3_4, reinterpret_cast(divf_handler)}; - instructions[DIVR] = {"DIVR", InstructionType::TYPE2, reinterpret_cast(divr_handler)}; - instructions[FIX] = {"FIX", InstructionType::TYPE1, reinterpret_cast(fix_handler)}; - instructions[FLOAT] = {"FLOAT", InstructionType::TYPE1, reinterpret_cast(float_handler)}; - instructions[HIO] = {"HIO", InstructionType::TYPE1, nullptr}; - instructions[J] = {"J", InstructionType::TYPE3_4, reinterpret_cast(j_handler)}; - instructions[JEQ] = {"JEQ", InstructionType::TYPE3_4, reinterpret_cast(jeq_handler)}; - instructions[JGT] = {"JGT", InstructionType::TYPE3_4, reinterpret_cast(jgt_handler)}; - instructions[JLT] = {"JLT", InstructionType::TYPE3_4, reinterpret_cast(jlt_handler)}; - instructions[JSUB] = {"JSUB", InstructionType::TYPE3_4, reinterpret_cast(jsub_handler)}; - instructions[LDA] = {"LDA", InstructionType::TYPE3_4, reinterpret_cast(lda_handler)}; - instructions[LDB] = {"LDB", InstructionType::TYPE3_4, reinterpret_cast(ldb_handler)}; - instructions[LDCH] = {"LDCH", InstructionType::TYPE3_4, reinterpret_cast(ldch_handler)}; - instructions[LDF] = {"LDF", InstructionType::TYPE3_4, reinterpret_cast(ldf_handler)}; - instructions[LDL] = {"LDL", InstructionType::TYPE3_4, reinterpret_cast(ldl_handler)}; - instructions[LDS] = {"LDS", InstructionType::TYPE3_4, reinterpret_cast(lds_handler)}; - instructions[LDT] = {"LDT", InstructionType::TYPE3_4, reinterpret_cast(ldt_handler)}; - instructions[LDX] = {"LDX", InstructionType::TYPE3_4, reinterpret_cast(ldx_handler)}; - instructions[LPS] = {"LPS", InstructionType::TYPE3_4, nullptr}; - instructions[MUL] = {"MUL", InstructionType::TYPE3_4, reinterpret_cast(mul_handler)}; - instructions[MULF] = {"MULF", InstructionType::TYPE3_4, reinterpret_cast(mulf_handler)}; - instructions[MULR] = {"MULR", InstructionType::TYPE2, reinterpret_cast(mulr_handler)}; - instructions[NORM] = {"NORM", InstructionType::TYPE1, reinterpret_cast(norm_handler)}; - instructions[OR] = {"OR", InstructionType::TYPE3_4, reinterpret_cast(or_handler)}; - instructions[RD] = {"RD", InstructionType::TYPE3_4, reinterpret_cast(rd_handler)}; - instructions[RMO] = {"RMO", InstructionType::TYPE2, reinterpret_cast(rmo_handler)}; - instructions[RSUB] = {"RSUB", InstructionType::TYPE3_4, reinterpret_cast(rsub_handler)}; - instructions[SHIFTL] = {"SHIFTL", InstructionType::TYPE2, reinterpret_cast(shiftl_handler)}; - instructions[SHIFTR] = {"SHIFTR", InstructionType::TYPE2, reinterpret_cast(shiftr_handler)}; - instructions[SIO] = {"SIO", InstructionType::TYPE1, nullptr}; - instructions[SSK] = {"SSK", InstructionType::TYPE3_4, nullptr}; - instructions[STA] = {"STA", InstructionType::TYPE3_4, reinterpret_cast(sta_handler)}; - instructions[STB] = {"STB", InstructionType::TYPE3_4, reinterpret_cast(stb_handler)}; - instructions[STCH] = {"STCH", InstructionType::TYPE3_4, reinterpret_cast(stch_handler)}; - instructions[STF] = {"STF", InstructionType::TYPE3_4, reinterpret_cast(stf_handler)}; - instructions[STI] = {"STI", InstructionType::TYPE3_4, nullptr}; - instructions[STL] = {"STL", InstructionType::TYPE3_4, reinterpret_cast(stl_handler)}; - instructions[STS] = {"STS", InstructionType::TYPE3_4, reinterpret_cast(sts_handler)}; - instructions[STSW] = {"STSW", InstructionType::TYPE3_4, reinterpret_cast(stsw_handler)}; - instructions[STT] = {"STT", InstructionType::TYPE3_4, reinterpret_cast(stt_handler)}; - instructions[STX] = {"STX", InstructionType::TYPE3_4, reinterpret_cast(stx_handler)}; - instructions[SUB] = {"SUB", InstructionType::TYPE3_4, reinterpret_cast(sub_handler)}; - instructions[SUBF] = {"SUBF", InstructionType::TYPE3_4, reinterpret_cast(subf_handler)}; - instructions[SUBR] = {"SUBR", InstructionType::TYPE2, reinterpret_cast(subr_handler)}; - instructions[SVC] = {"SVC", InstructionType::TYPE2, reinterpret_cast(svc_handler)}; - instructions[TIXR] = {"TIXR", InstructionType::TYPE2, reinterpret_cast(tixr_handler)}; - instructions[TD] = {"TD", InstructionType::TYPE3_4, reinterpret_cast(td_handler)}; - instructions[TIX] = {"TIX", InstructionType::TYPE3_4, reinterpret_cast(tix_handler)}; - instructions[TIO] = {"TIO", InstructionType::TYPE1, nullptr}; - instructions[WD] = {"WD", InstructionType::TYPE3_4, reinterpret_cast(wd_handler)}; + instructions[ADD] = {"ADD", InstructionType::TYPE3_4, nullptr}; + instructions[ADDF] = {"ADDF", InstructionType::TYPE3_4, nullptr}; + instructions[ADDR] = {"ADDR", InstructionType::TYPE2, reinterpret_cast(addr_handler)}; + instructions[AND] = {"AND", InstructionType::TYPE3_4, nullptr}; + instructions[CLEAR] = {"CLEAR", InstructionType::TYPE2, reinterpret_cast(clear_handler)}; + instructions[COMP] = {"COMP", InstructionType::TYPE3_4, nullptr}; + instructions[COMPF] = {"COMPF", InstructionType::TYPE3_4, nullptr}; + instructions[COMPR] = {"COMPR", InstructionType::TYPE2, nullptr}; + instructions[DIV] = {"DIV", InstructionType::TYPE3_4, nullptr}; + instructions[DIVF] = {"DIVF", InstructionType::TYPE3_4, nullptr}; + instructions[DIVR] = {"DIVR", InstructionType::TYPE2, reinterpret_cast(divr_handler)}; + instructions[FIX] = {"FIX", InstructionType::TYPE1, nullptr}; + instructions[FLOAT] = {"FLOAT", InstructionType::TYPE1, nullptr}; + instructions[HIO] = {"HIO", InstructionType::TYPE1, nullptr}; + instructions[J] = {"J", InstructionType::TYPE3_4, nullptr}; + instructions[JEQ] = {"JEQ", InstructionType::TYPE3_4, nullptr}; + instructions[JGT] = {"JGT", InstructionType::TYPE3_4, nullptr}; + instructions[JLT] = {"JLT", InstructionType::TYPE3_4, nullptr}; + instructions[JSUB] = {"JSUB", InstructionType::TYPE3_4, nullptr}; + instructions[LDA] = {"LDA", InstructionType::TYPE3_4, nullptr}; + instructions[LDB] = {"LDB", InstructionType::TYPE3_4, nullptr}; + instructions[LDCH] = {"LDCH", InstructionType::TYPE3_4, nullptr}; + instructions[LDF] = {"LDF", InstructionType::TYPE3_4, nullptr}; + instructions[LDL] = {"LDL", InstructionType::TYPE3_4, nullptr}; + instructions[LDS] = {"LDS", InstructionType::TYPE3_4, nullptr}; + instructions[LDT] = {"LDT", InstructionType::TYPE3_4, nullptr}; + instructions[LDX] = {"LDX", InstructionType::TYPE3_4, nullptr}; + instructions[LPS] = {"LPS", InstructionType::TYPE3_4, nullptr}; + instructions[MUL] = {"MUL", InstructionType::TYPE3_4, nullptr}; + instructions[MULF] = {"MULF", InstructionType::TYPE3_4, nullptr}; + instructions[MULR] = {"MULR", InstructionType::TYPE2, reinterpret_cast(mulr_handler)}; + instructions[NORM] = {"NORM", InstructionType::TYPE1, nullptr}; + instructions[OR] = {"OR", InstructionType::TYPE3_4, nullptr}; + instructions[RD] = {"RD", InstructionType::TYPE3_4, nullptr}; + instructions[RMO] = {"RMO", InstructionType::TYPE2, reinterpret_cast(rmo_handler)}; + instructions[RSUB] = {"RSUB", InstructionType::TYPE3_4, nullptr}; + instructions[SHIFTL] = {"SHIFTL", InstructionType::TYPE2, reinterpret_cast(shiftl_handler)}; + instructions[SHIFTR] = {"SHIFTR", InstructionType::TYPE2, reinterpret_cast(shiftr_handler)}; + instructions[SIO] = {"SIO", InstructionType::TYPE1, nullptr}; + instructions[SSK] = {"SSK", InstructionType::TYPE3_4, nullptr}; + instructions[STA] = {"STA", InstructionType::TYPE3_4, nullptr}; + instructions[STB] = {"STB", InstructionType::TYPE3_4, nullptr}; + instructions[STCH] = {"STCH", InstructionType::TYPE3_4, nullptr}; + instructions[STF] = {"STF", InstructionType::TYPE3_4, nullptr}; + instructions[STI] = {"STI", InstructionType::TYPE3_4, nullptr}; + instructions[STL] = {"STL", InstructionType::TYPE3_4, nullptr}; + instructions[STS] = {"STS", InstructionType::TYPE3_4, nullptr}; + instructions[STSW] = {"STSW", InstructionType::TYPE3_4, nullptr}; + instructions[STT] = {"STT", InstructionType::TYPE3_4, nullptr}; + instructions[STX] = {"STX", InstructionType::TYPE3_4, nullptr}; + instructions[SUB] = {"SUB", InstructionType::TYPE3_4, nullptr}; + instructions[SUBF] = {"SUBF", InstructionType::TYPE3_4, nullptr}; + instructions[SUBR] = {"SUBR", InstructionType::TYPE2, reinterpret_cast(subr_handler)}; + instructions[SVC] = {"SVC", InstructionType::TYPE2, reinterpret_cast(svc_handler)}; + instructions[TIXR] = {"TIXR", InstructionType::TYPE2, reinterpret_cast(tixr_handler)}; + instructions[TD] = {"TD", InstructionType::TYPE3_4, nullptr}; + instructions[TIX] = {"TIX", InstructionType::TYPE3_4, nullptr}; + instructions[TIO] = {"TIO", InstructionType::TYPE1, nullptr}; + instructions[WD] = {"WD", InstructionType::TYPE3_4, nullptr}; - // Load SIC/XE/XE extended instructions - if (USE_EXTENDED_MODE) { - // Still in main table - instructions[NOP] = {"NOP", InstructionType::TYPE1, reinterpret_cast(nop_handler)}; - instructions[HALT] = {"HALT", InstructionType::TYPE1, reinterpret_cast(halt_handler)}; - instructions[XEXE] = {"XEXE", InstructionType::TYPE1, reinterpret_cast(xexe_handler)}; - - instructionsEXEX[VADD] = {"VADD", InstructionType::TYPE3_4, reinterpret_cast(vadd_handler)}; - instructionsEXEX[VADDR] = {"VADDR", InstructionType::TYPE2, reinterpret_cast(vaddr_handler)}; - instructionsEXEX[VSUB] = {"VSUB", InstructionType::TYPE3_4, reinterpret_cast(vsub_handler)}; - instructionsEXEX[VSUBR] = {"VSUBR", InstructionType::TYPE2, reinterpret_cast(vsubr_handler)}; - instructionsEXEX[VMUL] = {"VMUL", InstructionType::TYPE3_4, reinterpret_cast(vmul_handler)}; - instructionsEXEX[VMULR] = {"VMULR", InstructionType::TYPE2, reinterpret_cast(vmulr_handler)}; - instructionsEXEX[VDIV] = {"VDIV", InstructionType::TYPE3_4, reinterpret_cast(vdiv_handler)}; - instructionsEXEX[VDIVR] = {"VDIVR", InstructionType::TYPE2, reinterpret_cast(vdivr_handler)}; - instructionsEXEX[STVA] = {"STVA", InstructionType::TYPE3_4, reinterpret_cast(stva_handler)}; - instructionsEXEX[STVS] = {"STVS", InstructionType::TYPE3_4, reinterpret_cast(stvs_handler)}; - instructionsEXEX[STVT] = {"STVT", InstructionType::TYPE3_4, reinterpret_cast(stvt_handler)}; - instructionsEXEX[LDVA] = {"LDVA", InstructionType::TYPE3_4, reinterpret_cast(ldva_handler)}; - instructionsEXEX[LDVS] = {"LDVS", InstructionType::TYPE3_4, reinterpret_cast(ldvs_handler)}; - instructionsEXEX[LDVT] = {"LDVT", InstructionType::TYPE3_4, reinterpret_cast(ldvt_handler)}; - } - // Mark uninitialized opcodes as INVALID + // Mark uninitialized opcodes as INVALID for (int i = 0; i < 0xff; ++i) { - if (instructions[i].name == nullptr) instructions[i] = {"INVALID", InstructionType::INVALID, nullptr}; - if (instructionsEXEX[i].name == nullptr) instructionsEXEX[i] = {"INVALID", InstructionType::INVALID, nullptr}; + if (instructions[i].name == nullptr) { + instructions[i] = {"INVALID", InstructionType::INVALID, nullptr}; + } } -} - -AddressingMode getAddressingMode(int ni) -{ - switch (ni) { - case 0x0: return AddressingMode::SIC_DIRECT; - case 0x1: return AddressingMode::IMMEDIATE; - case 0x2: return AddressingMode::INDIRECT; - case 0x3: return AddressingMode::SIMPLE; - default: return AddressingMode::INVALID; // Should not happen - } -} +} \ No newline at end of file diff --git a/simulator_SIC_XE/src/string_reader.cpp b/simulator_SIC_XE/src/string_reader.cpp deleted file mode 100644 index b87cc02..0000000 --- a/simulator_SIC_XE/src/string_reader.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "string_reader.h" - -StringReader::StringReader(const std::string &s) - : in(s) -{} - -StringReader::~StringReader() = default; - -int StringReader::readByte() { - char c; - if (!in.get(c)) return -1; - return static_cast(c); -} - -bool StringReader::readBytes(uint8_t* buf, size_t len) { - in.read(reinterpret_cast(buf), static_cast(len)); - return static_cast(in.gcount()) == len; -} - -std::string StringReader::readString(size_t len) { - std::string s; - s.resize(len); - in.read(reinterpret_cast(&s[0]), static_cast(len)); - std::streamsize got = in.gcount(); - if (static_cast(got) < len) s.resize(static_cast(got)); - return s; -} - -std::string StringReader::readLine() { - std::string s; - if (!std::getline(in, s)) return std::string(); - return s; -} diff --git a/test.asm b/test.asm deleted file mode 100644 index e25da30..0000000 --- a/test.asm +++ /dev/null @@ -1,7 +0,0 @@ -test START 0 - LDA #1 - LDB #2 - ADDR B, A - -halt J halt - END test \ No newline at end of file