spo/ass3/simulator_SIC_XE/src/node.cpp
2025-12-21 17:23:05 +01:00

121 lines
No EOL
4.2 KiB
C++

#include "node.h"
#include <sstream>
#include <iomanip>
#include <algorithm>
string Node::toString() const {
std::ostringstream oss;
if (!_label.empty()) oss << _label << " ";
if (_mnemonic) oss << _mnemonic->toString() << " ";
if (!_comment.empty()) oss << "." << _comment;
return oss.str();
}
std::string Mnemonic::toString() const {
std::ostringstream oss;
oss << "[OP:" << std::hex << (int)_opcode << "]";
if (_extended) oss << "+";
// Print operands
for (size_t i = 0; i < _operands.size(); ++i) {
if (i > 0) oss << ",";
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Empty>) {
// nothing
} else if constexpr (std::is_same_v<T, Register>) {
oss << "R" << arg.num;
} else if constexpr (std::is_same_v<T, Immediate>) {
oss << "#" << arg.value;
} else if constexpr (std::is_same_v<T, SymbolRef>) {
oss << arg.name;
if (arg.indexed) oss << ",X";
}
}, _operands[i]);
}
return oss.str();
}
string InstructionNode::toString() const {
std::ostringstream oss;
if (!_label.empty()) oss << _label << " ";
if (_mnemonic) oss << _mnemonic->toString();
if (!_comment.empty()) oss << " ." << _comment;
return oss.str();
}
string CommentNode::toString() const {
return "." + _comment;
}
string DirectiveNode::toString() const {
std::ostringstream oss;
if (!_label.empty()) oss << _label << " ";
switch (_kind) {
case DirectiveKind::START: oss << "START"; break;
case DirectiveKind::END: oss << "END"; break;
case DirectiveKind::BASE: oss << "BASE"; break;
case DirectiveKind::NOBASE: oss << "NOBASE"; break;
case DirectiveKind::EQU: oss << "EQU"; break;
case DirectiveKind::ORG: oss << "ORG"; break;
case DirectiveKind::LTORG: oss << "LTORG"; break;
case DirectiveKind::EXTDEF: oss << "EXTDEF"; break;
case DirectiveKind::EXTREF: oss << "EXTREF"; break;
case DirectiveKind::CSECT: oss << "CSECT"; break;
}
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>) {
// no arg
} else if constexpr (std::is_same_v<T, int>) {
oss << " " << std::hex << arg;
} else if constexpr (std::is_same_v<T, std::string>) {
oss << " " << arg;
} else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
for (size_t i = 0; i < arg.size(); ++i) {
if (i > 0) oss << ",";
oss << arg[i];
}
}
}, _arg);
if (!_comment.empty()) oss << " ." << _comment;
return oss.str();
}
string DataNode::toString() const {
std::ostringstream oss;
if (!_label.empty()) oss << _label << " ";
switch (_kind) {
case DataKind::WORD: oss << "WORD"; break;
case DataKind::BYTE: oss << "BYTE"; break;
case DataKind::RESW: oss << "RESW"; break;
case DataKind::RESB: oss << "RESB"; break;
}
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>) {
// no value
} else if constexpr (std::is_same_v<T, int>) {
oss << " " << arg;
} else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
// Try to display as string if all printable ASCII
bool isPrintable = !arg.empty() && std::all_of(arg.begin(), arg.end(),
[](uint8_t b) { return b >= 32 && b <= 126; });
if (isPrintable) {
oss << " C'";
for (uint8_t b : arg) oss << static_cast<char>(b);
oss << "'";
} else {
// Display as hex
oss << " X'";
for (uint8_t b : arg) {
oss << std::hex << std::setw(2) << std::setfill('0') << (int)b;
}
oss << "'";
}
}
}, _value);
if (!_comment.empty()) oss << " ." << _comment;
return oss.str();
}