#include #include #include "machine.h" #include "device.h" #include "inputDevice.h" #include "outputDevice.h" #include "fileDevice.h" #include "opcode.h" #include #include #include #include using namespace std; machine::machine() { registri.fill(0); //konstruktor -> vsi registri so 0 na zacetku naprave[0] = make_unique(cin); //0 = std vhod naprave[1] = make_unique(cout); //1 = std izhod naprave[2] = make_unique(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(fname); } ukaziF2 = { {"ADDR", [&](int r1, int r2){setReg(r2, getReg(r1)+getReg(r2)); return true;}}, {"SUBR", [&](int r1, int r2){setReg(r2, getReg(r2)-getReg(r1)); return true;}}, {"MULR", [&](int r1, int r2){setReg(r2, getReg(r2)*getReg(r1)); return true;}}, {"DIVR", [&](int r1, int r2){setReg(r2, getReg(r2)/getReg(r1)); return true;}}, {"CLEAR", [&](int r1, int){setReg(r1, 0); return true; }}, {"COMPR", [&](int r1, int r2){int v1 = getReg(r1), v2 = getReg(r2); if (v1 < v2) setSW(CC_LT); else if (v1 == v2) setSW(CC_EQ); else setSW(CC_GT); return true;}}, {"RMO", [&](int r1, int r2){setReg(r2, getReg(r1)); return true;}}, {"SHIFTR", [&](int r1, int n){int val = getReg(r1);setReg(r1, val >> n);return true;}}, {"SHIFTL", [&](int r1, int n){int val = getReg(r1);setReg(r1, val << n);return true;}}, {"TIXR", [&](int r1, int){int x = getX()+1; setX(x); int v2 = getReg(r1); if (x < v2) setSW(CC_LT); else if (x == v2) setSW(CC_EQ); else setSW(CC_GT); return true;}}, }; ukaziSICF3F4 = { {"ADD", [&](int m){setA(getA()+getWord(m)); return true;}}, {"SUB", [&](int m){setA(getA()-getWord(m)); return true;}}, {"MUL", [&](int m){setA(getA()*getWord(m)); return true;}}, {"DIV", [&](int m){if(getWord(m) == 0) divisionByZero();setA(getA()/getWord(m)); return true;}}, {"AND", [&](int m){setA(getA()&getWord(m)); return true;}}, {"OR", [&](int m){setA(getA()|getWord(m)); return true;}}, {"COMP", [&](int m){int a = getA(); int b = getWord(m); if (a < b) setSW(CC_LT); else if (a == b) setSW(CC_EQ); else setSW(CC_GT); return true;}}, {"J", [&](int m){setPC(m); return true;}}, {"JEQ", [&](int m){if (getSW() == CC_EQ){setPC(m);} else {setPC(getPC()+1);} return true;}}, {"JGT", [&](int m){if (getSW() == CC_GT) {setPC(m);} else {setPC(getPC()+1);} return true;}}, {"JLT", [&](int m){if (getSW() == CC_LT){setPC(m);} else{setPC(getPC()+1);} return true;}}, {"JSUB", [&](int m){setL(getPC()); setPC(m); return true;}}, {"RSUB", [&](int m){setPC(getL()); return true;}}, {"LDA", [&](int m){setA(getWord(m)); return true;}}, {"LDB", [&](int m){setB(getWord(m)); return true;}}, {"LDT", [&](int m){setT(getWord(m)); return true;}}, {"LDX", [&](int m){setX(getWord(m)); return true;}}, {"LDS", [&](int m){setS(getWord(m)); return true;}}, {"LDL", [&](int m){setL(getWord(m)); return true;}}, {"LDCH", [&](int m){setA(getByte(m)); return true;}}, //POPRAVIT {"STA", [&](int m){setWord(m, getA()); return true;}}, {"STB", [&](int m){setWord(m, getB()); return true;}}, {"STT", [&](int m){setWord(m, getT()); return true;}}, {"STX", [&](int m){setWord(m, getX()); return true;}}, {"STL", [&](int m){setWord(m, getL()); return true;}}, {"STS", [&](int m){setWord(m, getS()); return true;}}, {"STCH", [&](int m){setByte(m, getA()); return true;}}, //POPRAVIT {"TIX", [&](int m){setX(getX()+1); if (getX() < getWord(m)) setSW(CC_LT); else if (getX() == getWord(m)) setSW(CC_EQ); else setSW(CC_GT); return true;}}, {"WD", [&](int m){return true;}},//POPRAVIT {"RD", [&](int m){return true;}},//POPRAVIT }; } //machine::getterji, setterji int machine::getA() {return registri[A];} void machine::setA(int a) {registri[A] = a;} int machine::getX() {return registri[X];} void machine::setX(int x) {registri[X] = x;} int machine::getL() {return registri[L];} void machine::setL(int l) {registri[L] = l;} int machine::getB() {return registri[B];} void machine::setB(int b) {registri[B] = b;} int machine::getS() {return registri[S];} void machine::setS(int s) {registri[S] = s;} int machine::getT() {return registri[T];} void machine::setT(int t) {registri[T] = t;} double machine::getF() {return F_val;} void machine::setF(double f) {F_val = f;} int machine::getPC() {return registri[PC];} void machine::setPC(int pc) {registri[PC] = pc;} int machine::getSW() {return registri[SW];} void machine::setSW(int sw) {registri[SW] = sw;} int machine::getReg(int r) { return r!=6 ? registri[r] : F_val; } void machine::setReg(int r, int val) { if (r == 6) { F_val = val; } else { registri[r] = val; } } int machine::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 machine::setByte(int adr, int val) { if (adr < 0 || adr > MAX_ADRESS) outOfMemoryRange(adr); if (val < 0 || val > 255) throw invalid_argument("Byte ima vrednost med 0 in 255."); pomnilnik[adr] = static_cast(val); } int machine::getWord(int adr) { if (adr < 0 || adr + 2 > MAX_ADRESS) outOfMemoryRange(adr+2); int byte1 = pomnilnik[adr]; int byte2 = pomnilnik[adr+1]; int byte3 = pomnilnik[adr+2]; return (byte1 << 16) | (byte2 << 8) | byte3; } void machine::setWord(int adr, int val) { if (adr < 0 || adr + 2 > MAX_ADRESS) outOfMemoryRange(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& machine::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 machine::setDevice(uint8_t num, unique_ptr dev) { if (num > 255) throw out_of_range("Naprava ne obstaja, izberite napravo med 0 in 255"); naprave[num] = move(dev); } void machine::setFileDevice(uint8_t num, const 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(filename); } int getUN(int n, int x, int b, int p, int e, int operand) { //NEED TO IMPLEMENT return 1; } void machine::outOfMemoryRange(int memory) { throw out_of_range("Naslov je izven pomnilniškega obmocja: " + to_string(memory)); } void machine::notImplemented(const string& mnemonic) { throw runtime_error("Mnemonic ni implementiran: " + mnemonic); } void machine::invalidOpcode (int opcode) { throw invalid_argument("Opcode ne obstaja: " + to_string(opcode) + "."); } void machine::invalidAdressing() { throw invalid_argument("Ta način naslavljanja ni podprt."); } void machine::invalidRegister(const string& mnemonic, int r1, int r2) { throw invalid_argument("Neveljaven register v ukazu" + mnemonic + " r1 = " + to_string(r1) + " r2 = " + to_string(r2)); } uint8_t machine::fetch() { return machine::getByte(registri[PC]++); } void machine::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 { throw runtime_error("Izvajanje ukaza je bilo neuspešno"); } } ////////////////////////////////////////////////////////////////////////////////// //TO DO, racunanje uporabnih naslovov!!!! bool machine::execF1(uint8_t opcode, const string& mnemonic){ //FIX, FLOAT, HIO, TIO, SIO, NORM auto it = Opcode::OPCODES.find(opcode); InstructionInfo ii = it->second; string name = ii.mnemonic; if (name == "FIX") { setA(static_cast(getF())); return true; } else if (name == "FLOAT") { setF(static_cast(getA())); return true; } else if (name == "HIO") { //halt I/0 na kanalu (A) return true; } else if (name == "TIO") { //test I/O na kanalu (A) return true; } else if (name == "SIO") { //start I/O na kanalu (A), adress kanala je dan na (S) return true; } else if (name == "NORM") { //normalizirej (F), v c++ so ze vsa double stevila normalizirana return true; } } bool machine::execF2(uint8_t opcode, uint8_t operand, const string& mnemonic){ uint8_t r1 = (operand & 0xF0) >> 4; uint8_t r2 = (operand & 0x0F); auto it = ukaziF2.find(mnemonic); if (it == ukaziF2.end()) notImplemented(mnemonic); return false; if (r1 > 9 || r2 > 9 || r1 < 0 || r2 < 0) invalidRegister(mnemonic, r1, r2); return false; return it->second(r1, r2); } bool machine::execSIC_F3_F4(uint8_t byte1, uint8_t byte2, uint8_t byte3, const 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 } } //TO DO ///////////////////////////////////////////////////////////////////////////////////// int main() { return 0; }