From 78236d0bec463add160c1ef94042c0a529c3831d Mon Sep 17 00:00:00 2001 From: Martin Perner Date: Sun, 31 Oct 2010 13:21:00 +0100 Subject: [PATCH] sim: added cmds may be buggy on overflow and carry bit! --- 3b_sim/.gitignore | 4 + 3b_sim/Makefile.flags | 2 +- 3b_sim/ccpu.cpp | 22 ++++ 3b_sim/ccpu.hpp | 4 + 3b_sim/sim.cpp | 230 ++++++++++++++++++++++++++++++++++++--- 3c_disasm/ccpu.hpp | 1 + 3c_disasm/cdat.hpp | 1 + 3c_disasm/cmem.hpp | 1 + 3c_disasm/cpmem.hpp | 1 + 3c_disasm/dasm.cpp | 4 + 3c_disasm/instr/add.cpp | 6 +- 3c_disasm/instr/addi.cpp | 5 +- 3c_disasm/instr/subi.cpp | 5 +- 13 files changed, 265 insertions(+), 21 deletions(-) create mode 100644 3b_sim/.gitignore create mode 120000 3c_disasm/ccpu.hpp create mode 120000 3c_disasm/cdat.hpp create mode 120000 3c_disasm/cmem.hpp create mode 120000 3c_disasm/cpmem.hpp diff --git a/3b_sim/.gitignore b/3b_sim/.gitignore new file mode 100644 index 0000000..6eedf3a --- /dev/null +++ b/3b_sim/.gitignore @@ -0,0 +1,4 @@ +*.o +*.so +*.d +sim diff --git a/3b_sim/Makefile.flags b/3b_sim/Makefile.flags index 50f7e14..f79e104 100644 --- a/3b_sim/Makefile.flags +++ b/3b_sim/Makefile.flags @@ -1,4 +1,4 @@ -CC := g++ +CC := ccache g++ CPPFLAGS = -g3 -O2 -std=c++0x -Wnon-virtual-dtor -Weffc++ -pedantic -Werror -Wall -Wextra -W -Wshadow -fno-common -pedantic-errors -Wpointer-arith -Wcast-qual -Wcast-align -Woverloaded-virtual -Wswitch-default -Wempty-body -Wlogical-op diff --git a/3b_sim/ccpu.cpp b/3b_sim/ccpu.cpp index 00b84f6..148fe81 100644 --- a/3b_sim/ccpu.cpp +++ b/3b_sim/ccpu.cpp @@ -85,6 +85,11 @@ bool CCpu::conditionMet(short cond) } +CDat CCpu::getNextPC() const +{ + return m_pc_next; +} + CDat CCpu::getCurPC() const { return m_pc; @@ -95,6 +100,15 @@ 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::updateFlags(CDat val) { this->m_Z = (val == 0); this->m_S = ((val >> (BIT_LEN-1)) & 0x1); @@ -102,6 +116,14 @@ void CCpu::updateFlags(CDat val) { 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 v = (((a ^ b) >> (BIT_LEN-1)) & 0x1) ? true : false; + this->m_O = (this->m_S != v); +} + void CCpu::updateFlags(bool z, bool o, bool c, bool s) { this->m_Z = z; diff --git a/3b_sim/ccpu.hpp b/3b_sim/ccpu.hpp index e428f63..bef4f9e 100644 --- a/3b_sim/ccpu.hpp +++ b/3b_sim/ccpu.hpp @@ -35,10 +35,14 @@ class CCpu { void setProg(const int, Iinstr*); CDat getCurPC() const; + CDat getNextPC() const; void setNextPC(CDat); + CDat getFlags() const; void updateFlags(CDat); + void updateFlags(CDatd, CDat, CDat); void updateFlags(bool z, bool o, bool c, bool s); + bool conditionMet(short); diff --git a/3b_sim/sim.cpp b/3b_sim/sim.cpp index 5cc89e4..bd7f5d0 100644 --- a/3b_sim/sim.cpp +++ b/3b_sim/sim.cpp @@ -20,8 +20,12 @@ #include "SReadline/SReadline.h" using namespace swift; +#define RAM_END (1000) +#define PROG_END (1000) +#define REG_COUNT (16) + typedef boost::function &)> Func; -typedef boost::tuple CompleterElement; +typedef boost::tuple CompleterElement; typedef list MyCompleterContainer; @@ -56,7 +60,7 @@ class CHelpExec { cout << "Available commands: " << endl; for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) { - cout << (*iter).get<0>() << endl; + cout << setw(15) << (*iter).get<0>() << ": " << (*iter).get<2>() << endl; } } }; @@ -67,6 +71,10 @@ CCpu* Iinstr::m_cpu; CCpu* global_cpu = NULL; +vector breakpoints; + +bool ignoreBreak = false; + void doExit(const vector&) { exit(EXIT_SUCCESS); @@ -85,7 +93,16 @@ void execStep(const vector& in) } while(count > 0) { try { - global_cpu->tick(); + auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC()); + if(breakp == breakpoints.end() || ignoreBreak) { + global_cpu->tick(); + ignoreBreak = false; + } + else { + ignoreBreak = true; + cout << "Breakpoint " << *breakp << " hit" << endl; + break; + } } catch(std::string& e) { cerr << e << endl; @@ -94,19 +111,199 @@ void execStep(const vector& in) } } -void printReg(const vector&) +void execRun(const vector&) { - int i, start = 0, end = 15; + while(1) { + try { + auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC()); + if(breakp == breakpoints.end() || ignoreBreak) { + global_cpu->tick(); + ignoreBreak = false; + } + else { + ignoreBreak = true; + cout << "Breakpoint " << *breakp << " hit" << endl; + return; + } + } + catch(std::string& e) { + cerr << e << endl; + return; + } + } +} + +void setPC(const vector& in) +{ + CDat addr = 0; + if(in.size() == 2) { + try { + addr = lexical_cast(in.back()); + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + global_cpu->setNextPC(addr); + cout << "Set programcounter to " << addr << endl; +} + + +void printReg(const vector& in) +{ + int i, start = 0, end = REG_COUNT-1; /* Todo: * 1) make 2 columns - * 2) let use select registers to show (one register, range of registers) */ + + if(in.size() >= 2) { + try { + start = lexical_cast(in[1]); + if(start < 0 || start > (REG_COUNT-1)) { + cerr << "start is out of range" << endl; + return; + } + end = start; + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + + if(in.size() >= 3) { + try { + end = lexical_cast(in[2]); + if(start > end || end > (REG_COUNT-1)) { + cerr << "end is out of range or smaller than start" << endl; + return; + } + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } for(i = start; i <= end; i++) { - cout << setw(2) << i << ": 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getRegister(i) << std::dec << endl; + cout << setw(2) << i << ": 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getRegister(i) << " " << std::dec << setw(10) << setfill(' ') << global_cpu->getRegister(i) << endl; } } +void printRAM(const vector& in) +{ + int i, start = 0, end = 15; + /* Todo: + * 1) make 2 columns + */ + + if(in.size() >= 2) { + try { + start = lexical_cast(in[1]); + if(start < 0 || start > (RAM_END-1)) { + cerr << "start is out of range" << endl; + return; + } + end = start; + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + + if(in.size() >= 3) { + try { + end = lexical_cast(in[2]); + if(start > end || end > (RAM_END-1)) { + cerr << "end is out of range or smaller than start" << endl; + return; + } + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + + for(i = start*4; i <= end*4; i += 4) { + cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getRAM(i) << " " << std::dec << setw(10) << setfill(' ') << global_cpu->getRAM(i) << endl; + } +} + +void printPROG(const vector& in) +{ + int i, start = 0, end = 15; + /* Todo: + * 1) make 2 columns + */ + + if(in.size() >= 2) { + try { + start = lexical_cast(in[1]); + if(start < 0 || start > (PROG_END-1)) { + cerr << "start is out of range" << endl; + return; + } + end = start; + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + + if(in.size() >= 3) { + try { + end = lexical_cast(in[2]); + if(start > end || end > (PROG_END-1)) { + cerr << "end is out of range or smaller than start" << endl; + return; + } + } + catch(bad_cast&) { + cerr << "given parameter is not a number" << endl; + return; + } + } + + for(i = start*4; i <= end*4; i += 4) { + Iinstr* pi = global_cpu->getProg(i); + if(pi == NULL) { + cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": NOP" << endl; + } + else { + cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": " << std::dec << pi->toString() << endl; + } + } +} + +void setBreak(const vector& in) +{ + int addr = 0; + if(in.size() == 2) { + try { + addr = lexical_cast(in.back()); + breakpoints.push_back(addr); + } + catch(bad_cast&) { + cerr << "Given parameter is not a valid address" << endl; + } + } + else { + cerr << "Invalid parameter count!" << endl; + } +} + +void printStatus(const vector&) +{ + CDat stackp = global_cpu->getStack(); + CDat stackd = global_cpu->getRAM(stackp); + cout << "Stack pointer: " << stackp << " @stackpointer: " << stackd << endl; + cout << "PSW: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getFlags() << std::dec << endl; + +} using boost::lexical_cast; using boost::bad_lexical_cast; @@ -179,7 +376,7 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); } - CCpu cpu(16,1000,1000); + CCpu cpu(REG_COUNT, RAM_END, PROG_END); global_cpu = &cpu; @@ -293,12 +490,17 @@ int main(int argc, char* argv[]) CHelpExec HelpExec(Completers); - Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec))); - Completers.push_back(CompleterElement("quit", &doExit)); - Completers.push_back(CompleterElement("exit", &doExit)); - Completers.push_back(CompleterElement("q", &doExit)); - Completers.push_back(CompleterElement("step [count]",&execStep)); - Completers.push_back(CompleterElement("reg",&printReg)); + Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec), "Prints this message")); + Completers.push_back(CompleterElement("quit", &doExit, "Exits program")); + Completers.push_back(CompleterElement("exit", &doExit, "Exits program")); + Completers.push_back(CompleterElement("step [count]",&execStep, "Runs [count] ticks. if count is not given one tick is executed.")); + Completers.push_back(CompleterElement("dre [s] [e]",&printReg, "Prints registers. if s is given, only register s is printed. if s and e are given the registers from s to e are printed. if omitted all registers a printed.")); + Completers.push_back(CompleterElement("dra [s] [e]",&printRAM, "Prints RAM. if s is given, only RAM-Addr. s is printed. if s and e are given the RAM-Addrs from s to e are printed. if omitted the first 16 RAM-Addrs are printed.")); + Completers.push_back(CompleterElement("dpr [s] [e]",&printPROG, "Prints program. if s is given, only Prog-Addr. s is printed. if s and e are given the Prog-Addrs from s to e are printed. if omitted the first 16 Prog-Addrs are printed.")); + Completers.push_back(CompleterElement("break addr",&setBreak, "Sets a breakpoint for address addr.")); + Completers.push_back(CompleterElement("run",&execRun, "Runs till next breakpoint or end of program.")); + Completers.push_back(CompleterElement("setpc [num]",&setPC, "Sets PC to num. if num is omitted 0 is used.")); + Completers.push_back(CompleterElement("status",&printStatus, "Prints status of CPU.")); Reader.RegisterCompletions(Completers); diff --git a/3c_disasm/ccpu.hpp b/3c_disasm/ccpu.hpp new file mode 120000 index 0000000..e4fac89 --- /dev/null +++ b/3c_disasm/ccpu.hpp @@ -0,0 +1 @@ +../3b_sim/ccpu.hpp \ No newline at end of file diff --git a/3c_disasm/cdat.hpp b/3c_disasm/cdat.hpp new file mode 120000 index 0000000..fb00d74 --- /dev/null +++ b/3c_disasm/cdat.hpp @@ -0,0 +1 @@ +../3b_sim/cdat.hpp \ No newline at end of file diff --git a/3c_disasm/cmem.hpp b/3c_disasm/cmem.hpp new file mode 120000 index 0000000..88d7c7f --- /dev/null +++ b/3c_disasm/cmem.hpp @@ -0,0 +1 @@ +../3b_sim/cmem.hpp \ No newline at end of file diff --git a/3c_disasm/cpmem.hpp b/3c_disasm/cpmem.hpp new file mode 120000 index 0000000..d17e3dc --- /dev/null +++ b/3c_disasm/cpmem.hpp @@ -0,0 +1 @@ +../3b_sim/cpmem.hpp \ No newline at end of file diff --git a/3c_disasm/dasm.cpp b/3c_disasm/dasm.cpp index 177da6e..a11d4f5 100644 --- a/3c_disasm/dasm.cpp +++ b/3c_disasm/dasm.cpp @@ -7,6 +7,7 @@ #include #include "disasm.h" + #include "CInstrFactory.hpp" using boost::lexical_cast; @@ -19,6 +20,9 @@ namespace po = boost::program_options; std::string progName; + +CCpu* Iinstr::m_cpu; + int main(int argc, char* argv[]) { progName = argv[0]; diff --git a/3c_disasm/instr/add.cpp b/3c_disasm/instr/add.cpp index 6651989..4131932 100644 --- a/3c_disasm/instr/add.cpp +++ b/3c_disasm/instr/add.cpp @@ -59,9 +59,11 @@ void Cadd::evalInstr() void Cadd::execInstr() { //cout << "should exec " << this->toString() << endl; - CDat val = this->m_cpu->getRegister(m_ra) + this->m_cpu->getRegister(m_rb); + CDat ra = this->m_cpu->getRegister(m_ra); + CDat rb = this->m_cpu->getRegister(m_rb); + CDatd val = ra + rb; this->m_cpu->setRegister(m_rd, val); - this->m_cpu->updateFlags(val); + this->m_cpu->updateFlags(val, ra, rb); } std::string Cadd::toString() diff --git a/3c_disasm/instr/addi.cpp b/3c_disasm/instr/addi.cpp index 2bcab65..9b9b44f 100644 --- a/3c_disasm/instr/addi.cpp +++ b/3c_disasm/instr/addi.cpp @@ -63,9 +63,10 @@ void Caddi::evalInstr() void Caddi::execInstr() { //cout << "should exec " << this->toString() << endl; - CDat reg = this->m_cpu->getRegister(m_ra) + this->m_imm; + CDat ra = this->m_cpu->getRegister(m_ra); + CDatd reg = ra + this->m_imm; this->m_cpu->setRegister(m_rd, reg); - this->m_cpu->updateFlags(reg); + this->m_cpu->updateFlags(reg, ra, this->m_imm); } std::string Caddi::toString() diff --git a/3c_disasm/instr/subi.cpp b/3c_disasm/instr/subi.cpp index 90bdd5f..69ba7e1 100644 --- a/3c_disasm/instr/subi.cpp +++ b/3c_disasm/instr/subi.cpp @@ -62,9 +62,10 @@ void Csubi::evalInstr() void Csubi::execInstr() { //cout << "should exec " << this->toString() << endl; - CDat reg = this->m_cpu->getRegister(m_ra) - this->m_imm; + CDat ra = this->m_cpu->getRegister(m_ra); + CDatd reg = ra - this->m_imm; this->m_cpu->setRegister(m_rd, reg); - this->m_cpu->updateFlags(reg); + this->m_cpu->updateFlags(reg, ra, this->m_imm); } std::string Csubi::toString() -- 2.25.1