added extra istructions

This commit is contained in:
zanostro 2025-11-16 02:10:14 +01:00
parent ad3078ba48
commit ba18b92116
8 changed files with 470 additions and 123 deletions

View file

@ -35,4 +35,9 @@ 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;
#endif // CONSTANTS_H

View file

@ -12,6 +12,7 @@ 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);
@ -75,4 +76,26 @@ 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

View file

@ -26,7 +26,7 @@ using std::cout;
class Machine {
public:
Machine();
Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; }
Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; _instructionsTable = instructions; }
~Machine();
int getA() const { return A; }
@ -82,16 +82,13 @@ public:
int fetch();
void execute();
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);
// Execution and speed control
int getSpeed() const;
void setSpeed(int kHz);
void start();
void stop();
void tick();
void halt();
// error handling methods
void notImplemented(string mnemonic);
@ -100,6 +97,22 @@ 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;
@ -116,6 +129,17 @@ private:
// Execution control
std::atomic<bool> running{false};
std::atomic<int> 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
};

View file

@ -66,6 +66,28 @@
#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
enum class InstructionType {
TYPE1,
@ -86,6 +108,7 @@ struct InstructionInfo {
};
extern InstructionInfo instructions[];
extern InstructionInfo instructionsEXEX[];
// Initialize the instruction table
void loadInstructionSet();

View file

@ -412,3 +412,177 @@ void wd_handler(Machine &m, int ea, AddressingMode mode)
// Write rightmost byte of A register to device
device.write(static_cast<unsigned char>(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);
}

View file

@ -21,6 +21,8 @@ Machine::Machine()
devices[1] = make_shared<OutputDevice>(std::cout);
// device 2: standard error
devices[2] = make_shared<OutputDevice>(std::cerr);
_exex_mode = false;
_instructionsTable = instructions;
}
Machine::~Machine()
@ -67,6 +69,62 @@ 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();
@ -76,6 +134,11 @@ void Machine::tick()
std::this_thread::sleep_for(delay);
}
void Machine::halt()
{
_stopped = true;
}
int Machine::getReg(int regNum) const
{
switch (regNum) {
@ -289,14 +352,16 @@ int Machine::fetch()
}
void Machine::execute() {
if (_stopped) return;
int b1 = fetch();
InstructionInfo &info = instructions[b1];
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 = instructions[opcode];
InstructionInfo &info34 = _instructionsTable[opcode];
int ni = b1 & NI_MASK;
if (info34.type == InstructionType::TYPE3_4) {
@ -329,8 +394,8 @@ void Machine::execute() {
bool Machine::execF1(int opcode)
{
if (instructions[opcode].handler) {
auto handler = reinterpret_cast<void(*)(Machine&)>(instructions[opcode].handler);
if (_instructionsTable[opcode].handler) {
auto handler = reinterpret_cast<void(*)(Machine&)>(_instructionsTable[opcode].handler);
handler(*this);
return true;
}
@ -343,8 +408,8 @@ bool Machine::execF2(int opcode, int operand)
int r1 = (operand >> 4) & 0xF;
int r2 = operand & 0xF;
if (instructions[opcode].handler) {
auto handler = reinterpret_cast<void(*)(Machine&, int, int)>(instructions[opcode].handler);
if (_instructionsTable[opcode].handler) {
auto handler = reinterpret_cast<void(*)(Machine&, int, int)>(_instructionsTable[opcode].handler);
handler(*this, r1, r2);
return true;
}
@ -362,8 +427,8 @@ bool Machine::execSICF3F4(int opcode, int ni, int x, int b, int p, int e, int op
// --- PURE SIC ---
if (mode == AddressingMode::SIC_DIRECT) {
int ea = ea_part + (x ? getX() : 0);
if (instructions[opcode].handler) {
auto h = reinterpret_cast<void(*)(Machine&, int, AddressingMode)>(instructions[opcode].handler);
if (_instructionsTable[opcode].handler) {
auto h = reinterpret_cast<void(*)(Machine&, int, AddressingMode)>(_instructionsTable[opcode].handler);
h(*this, ea, mode);
return true;
}
@ -386,8 +451,8 @@ bool Machine::execSICF3F4(int opcode, int ni, int x, int b, int p, int e, int op
// format 4 (e=1): b/p ignored, ea_part is 20-bit absolute
int ea = base + ea_part + (x ? getX() : 0);
if (instructions[opcode].handler) {
auto h = reinterpret_cast<void(*)(Machine&, int, AddressingMode)>(instructions[opcode].handler);
if (_instructionsTable[opcode].handler) {
auto h = reinterpret_cast<void(*)(Machine&, int, AddressingMode)>(_instructionsTable[opcode].handler);
h(*this, ea, mode);
return true;
}

View file

@ -9,11 +9,16 @@
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;
@ -21,61 +26,67 @@ int main()
// clear TEMP
machine.setByte(TEMP_ADDR, 0);
loadInstructionSet();
// Program (addresses):
// 0x00 LDA #1
// 0x03 LDB TEMP
// 0x06 ADDR A,B
// 0x08 RMO B,A
// 0x0A STA TEMP
// 0x0D J LOOP
cout << "SIC/XE Program: Vector add test" << endl;
// LDA #1
machine.setByte(0x00, 0x01);
machine.setByte(0x01, 0x00);
machine.setByte(0x02, 0x01);
const int VA_ADDR = 0x100; // source vector A
const int VB_ADDR = 0x200; // source vector B
const int VR_ADDR = 0x300; // result store (STVA)
// LDB TEMP
machine.setByte(0x03, 0x6B);
machine.setByte(0x04, 0x00);
machine.setByte(0x05, TEMP_ADDR);
// 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};
// ADDR A,B
machine.setByte(0x06, 0x90);
machine.setByte(0x07, 0x03);
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]);
}
// RMO B,A
machine.setByte(0x08, 0xAC);
machine.setByte(0x09, 0x30);
// 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
// STA TEMP
machine.setByte(0x0A, 0x0F);
machine.setByte(0x0B, 0x00);
machine.setByte(0x0C, TEMP_ADDR);
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
};
// J LOOP
machine.setByte(0x0D, 0x3F);
machine.setByte(0x0E, 0x00);
machine.setByte(0x0F, LOOP_ADDR);
const int PROG_START = 0x00;
for (size_t i = 0; i < sizeof(prog); ++i) {
machine.setByte(PROG_START + static_cast<int>(i), prog[i]);
}
machine.setPC(0x00);
machine.setPC(PROG_START);
cout << "Program loaded. TEMP at 0x" << std::hex << TEMP_ADDR << std::dec << endl;
cout << "Program loaded. VA@0x" << std::hex << VA_ADDR << " VB@0x" << VB_ADDR << " -> store@0x" << VR_ADDR << std::dec << endl;
// run a few iterations
for (int i = 0; i < 10; ++i) {
cout << "Iter " << (i + 1) << ": A=" << machine.getA()
<< " B=" << machine.getB()
<< " TEMP=" << machine.getByte(TEMP_ADDR);
const int MAX_STEPS = 100;
for (int i = 0; i < MAX_STEPS; ++i) {
machine.execute();
}
// advance the program by executing the next 6 instructions
for (int k = 0; k < 6; ++k) machine.execute();
cout << " -> A=" << machine.getA()
<< " B=" << machine.getB()
<< " TEMP=" << machine.getByte(TEMP_ADDR) << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// 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");
}
return 0;

View file

@ -4,74 +4,96 @@
#include <utility>
InstructionInfo instructions[0xff];
InstructionInfo instructionsEXEX[0xff];
void loadInstructionSet()
{
instructions[ADD] = {"ADD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(add_handler)};
instructions[ADDF] = {"ADDF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(addf_handler)};
instructions[ADDR] = {"ADDR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(addr_handler)};
instructions[AND] = {"AND", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(and_handler)};
instructions[CLEAR] = {"CLEAR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(clear_handler)};
instructions[COMP] = {"COMP", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(comp_handler)};
instructions[COMPF] = {"COMPF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(compf_handler)};
instructions[COMPR] = {"COMPR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(compr_handler)};
instructions[DIV] = {"DIV", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(div_handler)};
instructions[DIVF] = {"DIVF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(divf_handler)};
instructions[DIVR] = {"DIVR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(divr_handler)};
instructions[FIX] = {"FIX", InstructionType::TYPE1, reinterpret_cast<RawHandler>(fix_handler)};
instructions[FLOAT] = {"FLOAT", InstructionType::TYPE1, reinterpret_cast<RawHandler>(float_handler)};
instructions[HIO] = {"HIO", InstructionType::TYPE1, nullptr};
instructions[J] = {"J", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(j_handler)};
instructions[JEQ] = {"JEQ", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jeq_handler)};
instructions[JGT] = {"JGT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jgt_handler)};
instructions[JLT] = {"JLT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jlt_handler)};
instructions[JSUB] = {"JSUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jsub_handler)};
instructions[LDA] = {"LDA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(lda_handler)};
instructions[LDB] = {"LDB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldb_handler)};
instructions[LDCH] = {"LDCH", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldch_handler)};
instructions[LDF] = {"LDF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldf_handler)};
instructions[LDL] = {"LDL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldl_handler)};
instructions[LDS] = {"LDS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(lds_handler)};
instructions[LDT] = {"LDT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldt_handler)};
instructions[LDX] = {"LDX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldx_handler)};
instructions[LPS] = {"LPS", InstructionType::TYPE3_4, nullptr};
instructions[MUL] = {"MUL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(mul_handler)};
instructions[MULF] = {"MULF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(mulf_handler)};
instructions[MULR] = {"MULR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(mulr_handler)};
instructions[NORM] = {"NORM", InstructionType::TYPE1, reinterpret_cast<RawHandler>(norm_handler)};
instructions[OR] = {"OR", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(or_handler)};
instructions[RD] = {"RD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(rd_handler)};
instructions[RMO] = {"RMO", InstructionType::TYPE2, reinterpret_cast<RawHandler>(rmo_handler)};
instructions[RSUB] = {"RSUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(rsub_handler)};
instructions[SHIFTL] = {"SHIFTL", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftl_handler)};
instructions[SHIFTR] = {"SHIFTR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftr_handler)};
instructions[SIO] = {"SIO", InstructionType::TYPE1, nullptr};
instructions[SSK] = {"SSK", InstructionType::TYPE3_4, nullptr};
instructions[STA] = {"STA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sta_handler)};
instructions[STB] = {"STB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stb_handler)};
instructions[STCH] = {"STCH", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stch_handler)};
instructions[STF] = {"STF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stf_handler)};
instructions[STI] = {"STI", InstructionType::TYPE3_4, nullptr};
instructions[STL] = {"STL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stl_handler)};
instructions[STS] = {"STS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sts_handler)};
instructions[STSW] = {"STSW", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stsw_handler)};
instructions[STT] = {"STT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stt_handler)};
instructions[STX] = {"STX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stx_handler)};
instructions[SUB] = {"SUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sub_handler)};
instructions[SUBF] = {"SUBF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(subf_handler)};
instructions[SUBR] = {"SUBR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(subr_handler)};
instructions[SVC] = {"SVC", InstructionType::TYPE2, reinterpret_cast<RawHandler>(svc_handler)};
instructions[TIXR] = {"TIXR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(tixr_handler)};
instructions[TD] = {"TD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(td_handler)};
instructions[TIX] = {"TIX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(tix_handler)};
instructions[TIO] = {"TIO", InstructionType::TYPE1, nullptr};
instructions[WD] = {"WD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(wd_handler)};
instructions[ADD] = {"ADD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(add_handler)};
instructions[ADDF] = {"ADDF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(addf_handler)};
instructions[ADDR] = {"ADDR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(addr_handler)};
instructions[AND] = {"AND", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(and_handler)};
instructions[CLEAR] = {"CLEAR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(clear_handler)};
instructions[COMP] = {"COMP", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(comp_handler)};
instructions[COMPF] = {"COMPF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(compf_handler)};
instructions[COMPR] = {"COMPR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(compr_handler)};
instructions[DIV] = {"DIV", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(div_handler)};
instructions[DIVF] = {"DIVF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(divf_handler)};
instructions[DIVR] = {"DIVR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(divr_handler)};
instructions[FIX] = {"FIX", InstructionType::TYPE1, reinterpret_cast<RawHandler>(fix_handler)};
instructions[FLOAT] = {"FLOAT", InstructionType::TYPE1, reinterpret_cast<RawHandler>(float_handler)};
instructions[HIO] = {"HIO", InstructionType::TYPE1, nullptr};
instructions[J] = {"J", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(j_handler)};
instructions[JEQ] = {"JEQ", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jeq_handler)};
instructions[JGT] = {"JGT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jgt_handler)};
instructions[JLT] = {"JLT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jlt_handler)};
instructions[JSUB] = {"JSUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(jsub_handler)};
instructions[LDA] = {"LDA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(lda_handler)};
instructions[LDB] = {"LDB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldb_handler)};
instructions[LDCH] = {"LDCH", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldch_handler)};
instructions[LDF] = {"LDF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldf_handler)};
instructions[LDL] = {"LDL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldl_handler)};
instructions[LDS] = {"LDS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(lds_handler)};
instructions[LDT] = {"LDT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldt_handler)};
instructions[LDX] = {"LDX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldx_handler)};
instructions[LPS] = {"LPS", InstructionType::TYPE3_4, nullptr};
instructions[MUL] = {"MUL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(mul_handler)};
instructions[MULF] = {"MULF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(mulf_handler)};
instructions[MULR] = {"MULR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(mulr_handler)};
instructions[NORM] = {"NORM", InstructionType::TYPE1, reinterpret_cast<RawHandler>(norm_handler)};
instructions[OR] = {"OR", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(or_handler)};
instructions[RD] = {"RD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(rd_handler)};
instructions[RMO] = {"RMO", InstructionType::TYPE2, reinterpret_cast<RawHandler>(rmo_handler)};
instructions[RSUB] = {"RSUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(rsub_handler)};
instructions[SHIFTL] = {"SHIFTL", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftl_handler)};
instructions[SHIFTR] = {"SHIFTR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(shiftr_handler)};
instructions[SIO] = {"SIO", InstructionType::TYPE1, nullptr};
instructions[SSK] = {"SSK", InstructionType::TYPE3_4, nullptr};
instructions[STA] = {"STA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sta_handler)};
instructions[STB] = {"STB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stb_handler)};
instructions[STCH] = {"STCH", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stch_handler)};
instructions[STF] = {"STF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stf_handler)};
instructions[STI] = {"STI", InstructionType::TYPE3_4, nullptr};
instructions[STL] = {"STL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stl_handler)};
instructions[STS] = {"STS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sts_handler)};
instructions[STSW] = {"STSW", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stsw_handler)};
instructions[STT] = {"STT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stt_handler)};
instructions[STX] = {"STX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stx_handler)};
instructions[SUB] = {"SUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(sub_handler)};
instructions[SUBF] = {"SUBF", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(subf_handler)};
instructions[SUBR] = {"SUBR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(subr_handler)};
instructions[SVC] = {"SVC", InstructionType::TYPE2, reinterpret_cast<RawHandler>(svc_handler)};
instructions[TIXR] = {"TIXR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(tixr_handler)};
instructions[TD] = {"TD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(td_handler)};
instructions[TIX] = {"TIX", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(tix_handler)};
instructions[TIO] = {"TIO", InstructionType::TYPE1, nullptr};
instructions[WD] = {"WD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(wd_handler)};
// Mark uninitialized opcodes as INVALID
// Load SIC/XE/XE extended instructions
if (USE_EXTENDED_MODE) {
// Still in main table
instructions[NOP] = {"NOP", InstructionType::TYPE1, reinterpret_cast<RawHandler>(nop_handler)};
instructions[HALT] = {"HALT", InstructionType::TYPE1, reinterpret_cast<RawHandler>(halt_handler)};
instructions[XEXE] = {"XEXE", InstructionType::TYPE1, reinterpret_cast<RawHandler>(xexe_handler)};
instructionsEXEX[VADD] = {"VADD", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(vadd_handler)};
instructionsEXEX[VADDR] = {"VADDR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(vaddr_handler)};
instructionsEXEX[VSUB] = {"VSUB", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(vsub_handler)};
instructionsEXEX[VSUBR] = {"VSUBR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(vsubr_handler)};
instructionsEXEX[VMUL] = {"VMUL", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(vmul_handler)};
instructionsEXEX[VMULR] = {"VMULR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(vmulr_handler)};
instructionsEXEX[VDIV] = {"VDIV", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(vdiv_handler)};
instructionsEXEX[VDIVR] = {"VDIVR", InstructionType::TYPE2, reinterpret_cast<RawHandler>(vdivr_handler)};
instructionsEXEX[STVA] = {"STVA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stva_handler)};
instructionsEXEX[STVS] = {"STVS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stvs_handler)};
instructionsEXEX[STVT] = {"STVT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(stvt_handler)};
instructionsEXEX[LDVA] = {"LDVA", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldva_handler)};
instructionsEXEX[LDVS] = {"LDVS", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldvs_handler)};
instructionsEXEX[LDVT] = {"LDVT", InstructionType::TYPE3_4, reinterpret_cast<RawHandler>(ldvt_handler)};
}
// Mark uninitialized opcodes as INVALID
for (int i = 0; i < 0xff; ++i) {
if (instructions[i].name == nullptr) {
instructions[i] = {"INVALID", InstructionType::INVALID, nullptr};
}
if (instructions[i].name == nullptr) instructions[i] = {"INVALID", InstructionType::INVALID, nullptr};
if (instructionsEXEX[i].name == nullptr) instructionsEXEX[i] = {"INVALID", InstructionType::INVALID, nullptr};
}
}