added loading

This commit is contained in:
zanostro 2025-11-17 15:21:25 +01:00
parent 598865d216
commit 7b79c35f63
8 changed files with 84 additions and 14 deletions

View file

@ -46,3 +46,15 @@ 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()

View file

@ -4,6 +4,8 @@
#include "../../include/machine.h"
#include "../../include/instructions.h"
#include "../../include/opcode.h"
#include "../../include/constants.h"
#include "../../../include/loader.h"
#include <QIntValidator>
#include <QLineEdit>
@ -16,6 +18,10 @@
#include <QLabel>
#include <QFont>
class Loader;
std::shared_ptr<Loader> g_loader;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
@ -93,7 +99,9 @@ MainWindow::MainWindow(QWidget *parent) :
setupMemoryDisplay();
setupDisassemblyDisplay();
loadDemoProgram();
//loadDemoProgram();
g_loader = std::make_shared<Loader>(machine(), std::string(PATH_RESOURCES) + "demo_program.obj");
g_loader->load();
updateRegisterDisplays();
updateMemoryDisplay();

View file

@ -1,6 +1,7 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <string>
// ==============================
// SIC/XE Architecture Constants
// ==============================
@ -39,5 +40,13 @@ constexpr int BIT_E_MASK = 0x10; // mask for e bit in F4 and F3 instructions
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

View file

@ -5,6 +5,7 @@
#include <string>
#include <vector>
#include "file_reader.h"
#include <stdexcept>
class Machine;
@ -16,6 +17,9 @@ class Loader {
public:
Loader( shared_ptr<Machine> machine, string filename) : _machine(machine), _filename(filename) {
_file_reader = std::make_shared<FileReader>(filename, std::ios::in);
if (!_file_reader->good()) {
throw std::runtime_error("Loader: failed to open file: " + filename);
}
}
~Loader();

View file

@ -2,6 +2,7 @@
#include "file_reader.h"
#include "machine.h"
#include "constants.h"
#include <algorithm>
Loader::~Loader()
{
@ -49,15 +50,22 @@ Loader::RecordType Loader::parseRecordType(char c)
Loader::HeaderMetadata Loader::readHeader()
{
RecordType type = parseRecordType(static_cast<char>(_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
@ -67,35 +75,40 @@ Loader::HeaderMetadata Loader::readHeader()
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();
// Read data bytes
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) {
unsigned char buffer[2];
_file_reader->readBytes(buffer, 2);
record.data[i] = static_cast<uint8_t>(std::stoi(std::string(reinterpret_cast<char*>(buffer), 2), nullptr, 16));
std::string byteHex = byteStr.substr(i * 2, 2);
record.data[i] = static_cast<uint8_t>(std::stoi(byteHex, nullptr, 16));
}
// consume newline
_file_reader->readLine();
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; // default start address
record.execution_start_address = 0;
}
// consume newline
_file_reader->readLine();
@ -106,8 +119,8 @@ bool Loader::load_into_memory(int start_address, const std::vector<uint8_t> &dat
{
for(size_t i = 0; i < data.size(); ++i) {
int addr = start_address + static_cast<int>(i);
if (addr < 0 || addr >= MEMORY_SIZE) { // 24-bit address space
return false; // Address out of bounds
if (addr < 0 || addr >= MEMORY_SIZE) {
return false;
}
_machine->setByte(addr, data[i]);
}

View file

@ -5,6 +5,8 @@
#include "file_device.h"
#include "opcode.h"
#include "instructions.h"
#include "constants.h"
#include "loader.h"
using std::cout;
using std::endl;
@ -17,6 +19,7 @@ struct VectorAddProgram {
int main()
{
/*
loadInstructionSet();
Machine machine;
cout << "SIC/XE Program: Accumulator Loop" << endl;
@ -88,6 +91,20 @@ int main()
int val = machine.getWord(VR_ADDR + i * 3);
cout << val << (i + 1 < VECTOR_REG_SIZE ? ", " : "\n");
}
*/
loadInstructionSet();
std::shared_ptr<Machine> machine = std::make_shared<Machine>();
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;
return 0;
}

7
test.asm Normal file
View file

@ -0,0 +1,7 @@
test START 0
LDA #1
LDB #2
ADDR B, A
halt J halt
END test