big endian fix

This commit is contained in:
zanostro 2025-12-05 18:03:48 +01:00
parent f98e4b323c
commit 1fb7d52842
4 changed files with 73 additions and 37 deletions

View file

@ -13,7 +13,10 @@ public:
void write(unsigned char value) override;
private:
void ensureFileOpen();
std::fstream fileStream;
std::string filename;
bool fileCreated;
};
#endif // FILE_DEVICE_H

View file

@ -3,21 +3,9 @@
#include <fstream>
FileDevice::FileDevice(const std::string &filename)
: filename(filename), fileCreated(false)
{
fileStream.open(filename, std::ios::in | std::ios::out | std::ios::binary);
if (!fileStream.is_open()) {
std::ofstream create(filename, std::ios::binary);
if (!create) {
throw std::runtime_error("Failed to create file: " + filename);
}
create.close();
fileStream.clear();
fileStream.open(filename, std::ios::in | std::ios::out | std::ios::binary);
if (!fileStream.is_open()) {
throw std::runtime_error("Failed to open file after creating: " + filename);
}
}
// Don't create the file yet - wait until first write
}
FileDevice::~FileDevice()
@ -27,19 +15,45 @@ FileDevice::~FileDevice()
}
}
void FileDevice::ensureFileOpen()
{
if (!fileStream.is_open()) {
if (fileCreated) {
fileStream.open(filename, std::ios::in | std::ios::out);
} else {
std::ofstream create(filename);
if (!create) {
throw std::runtime_error("Failed to create file: " + filename);
}
create.close();
fileCreated = true;
fileStream.open(filename, std::ios::in | std::ios::out);
if (!fileStream.is_open()) {
throw std::runtime_error("Failed to open file after creating: " + filename);
}
}
}
}
unsigned char FileDevice::read()
{
unsigned char value = 0;
ensureFileOpen();
if (fileStream.is_open()) {
fileStream.read(reinterpret_cast<char*>(&value), sizeof(value));
char ch;
if (fileStream.get(ch)) {
value = static_cast<unsigned char>(ch);
}
}
return value;
}
void FileDevice::write(unsigned char value)
{
ensureFileOpen();
if (fileStream.is_open()) {
fileStream.write(reinterpret_cast<const char*>(&value), sizeof(value));
fileStream.put(static_cast<char>(value));
fileStream.flush();
}
}

View file

@ -262,7 +262,12 @@ void ldb_handler(Machine &m, int ea, AddressingMode mode)
void ldch_handler(Machine &m, int ea, AddressingMode mode)
{
int val = resolveWordOperand(m, ea, mode);
int val;
if (mode == AddressingMode::IMMEDIATE) {
val = ea & 0xFF;
} else {
val = m.getByte(ea);
}
m.setA((m.getA() & 0xFFFF00) | (val & 0xFF));
}

View file

@ -19,8 +19,19 @@ Machine::Machine()
devices[0] = make_shared<InputDevice>(std::cin);
// device 1: standard output
devices[1] = make_shared<OutputDevice>(std::cout);
// device 2: standard error
devices[2] = make_shared<OutputDevice>(std::cerr);
// Initialize devices >= 2 as FileDevice with hex names in devices directory
for (int i = 2; i < NUM_DEVICES; i++) {
char hex[3];
snprintf(hex, sizeof(hex), "%02X", i);
std::string filename = "devices/" + std::string(hex) + ".dev";
try {
devices[i] = std::make_shared<FileDevice>(filename);
} catch (const std::exception &e) {
cerr << prefix << "Warning: Failed to initialize FileDevice for device " << i << ": " << e.what() << endl;
}
}
_exex_mode = false;
_instructionsTable = instructions;
}
@ -204,7 +215,8 @@ int Machine::getWord(int address)
cerr << prefix << "Invalid memory address: " << address << endl;
return -1;
}
return static_cast<int>(memory[address]) | (static_cast<int>(memory[address + 1]) << 8) | (static_cast<int>(memory[address + 2]) << 16);
// Big-endian: high byte first
return (static_cast<int>(memory[address]) << 16) | (static_cast<int>(memory[address + 1]) << 8) | static_cast<int>(memory[address + 2]);
}
// Assuming word is 3 bytes
@ -216,9 +228,10 @@ void Machine::setWord(int address, int value)
}
value &= 0xFFFFFF;
memory[address] = static_cast<unsigned char>(value & 0xFF);
// Big-endian: high byte first
memory[address] = static_cast<unsigned char>((value >> 16) & 0xFF);
memory[address + 1] = static_cast<unsigned char>((value >> 8) & 0xFF);
memory[address + 2] = static_cast<unsigned char>((value >> 16) & 0xFF);
memory[address + 2] = static_cast<unsigned char>(value & 0xFF);
}
double Machine::getFloat(int address)
@ -228,14 +241,14 @@ double Machine::getFloat(int address)
return 0.0;
}
// load 6 bytes, little-endian → 48-bit word
// load 6 bytes, big-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);
((unsigned long long)memory[address] << 40) |
((unsigned long long)memory[address+1] << 32) |
((unsigned long long)memory[address+2] << 24) |
((unsigned long long)memory[address+3] << 16) |
((unsigned long long)memory[address+4] << 8) |
(unsigned long long)memory[address+5];
int sign = (raw >> 47) & 0x1;
int exponent = (raw >> 40) & 0x7F;
@ -290,13 +303,13 @@ void Machine::setFloat(int address, double value)
((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);
// store 6 bytes big-endian
memory[address] = (unsigned char)((raw >> 40) & 0xFF);
memory[address+1] = (unsigned char)((raw >> 32) & 0xFF);
memory[address+2] = (unsigned char)((raw >> 24) & 0xFF);
memory[address+3] = (unsigned char)((raw >> 16) & 0xFF);
memory[address+4] = (unsigned char)((raw >> 8) & 0xFF);
memory[address+5] = (unsigned char)( raw & 0xFF);
}
@ -353,6 +366,7 @@ int Machine::fetch()
void Machine::execute() {
if (_stopped) return;
int b1 = fetch();
InstructionInfo &info = _instructionsTable[b1];
@ -445,7 +459,7 @@ bool Machine::execSICF3F4(int opcode, int ni, int x, int b, int p, int e, int op
// PC-relative, signed 12-bit
if (ea_part & 0x800) // bit 11 set?
ea_part |= 0xFFFFF000; // sign-extend
base = getPC();
base = getPC();
}
}
// format 4 (e=1): b/p ignored, ea_part is 20-bit absolute