spo/simulator_SIC_XE/src/instructions.cpp
2025-11-12 12:13:26 +01:00

381 lines
9.3 KiB
C++

#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<double>(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<int>(m.getF()));
}
void float_handler(Machine &m)
{
m.setF(static_cast<double>(m.getA()));
}
void addr_handler(Machine &m, int r1, int r2)
{
m.setReg(r2, m.getReg(r1) + m.getReg(r2));
}
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) {
if (m.getReg(r2) == 0) {
m.invalidOpcode(DIVR);
return;
}
m.setReg(r2, m.getReg(r2) / m.getReg(r1));
}
void mulr_handler(Machine &m, int r1, int r2)
{
m.setReg(r2, m.getReg(r1) * m.getReg(r2));
}
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);
}
// 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);
}
void subr_handler(Machine &m, int r1, int r2)
{
m.setReg(r2, m.getReg(r2) - m.getReg(r1));
}
// TODO: implement SVC functionality
void svc_handler(Machine &m, int n, int unused)
{
m.notImplemented("SVC");
}
void tixr_handler(Machine &m, int r1, int unused)
{
m.setX(m.getX() + 1);
int valX = m.getX();
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 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 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()));
}