sim: added cmds
authorMartin Perner <martin@perner.cc>
Sun, 31 Oct 2010 12:21:00 +0000 (13:21 +0100)
committerMartin Perner <martin@perner.cc>
Sun, 31 Oct 2010 12:39:57 +0000 (13:39 +0100)
may be buggy on overflow and carry bit!

13 files changed:
3b_sim/.gitignore [new file with mode: 0644]
3b_sim/Makefile.flags
3b_sim/ccpu.cpp
3b_sim/ccpu.hpp
3b_sim/sim.cpp
3c_disasm/ccpu.hpp [new symlink]
3c_disasm/cdat.hpp [new symlink]
3c_disasm/cmem.hpp [new symlink]
3c_disasm/cpmem.hpp [new symlink]
3c_disasm/dasm.cpp
3c_disasm/instr/add.cpp
3c_disasm/instr/addi.cpp
3c_disasm/instr/subi.cpp

diff --git a/3b_sim/.gitignore b/3b_sim/.gitignore
new file mode 100644 (file)
index 0000000..6eedf3a
--- /dev/null
@@ -0,0 +1,4 @@
+*.o
+*.so
+*.d
+sim
index 50f7e14ec8e5d9cf9b59cffca3773a6669248966..f79e104fc5667510e70c4885dffaff6b3a40a1d7 100644 (file)
@@ -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
 
index 00b84f6e6f6c24cfaa5b82ec53dc64c8a104271e..148fe8170198214c7b3af4d8034cf6de54094196 100644 (file)
@@ -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;
index e428f630dd637dcf0e5cdbcb5c53af1ed0140316..bef4f9e692905e91c3b8fdbc53d0dabeb1996e30 100644 (file)
@@ -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);
 
index 5cc89e44486a0b1f77bd038805bc4b41fd6d2d43..bd7f5d0f48edbc341835885e7d3f0b5a759289af 100644 (file)
 #include "SReadline/SReadline.h"
 using namespace swift;
 
+#define RAM_END (1000)
+#define PROG_END (1000)
+#define REG_COUNT (16)
+
 typedef boost::function<void (const vector<string> &)> Func;
-typedef boost::tuple<string, Func> CompleterElement;
+typedef boost::tuple<string, Func, string> CompleterElement;
 
 typedef list<CompleterElement> 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<CDat> breakpoints;
+
+bool ignoreBreak = false;
+
 void doExit(const vector<string>&)
 {
        exit(EXIT_SUCCESS);
@@ -85,7 +93,16 @@ void execStep(const vector<string>& 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<string>& in)
        }
 }
 
-void printReg(const vector<string>&)
+void execRun(const vector<string>&)
 {
-       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<string>& in)
+{
+       CDat addr = 0;
+       if(in.size() == 2) {
+               try {
+                       addr = lexical_cast<uint32_from_hex>(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<string>& 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<int>(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<int>(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<string>& in)
+{
+       int i, start = 0, end = 15;
+       /* Todo: 
+        * 1) make 2 columns
+        */
+
+       if(in.size() >= 2) {
+               try {
+                       start = lexical_cast<int>(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<int>(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<string>& in)
+{
+       int i, start = 0, end = 15;
+       /* Todo: 
+        * 1) make 2 columns
+        */
+
+       if(in.size() >= 2) {
+               try {
+                       start = lexical_cast<int>(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<int>(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<string>& in)
+{
+       int addr = 0;
+       if(in.size() == 2) {
+               try {
+                       addr = lexical_cast<uint32_from_hex>(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<string>&)
+{
+       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 (symlink)
index 0000000..e4fac89
--- /dev/null
@@ -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 (symlink)
index 0000000..fb00d74
--- /dev/null
@@ -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 (symlink)
index 0000000..88d7c7f
--- /dev/null
@@ -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 (symlink)
index 0000000..d17e3dc
--- /dev/null
@@ -0,0 +1 @@
+../3b_sim/cpmem.hpp
\ No newline at end of file
index 177da6e6d7d3c40a44a704c03d1866cf212e25a0..a11d4f51cc6c5082e9a98cf2e6ac836ffed1b692 100644 (file)
@@ -7,6 +7,7 @@
 #include <map>
 #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];
index 6651989f6a656e57904fa68e3bdb490950a9cc34..413193236479a821769d65d8f5178068e50722f1 100644 (file)
@@ -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()
index 2bcab659797840cbf4ce6373a1f0bec2254fc0b5..9b9b44fae264787f08ab59a9a4c21565eaee26a6 100644 (file)
@@ -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()
index 90bdd5f95e72df6444b1783de2f58f30801709c4..69ba7e1029526eb08dcfceb9f0ca05479ebf7416 100644 (file)
@@ -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()