#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;
{
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;
}
}
};
CCpu* global_cpu = NULL;
+vector<CDat> breakpoints;
+
+bool ignoreBreak = false;
+
void doExit(const vector<string>&)
{
exit(EXIT_SUCCESS);
}
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;
}
}
-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;
exit(EXIT_FAILURE);
}
- CCpu cpu(16,1000,1000);
+ CCpu cpu(REG_COUNT, RAM_END, PROG_END);
global_cpu = &cpu;
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);