232 lines
No EOL
6.7 KiB
C++
232 lines
No EOL
6.7 KiB
C++
#include <array>
|
|
#include <stdexcept>
|
|
#include "device.h"
|
|
#include "inputDevice.h"
|
|
#include "outputDevice.h"
|
|
#include "fileDevice.h"
|
|
#include "opcode.h"
|
|
#include <memory>
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
class machine {
|
|
public:
|
|
//zaporedne stevilke registrov, ne njihove vrednosti
|
|
static const int A = 0;
|
|
static const int X = 1;
|
|
static const int L = 2;
|
|
static const int B = 3;
|
|
static const int S = 4;
|
|
static const int T = 5;
|
|
static const double F = 6;
|
|
static const int PC = 8;
|
|
static const int SW = 9;
|
|
static const int CC_LT = 0x00; //manjse
|
|
static const int CC_EQ = 0x40; //enako
|
|
static const int CC_GT = 0x80; //vecje
|
|
static const int MAX_ADRESS = 1048575;
|
|
private:
|
|
array<int, 10> registri{}; //tukaj so shranjene pa vrednosti registrov
|
|
double F_val = 0.0;
|
|
array<uint8_t, MAX_ADRESS> pomnilnik{};
|
|
array<unique_ptr<Device>, 256> naprave{}; //treba s pointerji zaradi dedovanja
|
|
|
|
|
|
public:
|
|
machine() {
|
|
registri.fill(0); //konstruktor -> vsi registri so 0 na zacetku
|
|
|
|
naprave[0] = make_unique<InputDevice>(cin); //0 = std vhod
|
|
naprave[1] = make_unique<InputDevice>(cout); //1 = std izhod
|
|
naprave[2] = make_unique<InputDevice>(cerr); //2 = std izhod za napake
|
|
|
|
for (int i = 3; i < 256; i++) { //inicializacija ostalih naprav
|
|
string fname = "file" + to_string(i) + ".dat";
|
|
naprave[i] = make_unique<fileDevice>(fname);
|
|
}
|
|
}
|
|
|
|
//getterji, setterji
|
|
int getA() {return registri[A];}
|
|
void setA(int a) {registri[A] = a;}
|
|
|
|
int getX() {return registri[X];}
|
|
void setX(int x) {registri[X] = x;}
|
|
|
|
int getL() {return registri[L];}
|
|
void setL(int l) {registri[L] = l;}
|
|
|
|
int getB() {return registri[B];}
|
|
void setB(int b) {registri[B] = b;}
|
|
|
|
int getS() {return registri[S];}
|
|
void setS(int s) {registri[S] = s;}
|
|
|
|
int getT() {return registri[T];}
|
|
void setT(int t) {registri[T] = t;}
|
|
|
|
double getF() {return F_val;}
|
|
void setF(double f) {F_val = f;}
|
|
|
|
int getPC() {return registri[PC];}
|
|
void setPC(int pc) {registri[PC] = pc;}
|
|
|
|
int getSW() {return registri[SW];}
|
|
void setSW(int sw) {registri[SW] = sw;}
|
|
|
|
int getReg(int r) {
|
|
return r!=6 ? registri[r] : F_val;
|
|
}
|
|
void setReg(int r, int val) {
|
|
if (r == 6) {
|
|
F_val = val;
|
|
} else {
|
|
registri[r] = val;
|
|
}
|
|
}
|
|
|
|
int getByte(int adr) {
|
|
return (adr <= MAX_ADRESS && adr >= 0) ? pomnilnik[adr] : throw out_of_range("Naslov je izven pomnilniškega obmocja: " + to_string(adr));
|
|
}
|
|
void setByte(int adr, int val) {
|
|
if (adr < 0 || adr > MAX_ADRESS) throw out_of_range("Naslov je izven pomnilniškega obmocja: " + to_string(adr));
|
|
if (val < 0 || val > 255) throw invalid_argument("Byte ima vrednost med 0 in 255.");
|
|
pomnilnik[adr] = static_cast<uint8_t>(val);
|
|
|
|
}
|
|
|
|
int getWord(int adr) {
|
|
if (adr < 0 || adr + 2 > MAX_ADRESS) throw out_of_range("Beseda je izven pomnilniškega območja: " + to_string(adr+2));
|
|
|
|
int byte1 = pomnilnik[adr];
|
|
int byte2 = pomnilnik[adr+1];
|
|
int byte3 = pomnilnik[adr+2];
|
|
|
|
return (byte1 << 16) | (byte2 << 8) | byte3;
|
|
}
|
|
|
|
void setWord(int adr, int val) {
|
|
if (adr < 0 || adr + 2 > MAX_ADRESS) throw out_of_range("Beseda je izven pomnilniškega območja: " + to_string(adr+2));
|
|
if (val < 0 || val > 0xFFFFFF) throw invalid_argument("Beseda mora imeti vrednost med 0 in 0xFFFFFF.");
|
|
|
|
pomnilnik[adr] = (val >> 16) & 0xFF; //val = 0x00123456 -> hočemo 12, val >> 16 -> 0x00000012 & 0x000000ff = 0x12
|
|
pomnilnik[adr+1] = (val >> 8) & 0xFF;
|
|
pomnilnik[adr+2] = (val) & 0xFF;
|
|
}
|
|
|
|
Device& getDevice(uint8_t dev) {
|
|
if (dev > 255)
|
|
throw out_of_range("Naprava ne obstaja, izberite napravo med 0 in 255");
|
|
|
|
if (!naprave[dev])
|
|
throw runtime_error("Naprava ni inicializirana");
|
|
|
|
return *naprave[dev]; //rabmo returnat pointer, ker nase naprave so shranjene kakor unique pointerji
|
|
}
|
|
|
|
|
|
void setDevice(uint8_t num, unique_ptr<Device> dev) {
|
|
if (num > 255)
|
|
throw out_of_range("Naprava ne obstaja, izberite napravo med 0 in 255");
|
|
|
|
naprave[num] = move(dev);
|
|
}
|
|
|
|
void setFileDevice(uint8_t num, string filename) {
|
|
if (num <= 2 || num > 255) {
|
|
throw out_of_range("Samo naprave med 3 in 255 imajo lahko poljubno ime");
|
|
}
|
|
naprave[num] = make_unique<fileDevice>(filename);
|
|
}
|
|
|
|
void notImplemented(string mnemonic) {
|
|
throw runtime_error("Mnemonic ni implementiran: " + mnemonic);
|
|
}
|
|
|
|
void invalidOpcode (int opcode) {
|
|
throw invalid_argument("Opcode ne obstaja: " + to_string(opcode) + ".");
|
|
}
|
|
|
|
void invalidAdressing() {
|
|
throw invalid_argument("Ta način naslavljanja ni podprt.");
|
|
}
|
|
|
|
uint8_t fetch() {
|
|
return getByte(registri[PC]++);
|
|
}
|
|
|
|
void execute() {
|
|
uint8_t opcode8 = fetch();
|
|
uint8_t opcode6 = opcode8 & 0xFC;
|
|
|
|
auto it = Opcode::OPCODES.find(opcode6);
|
|
if (it == Opcode::OPCODES.end()) {
|
|
invalidOpcode(opcode6);
|
|
return;
|
|
}
|
|
|
|
InstructionInfo ii = it->second;
|
|
bool uspesno = false;
|
|
|
|
switch (ii.format) {
|
|
case 1:
|
|
uspesno = execF1(opcode8, ii.mnemonic);
|
|
break;
|
|
|
|
case 2: {
|
|
uint8_t operand = fetch();
|
|
uspesno = execF2(opcode8, operand, ii.mnemonic);
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
uint8_t b2 = fetch();
|
|
uint8_t b3 = fetch();
|
|
uspesno = execSIC_F3_F4(opcode8, b2, b3, ii.mnemonic);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (uspesno) return;
|
|
else {}
|
|
}
|
|
|
|
|
|
|
|
bool execF1(uint8_t opcode, string mnemonic){
|
|
|
|
}
|
|
|
|
bool execF2(uint8_t opcode, uint8_t operand, string mnemonic){
|
|
uint8_t r1 = (operand & 0xF0) >> 4;
|
|
uint8_t r2 = (operand & 0x0F);
|
|
|
|
|
|
}
|
|
|
|
bool execSIC_F3_F4(uint8_t byte1, uint8_t byte2, uint8_t byte3, string mnemonic) {
|
|
uint8_t n = (byte1 >> 7) & 1;
|
|
uint8_t i = (byte1 >> 6) & 1;
|
|
uint8_t x = (byte2 >> 7) & 1;
|
|
uint8_t b = (byte2 >> 6) & 1;
|
|
uint8_t p = (byte2 >> 5) & 1;
|
|
uint8_t e = (byte2 >> 4) & 1;
|
|
|
|
if (n == 0 && i == 0) {
|
|
//imamo format SIC
|
|
} else if (e == 1) {
|
|
//imamo format 4
|
|
} else {
|
|
//imamo format 3
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int main() {
|
|
return 0;
|
|
} |