147 lines
No EOL
3.6 KiB
C++
147 lines
No EOL
3.6 KiB
C++
#ifndef MACHINE_H
|
|
#define MACHINE_H
|
|
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
|
|
|
|
#include "constants.h"
|
|
#include "device.h"
|
|
#include "input_device.h"
|
|
#include "output_device.h"
|
|
#include "file_device.h"
|
|
#include "opcode.h"
|
|
#include "utils.h"
|
|
|
|
using std::string;
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::cout;
|
|
|
|
|
|
class Machine {
|
|
public:
|
|
Machine();
|
|
Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; _instructionsTable = instructions; }
|
|
~Machine();
|
|
|
|
int getA() const { return A; }
|
|
void setA(int value) { A = toSIC24(value); }
|
|
|
|
int getB() const { return B; }
|
|
void setB(int value) { B = toSIC24(value); }
|
|
|
|
int getX() const { return X; }
|
|
void setX(int value) { X = toSIC24(value); }
|
|
|
|
int getL() const { return L; }
|
|
void setL(int value) { L = toSIC24(value); }
|
|
|
|
int getS() const { return S; }
|
|
void setS(int value) { S = toSIC24(value); }
|
|
|
|
int getT() const { return T; }
|
|
void setT(int value) { T = toSIC24(value); }
|
|
|
|
// PC is an address → don't mask to 24 unless you want 24-bit addressing
|
|
int getPC() const { return PC; }
|
|
void setPC(int value) { PC = value; }
|
|
|
|
// status word: keep as-is
|
|
int getSW() const { return SW; }
|
|
void setSW(int value) { SW = value; }
|
|
|
|
double getF() const { return F; }
|
|
void setF(double value) { F = value; }
|
|
|
|
int getReg(int regNum) const;
|
|
void setReg(int regNum, int value);
|
|
|
|
// Memory access methods
|
|
int getByte(int address);
|
|
void setByte(int address, int value);
|
|
|
|
int getWord(int address);
|
|
void setWord(int address, int value);
|
|
|
|
double getFloat(int address);
|
|
void setFloat(int address, double value);
|
|
|
|
|
|
// Device access methods
|
|
Device& getDevice(int num);
|
|
void setDevice(int num, std::shared_ptr<Device> device);
|
|
// Set a file device at index `num` using the provided filename.
|
|
void setFileDevice(int num, const std::string &filename);
|
|
|
|
// Fetch and execute instructions
|
|
int fetch();
|
|
void execute();
|
|
|
|
// 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);
|
|
void invalidOpcode(int opcode);
|
|
void invalidAddressing();
|
|
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;
|
|
double F;
|
|
|
|
// memory
|
|
unsigned char memory[MEMORY_SIZE];
|
|
|
|
// devices
|
|
std::vector<std::shared_ptr<Device>> devices;
|
|
// fallback device returned when device slot is empty/invalid
|
|
Device fallbackDevice;
|
|
|
|
// 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
|
|
};
|
|
|
|
|
|
|
|
#endif // MACHINE_H
|