X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=3b_sim%2Fccpu.cpp;h=3c0049bc9ca1a4684816f7d85be5cd0b221abf8b;hb=ad798a166d5abd342b031251f4a9931b81b2812d;hp=3ad97fb8bf7873ed55c6c530bb57dd4a88ab5677;hpb=31d88f201bf427d70924b9737ecdb6e0611939d3;p=calu.git diff --git a/3b_sim/ccpu.cpp b/3b_sim/ccpu.cpp index 3ad97fb..3c0049b 100644 --- a/3b_sim/ccpu.cpp +++ b/3b_sim/ccpu.cpp @@ -6,10 +6,125 @@ //void registerExtension() {}; +const char* expression = "(;.*)|(r0)|(rX)|(r1[0-5])|(r[1-5])|(r[6-9])|(0x[a-fA-F0-9]+)|([-]?\\d+)"; +const char* format = "(?1$&)" + //Return-Register: violett + "(?2\033[0m\033[35m$&\033[0m\\3:)" + // Callee-saved Register: rot + "(?4\033[0m\033[31m$&\033[0m\\3:)" + //Argument-Register: gruen + "(?5\033[0m\033[32m$&\033[0m\\3:)" + // Temporary Register: gelb + "(?6\033[0m\033[33m$&\033[0m\\3:)" + // Zahlenwerte: tuerkis + "(?7\033[0m\033[36m$&\033[0m\\3:)" + "(?8\033[0m\033[36m$&\033[0m\\3:)"; + + +string CCpu::colorifyInstr(string instr) +{ + boost::regex e; + e.assign(expression); + return boost::regex_replace(instr, e, format, boost::match_default | boost::format_all); +} + +void CCpu::registerExtension(Iext* ext) +{ + m_exts.push_back(ext); +} + +void CCpu::applyToExtensions(const vector& in) +{ + for(auto iter = m_exts.begin(); iter != m_exts.end(); ++iter) { + (*iter)->parseInput(in); + } +} + void CCpu::tick() { + // signal extensions + // Todo + m_pc = m_pc_next; m_pc_next += 4; + Iinstr* instr = this->getProg(m_pc); + + if(instr == NULL) { + throw string("Out of Instructions!"); + } + + for(auto iter = m_exts.begin(); iter != m_exts.end(); ++iter) { + (*iter)->applyTick(); + } + + if(this->conditionMet(instr->getCondition())) { + cout << color(green,black) << "Executing: " << color(white,black) << colorifyInstr(instr->toString()) << endl; + instr->execInstr(); + this->incPerfBy(instr->getClockCount()); + } + else { + cout << color(red,black) << "Didn't Execute " << color(white,black) << colorifyInstr(instr->toString()) << "; condition wasn't met" << endl; + this->incPerf(); + } + +} + +bool CCpu::conditionMet(short cond) +{ + switch(cond) { + case NOT_EQUAL: + return !this->m_Z; + break; + case EQUAL: + return this->m_Z; + break; + case NOT_OVERFLOW: + return !this->m_O; + break; + case OVER_FLOW: + return this->m_O; + break; + case NOT_CARRY: + return !this->m_C; + break; + case CARRY: + return this->m_C; + break; + case NOT_SIGNED: + return !this->m_S; + break; + case SIGNED: + return this->m_S; + break; + case ABOVE: + return (!this->m_C && !this->m_Z); + break; + case BELOW_EQ: + return (this->m_C || this->m_Z); + break; + case GREATER_EQ: + return (this->m_S == this->m_O); + break; + case LESS: + return (this->m_S != this->m_O); + break; + case GREATER: + return (!this->m_Z && (this->m_S == this->m_O)); + break; + case LESS_EQ: + return (!this->m_Z || (this->m_S != this->m_O)); + break; + case ALWAYS: + return true; + break; + case NEVER: + return false; + break; + default: + cerr << "What did you do? more than 16 values in 5 bits?!" << endl; + return false; + } + } CDat CCpu::getNextPC() const @@ -17,19 +132,148 @@ CDat CCpu::getNextPC() const return m_pc_next; } +CDat CCpu::getCurPC() const +{ + return m_pc; +} + +void CCpu::setNextPC(CDat val) +{ + m_pc_next = val; +} + +CDat CCpu::getFlags() const { + CDat psw = 0; + psw += (this->m_Z ? 1 : 0); + psw += (this->m_O ? 2 : 0); + psw += (this->m_C ? 4 : 0); + psw += (this->m_S ? 8 : 0); + return psw; +} + +void CCpu::setFlags(CDat psw) { + this->m_Z = ((psw & 0x1) != 0); + this->m_O = ((psw & 0x2) != 0); + this->m_C = ((psw & 0x4) != 0); + this->m_S = ((psw & 0x8) != 0); +} + +void CCpu::updateFlags(CDat val) { + this->m_Z = (val == 0); + this->m_S = ((val >> (BIT_LEN-1)) & 0x1); +/* this->m_C = false; + this->m_O = false; */ +} + +void CCpu::updateFlags(CDatd val, CDat a, CDat b) { + this->m_Z = (val == 0); + this->m_S = ((val >> (BIT_LEN-1)) & 0x1); + this->m_C = ((val >> (BIT_LEN)) & 0x1); + bool a_31 = ((a >> (BIT_LEN-1)) & 0x1); + bool b_31 = ((b >> (BIT_LEN-1)) & 0x1); + bool val_31 = ((val >> (BIT_LEN-1)) & 0x1); + this->m_O = ((a_31 && b_31 && !val_31) || (!a_31 && !b_31 && val_31)); +} + +void CCpu::updateCarry(bool c) +{ + this->m_C = c; +} + +bool CCpu::getCarry() +{ + return this->m_C; +} + +void CCpu::updateFlags(bool z, bool o, bool c, bool s) +{ + this->m_Z = z; + this->m_O = o; + this->m_C = c; + this->m_S = s; +} -// CDat getRegister(const short) const {}; -// void setRegister(const short, CDat&) {}; +CDat CCpu::getRegister(const int addr) const +{ + return m_reg.getDirect(addr); +} -// CDat getRAM(const short) const {}; -// void setRAM(const short, CDat&) {}; +void CCpu::setRegister(const int addr, CDat data) +{ + m_reg.setDirect(addr, data); +} + +CDat CCpu::getRAM(const int addr) const +{ + if((addr & EXT_MODEL_OFFSET) == 0) { + return m_ram.get(addr); + } + else { + CDat result = 0; + for(auto iter = m_exts.begin(); iter != m_exts.end(); ++iter) { + result = (*iter)->readData(addr); + if(result != 0) { + break; + } + } + return result; + } +} + +void CCpu::setRAM(const int addr, CDat data) +{ + if((addr & EXT_MODEL_OFFSET) == 0) { + m_ram.set(addr, data); + } + else { + for(auto iter = m_exts.begin(); iter != m_exts.end(); ++iter) { + (*iter)->loadData(addr, data); + } + } +} void CCpu::setProg(int addr, Iinstr* instr) { m_prog.set(addr, instr); } -CCpu::CCpu() : m_pc(0), m_pc_next(0), m_regfile(0), m_ram(0), m_prog(0) +Iinstr* CCpu::getProg(const int addr) const +{ + return m_prog.get(addr); +} + +int CCpu::getStack() const +{ + return this->m_stack; +} + +void CCpu::setStack(const int val) +{ + this->m_stack = val; +} + +CDat CCpu::getPerf() const +{ + return this->m_perf; +} + +void CCpu::setPerf(CDat val) +{ + this->m_perf = val; +} + +void CCpu::incPerf() +{ + this->m_perf++; +} + +void CCpu::incPerfBy(short inc) +{ + this->m_perf += inc; +} + + +CCpu::CCpu(int regs, int ram, int prog) : m_Z(false), m_S(false), m_C(false), m_O(false), m_pc(0), m_pc_next(0), m_perf(0), m_reg(regs), m_ram(ram), m_prog(prog), m_exts(0), m_stack(0) { }