4 #include <boost/tokenizer.hpp>
5 #include <boost/program_options.hpp>
6 #include <boost/lexical_cast.hpp>
11 #include <boost/function.hpp>
12 #include <boost/functional.hpp>
13 #include <boost/tuple/tuple.hpp>
17 #include "CInstrFactory.hpp"
18 #include "uint32_from_hex.hpp"
20 #include "SReadline/SReadline.h"
21 using namespace swift;
23 #define RAM_END (1000)
24 #define PROG_END (1000)
25 #define REG_COUNT (16)
27 typedef boost::function<void (const vector<string> &)> Func;
28 typedef boost::tuple<string, Func, string> CompleterElement;
30 typedef list<CompleterElement> MyCompleterContainer;
35 // Creates a functor and memorises tokens
36 LookupFunctor(const vector<string>& tokens) : Tokens(tokens) {}
38 // Compares the first token only
39 bool operator()(const CompleterElement& ele) const
41 return (strncmp(Tokens.begin()->c_str(), ele.get<0>().c_str(), Tokens.begin()->size()) == 0);
45 const vector<string> &Tokens;
54 const MyCompleterContainer &m_completers;
57 CHelpExec(const MyCompleterContainer &cont) : m_completers(cont) {}
59 void operator() (const vector<string>&)
61 cout << "Available commands: " << endl;
62 for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) {
63 cout << setw(15) << (*iter).get<0>() << ": " << (*iter).get<2>() << endl;
68 void close_prog(const std::vector<std::string> &);
72 CCpu* global_cpu = NULL;
74 vector<CDat> breakpoints;
76 bool ignoreBreak = false;
78 void doExit(const vector<string>&)
83 void execStep(const vector<string>& in)
88 count = lexical_cast<int>(in.back());
91 cerr << "given parameter to step is not a number" << endl;
96 auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
97 if(breakp == breakpoints.end() || ignoreBreak) {
103 cout << "Breakpoint " << *breakp << " hit" << endl;
107 catch(std::string& e) {
114 void execRun(const vector<string>&)
118 auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
119 if(breakp == breakpoints.end() || ignoreBreak) {
125 cout << "Breakpoint " << *breakp << " hit" << endl;
129 catch(std::string& e) {
136 void setPC(const vector<string>& in)
141 addr = lexical_cast<uint32_from_hex>(in.back());
144 cerr << "given parameter is not a number" << endl;
148 global_cpu->setNextPC(addr);
149 cout << "Set programcounter to " << addr << endl;
153 void printReg(const vector<string>& in)
155 int i, start = 0, end = REG_COUNT-1;
162 start = lexical_cast<int>(in[1]);
163 if(start < 0 || start > (REG_COUNT-1)) {
164 cerr << "start is out of range" << endl;
170 cerr << "given parameter is not a number" << endl;
177 end = lexical_cast<int>(in[2]);
178 if(start > end || end > (REG_COUNT-1)) {
179 cerr << "end is out of range or smaller than start" << endl;
184 cerr << "given parameter is not a number" << endl;
189 for(i = start; i <= end; i++) {
190 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;
194 void printRAM(const vector<string>& in)
196 int i, start = 0, end = 15;
203 start = lexical_cast<int>(in[1]);
204 if(start < 0 || start > (RAM_END-1)) {
205 cerr << "start is out of range" << endl;
211 cerr << "given parameter is not a number" << endl;
218 end = lexical_cast<int>(in[2]);
219 if(start > end || end > (RAM_END-1)) {
220 cerr << "end is out of range or smaller than start" << endl;
225 cerr << "given parameter is not a number" << endl;
230 for(i = start*4; i <= end*4; i += 4) {
231 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;
235 void printPROG(const vector<string>& in)
237 int i, start = 0, end = 15;
244 start = lexical_cast<int>(in[1]);
245 if(start < 0 || start > (PROG_END-1)) {
246 cerr << "start is out of range" << endl;
252 cerr << "given parameter is not a number" << endl;
259 end = lexical_cast<int>(in[2]);
260 if(start > end || end > (PROG_END-1)) {
261 cerr << "end is out of range or smaller than start" << endl;
266 cerr << "given parameter is not a number" << endl;
271 for(i = start*4; i <= end*4; i += 4) {
272 Iinstr* pi = global_cpu->getProg(i);
274 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": NOP" << endl;
277 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": " << std::dec << pi->toString() << endl;
282 void setBreak(const vector<string>& in)
287 addr = lexical_cast<uint32_from_hex>(in.back());
288 breakpoints.push_back(addr);
291 cerr << "Given parameter is not a valid address" << endl;
295 cerr << "Invalid parameter count!" << endl;
299 void printStatus(const vector<string>&)
301 CDat stackp = global_cpu->getStack();
302 CDat stackd = global_cpu->getRAM(stackp);
303 cout << "Stack pointer: " << stackp << " @stackpointer: " << stackd << endl;
304 cout << "PSW: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getFlags() << std::dec << endl;
308 using boost::lexical_cast;
309 using boost::bad_lexical_cast;
313 using namespace boost::program_options;
314 namespace po = boost::program_options;
316 std::string progName;
318 int main(int argc, char* argv[])
323 po::options_description desc("Allowed options");
325 ("help,h","produce help message")
326 ("file,f",value<string>(), "input file")
329 po::positional_options_description p;
332 po::variables_map vm;
333 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
336 if(vm.count("help")) {
337 cout << desc << endl;
341 if(vm.count("file")) {
343 cout << "going to open file " << vm["file"].as<string>() << endl;
345 inFile.open(vm["file"].as<string>(), ios::in);
347 cerr << "Error opening file " << vm["file"].as<string>() << endl;
352 cout << "not input file given!" << endl << endl;
353 cout << desc << endl;
357 catch(std::exception& ex) {
358 cout << ex.what() << endl;
362 string dir = "./instr/";
364 map<short, Iinstr*> instr;
366 CInstrFactory instrFab;
368 instrFab.loadLibsIntoMap(instr, dir);
370 catch(std::bad_alloc& e) {
371 cerr << progName << ": bad_alloc caught " << e.what() << endl;
374 catch(std::string& s) {
375 cerr << progName << ": " << s << endl;
379 CCpu cpu(REG_COUNT, RAM_END, PROG_END);
383 Iinstr::setCPU(&cpu);
386 std::string str = "";
388 boost::char_separator<char> sep(";", "", boost::keep_empty_tokens);
389 boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
390 disasm disasm(instr);
391 while(getline(inFile, str)) {
396 for(auto tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
397 if(tok_iter == tokens.begin()) {
399 type = lexical_cast<int>(*tok_iter);
403 catch(bad_lexical_cast &) {
412 addr = lexical_cast<uint32_from_hex>(*tok_iter);
414 catch(bad_lexical_cast& e) {
415 cerr << e.what() << endl;
419 else if(count == 2) {
421 CDat data = lexical_cast<uint32_from_hex>(*tok_iter);
422 cpu.setRAM(addr, data);
424 catch(bad_lexical_cast& e) {
425 cerr << e.what() << endl;
433 addr = lexical_cast<uint32_from_hex>(*tok_iter);
435 catch(bad_lexical_cast& e) {
436 cerr << e.what() << endl;
440 else if(count == 2) {
441 Iinstr *pi = disasm.decode(*tok_iter);
442 cpu.setProg(addr, pi);
447 cerr << "ignoring labels and comments for now" << endl;
449 cerr << "i was to lazy to implement the other format types for now" << endl;
459 for(int i = 0; i <= 32; i += 4) {
460 Iinstr *pinstr = cpu.getProg(i);
462 cout << i << " : " << std::hex << i << std::dec << " " << pinstr->toString() << endl;
465 cout << "Null at " << i << " : " << std::hex << i << endl;
469 for(int i = 0; i <= 32; i += 4) {
470 CDat data = cpu.getRAM(i);
471 cout << i << " : " << std::hex << i << std::dec << " " << data << endl;
474 cpu.setRegister(1, 4);
475 cpu.setRegister(2, 0);
481 // following: job of the bootloader
484 //set return to nowhere for ret
489 MyCompleterContainer Completers;
491 CHelpExec HelpExec(Completers);
493 Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec), "Prints this message"));
494 Completers.push_back(CompleterElement("quit", &doExit, "Exits program"));
495 Completers.push_back(CompleterElement("exit", &doExit, "Exits program"));
496 Completers.push_back(CompleterElement("step [count]",&execStep, "Runs [count] ticks. if count is not given one tick is executed."));
497 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."));
498 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."));
499 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."));
500 Completers.push_back(CompleterElement("break addr",&setBreak, "Sets a breakpoint for address addr."));
501 Completers.push_back(CompleterElement("run",&execRun, "Runs till next breakpoint or end of program."));
502 Completers.push_back(CompleterElement("setpc [num]",&setPC, "Sets PC to num. if num is omitted 0 is used."));
503 Completers.push_back(CompleterElement("status",&printStatus, "Prints status of CPU."));
505 Reader.RegisterCompletions(Completers);
508 vector<string> Tokens, lastTokens;
509 bool EndOfInput = false;
511 auto Found(Completers.end());
513 Func lastFunc = NULL;
517 UserInput = Reader.GetLine("> ", Tokens, EndOfInput);
522 if(!Tokens.empty()) {
523 Found = find_if(Completers.begin(), Completers.end(), LookupFunctor(Tokens));
525 if(Found != Completers.end()) {
526 if((*Found).get<1>() != 0) {
527 lastFunc = (*Found).get<1>();
530 //(*Found).get<1>()(Tokens);
535 cout << "Unknown command. 'help' displays help" << endl;
539 if(lastFunc != NULL) {
540 lastFunc(lastTokens);
543 cout << "Unknown command. 'help' displays help" << endl;
550 for(int i = 0; ; i++) {
553 cout << " reg0: " << cpu.getRegister(0) << " reg1: " << cpu.getRegister(1);
554 cout << " reg2: " << cpu.getRegister(2) << " reg3: " << cpu.getRegister(3);
555 cout << " reg4: " << cpu.getRegister(4) << " reg5: " << cpu.getRegister(5);
556 cout << endl << endl;