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"
21 #include "extensions/cprog.hpp"
22 #include "extensions/cuart.hpp"
24 #include "SReadline/SReadline.h"
25 using namespace swift;
27 #define RAM_END (0x3000)
28 #define PROG_END (0x3000)
29 #define REG_COUNT (16)
31 typedef boost::function<void (const vector<string> &)> Func;
32 typedef boost::tuple<string, Func, string> CompleterElement;
34 typedef list<CompleterElement> MyCompleterContainer;
39 // Creates a functor and memorises tokens
40 LookupFunctor(const vector<string>& tokens) : Tokens(tokens) {}
42 // Compares the first token only
43 bool operator()(const CompleterElement& ele) const
45 return (strncmp(Tokens.begin()->c_str(), ele.get<0>().c_str(), Tokens.begin()->size()) == 0);
49 const vector<string> &Tokens;
58 const MyCompleterContainer &m_completers;
61 CHelpExec(const MyCompleterContainer &cont) : m_completers(cont) {}
63 void operator() (const vector<string>&)
65 cout << "Available commands: " << endl;
66 for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) {
67 cout << setw(19) << setfill(' ') << (*iter).get<0>() << ": " << (*iter).get<2>() << endl;
72 void close_prog(const std::vector<std::string> &);
76 disasm* Iinstr::m_disasm;
77 disasm* Iext::m_disasm;
79 CCpu* global_cpu = NULL;
81 vector<CDat> breakpoints;
86 multimap<int,string> dataCommentsStore, progCommentsStore, dataLabelStore, progLabelStore;
87 map<int,string> dataLineCommentStore, progLineCommentStore;
89 bool ignoreBreak = false;
91 bool exitProg = false;
93 void doExit(const vector<string>&)
98 unsigned int convertStringToNum(const std::string& in)
100 if(in.substr(0,2) == "0x") {
101 return lexical_cast<uint32_from_hex>(in);
104 return lexical_cast<unsigned int>(in);
109 void execStep(const vector<string>& in)
114 count = convertStringToNum(in.back());
117 cerr << "given parameter to step is not a number" << endl;
122 auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
123 if(breakp == breakpoints.end() || ignoreBreak) {
129 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
133 catch(std::string& e) {
140 void execRun(const vector<string>&)
144 auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
145 if(breakp == breakpoints.end() || ignoreBreak) {
151 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
155 catch(std::string& e) {
162 void setPC(const vector<string>& in)
167 addr = convertStringToNum(in.back());
170 cerr << "given parameter is not a number" << endl;
174 global_cpu->setNextPC(addr);
175 cout << "Set programcounter to 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << endl;
179 void printReg(const vector<string>& in)
181 int i, start = 0, end = REG_COUNT-1;
188 start = convertStringToNum(in[1]);
189 if(start < 0 || start > (REG_COUNT-1)) {
190 cerr << "start is out of range" << endl;
196 cerr << "given parameter is not a number" << endl;
203 end = convertStringToNum(in[2]);
204 if(start > end || end > (REG_COUNT-1)) {
205 cerr << "end is out of range or smaller than start" << endl;
210 cerr << "given parameter is not a number" << endl;
215 for(i = start; i <= end; i++) {
216 cout << setw(2) << setfill('0') << i << ": 0x";
217 cout << std::hex << setw(8) << setfill('0') << global_cpu->getRegister(i) << " ";
218 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRegister(i) << " ";
219 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRegister(i) << endl;
223 void setReg(const vector<string>& in)
230 reg = convertStringToNum(in[1]);
231 if(reg < 0 || reg > (REG_COUNT-1)) {
232 cerr << "register is out of range" << endl;
236 val = convertStringToNum(in[2]);
238 cout << "Setting register " << reg << " to 0x" << std::hex << setw(8) << setfill('0') << val << std::dec << endl;
239 global_cpu->setRegister(reg,val);
242 cerr << "given parameter is not a number" << endl;
248 void printRAM(const vector<string>& in)
250 int i, start = 0, end = 15;
257 start = convertStringToNum(in[1]);
258 if(start < 0 || start > (RAM_END-1)) {
259 cerr << "start is out of range" << endl;
262 start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
266 cerr << "given parameter is not a number" << endl;
273 end = convertStringToNum(in[2]);
274 if(start > end || end > (RAM_END-1)) {
275 cerr << "end is out of range or smaller than start" << endl;
278 if(end % BYTE_COUNT != 0) {
279 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
282 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
286 cerr << "given parameter is not a number" << endl;
290 for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
292 auto range = dataLabelStore.equal_range(i);
293 for(auto iter = range.first; iter != range.second; ++iter) {
294 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
298 auto range = dataCommentsStore.equal_range(i);
299 for(auto iter = range.first; iter != range.second; ++iter) {
300 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
303 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": 0x";
304 cout << std::hex << setw(8) << setfill('0') << global_cpu->getRAM(i) << " ";
305 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRAM(i) << " ";
306 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRAM(i);
308 auto iter = dataLineCommentStore.find(i);
309 if(iter != dataLineCommentStore.end()) {
310 cout << color(blue,black) << " ;" << iter->second << color(white,black);
317 void setRam(const vector<string>& in)
324 addr = convertStringToNum(in[1]);
325 if(addr < 0 || addr > (RAM_END-1)) {
326 cerr << "RAM-Address is out of range" << endl;
330 addr = (addr & (~(BYTE_COUNT-1))) / BYTE_COUNT;
331 val = convertStringToNum(in[2]);
335 cout << "Setting RAM-Address 0x" << std::hex << setw(8) << setfill('0') << addr;
336 cout << " to 0x" << setw(8) << setfill('0') << val << std::dec << endl;
337 global_cpu->setRAM(addr,val);
340 cerr << "given parameter is not a number" << endl;
345 void printPROG(const vector<string>& in)
347 int i, start = 0, end = 15;
352 if(in.size() >= 2 && in[1][0] == 'c') {
353 start = global_cpu->getCurPC() / BYTE_COUNT;
356 else if(in.size() >= 2) {
358 start = convertStringToNum(in[1]);
359 if(start < 0 || start > (PROG_END-1)) {
360 cerr << "start is out of range" << endl;
363 start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
367 cerr << "given parameter is not a number" << endl;
374 end = convertStringToNum(in[2]);
375 if(start > end || end > (PROG_END-1)) {
376 cerr << "end is out of range or smaller than start" << endl;
379 if(end % BYTE_COUNT != 0) {
380 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
383 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
388 cerr << "given parameter is not a number" << endl;
394 for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
396 auto range = progLabelStore.equal_range(i);
397 for(auto iter = range.first; iter != range.second; ++iter) {
398 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
402 auto range = progCommentsStore.equal_range(i);
403 for(auto iter = range.first; iter != range.second; ++iter) {
404 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
408 Iinstr* pi = global_cpu->getProg(i);
410 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": NOP";
413 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": " << std::dec << global_cpu->colorifyInstr(pi->toString());
415 auto iter = progLineCommentStore.find(i);
416 if(iter != progLineCommentStore.end()) {
417 cout << color(blue,black) << " ;" << iter->second << color(white,black);
423 void setBreak(const vector<string>& in)
425 unsigned int addr = 0;
428 addr = convertStringToNum(in.back());
429 breakpoints.push_back(addr);
430 cout << "Breakpoint 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << " set" << endl;
433 cerr << "Given parameter is not a valid address" << endl;
437 cerr << "Invalid parameter count!" << endl;
441 void listBreaks(const vector<string>&)
443 for(auto iter = breakpoints.begin(); iter != breakpoints.end(); ++iter) {
444 cout << "Breakpoint at 0x" << std::hex << setw(8) << setfill('0') << *iter << std::dec << endl;
448 void getPerf(const vector<string>&)
450 cout << "current perfcounter is " << std::dec << global_cpu->getPerf() << endl;
453 void resetPerf(const vector<string>&)
455 cout << "reset perfcounter" << endl;
456 global_cpu->setPerf(0);
459 void applyToExtensions(const vector<string>& in)
461 global_cpu->applyToExtensions(in);
465 void printStatus(const vector<string>&)
467 CDat stackp = global_cpu->getStack();
468 CDat stackd = global_cpu->getRAM(stackp);
469 cout << "Stack pointer: 0x" << std::hex << setw(8) << setfill('0') << stackp << " @stackpointer: 0x" << setw(8) << stackd << std::dec << " (" << stackd << ")" << endl;
470 cout << "PSW: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getFlags() << std::dec << endl;
471 cout << "cur PC: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getCurPC() << " next PC: 0x" << setw(8) << setfill('0') << global_cpu->getNextPC() << std::dec << endl;
475 using boost::lexical_cast;
476 using boost::bad_lexical_cast;
480 using namespace boost::program_options;
481 namespace po = boost::program_options;
483 std::string progName;
485 int main(int argc, char* argv[])
490 po::options_description desc("Allowed options");
492 ("help,h","produce help message")
493 ("file,f",value<string>(), "input file")
496 po::positional_options_description p;
499 po::variables_map vm;
500 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
503 if(vm.count("help")) {
504 cout << desc << endl;
508 if(vm.count("file")) {
510 cout << "going to open file " << vm["file"].as<string>() << endl;
512 inFile.open(vm["file"].as<string>(), ios::in);
514 cerr << "Error opening file " << vm["file"].as<string>() << endl;
519 cout << "not input file given!" << endl << endl;
520 cout << desc << endl;
524 catch(std::exception& ex) {
525 cout << ex.what() << endl;
529 string dir = "./instr/";
531 map<short, Iinstr*> instr;
533 CInstrFactory instrFab;
535 instrFab.loadLibsIntoMap(instr, dir);
537 catch(std::bad_alloc& e) {
538 cerr << progName << ": bad_alloc caught " << e.what() << endl;
541 catch(std::string& s) {
542 cerr << progName << ": " << s << endl;
546 CCpu cpu(REG_COUNT, RAM_END, PROG_END);
550 Iinstr::setCPU(&cpu);
553 disasm disasm(instr);
555 Iinstr::setDisasm(&disasm);
556 Iext::setDisasm(&disasm);
558 global_cpu->registerExtension(new Cprog());
559 global_cpu->registerExtension(new Cuart());
561 vector<string> commentDefer;
562 vector<string> labelDefer;
563 std::string str = "";
565 boost::char_separator<char> sep(";", "", boost::keep_empty_tokens);
566 boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
567 while(getline(inFile, str)) {
572 for(auto tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
573 if(tok_iter == tokens.begin()) {
575 type = lexical_cast<int>(*tok_iter);
579 catch(bad_lexical_cast &) {
588 addr = lexical_cast<uint32_from_hex>(*tok_iter);
589 for(unsigned int i = 0; i < commentDefer.size(); i++) {
590 dataCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
592 for(unsigned int i = 0; i < labelDefer.size(); i++) {
593 dataLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
596 commentDefer.clear();
599 catch(bad_lexical_cast& e) {
600 cerr << e.what() << endl;
604 else if(count == 2) {
606 CDat data = lexical_cast<uint32_from_hex>(*tok_iter);
607 cpu.setRAM(addr, data);
609 catch(bad_lexical_cast& e) {
610 cerr << e.what() << endl;
614 else if(count == 4) {
615 if((*tok_iter).size() > 0) {
616 dataLabelStore.insert(pair<int,string>(addr, *tok_iter));
619 else if(count == 5) {
620 if((*tok_iter).size() > 0) {
621 dataLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
628 addr = lexical_cast<uint32_from_hex>(*tok_iter);
629 for(unsigned int i = 0; i < commentDefer.size(); i++) {
630 progCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
632 for(unsigned int i = 0; i < labelDefer.size(); i++) {
633 progLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
636 commentDefer.clear();
639 catch(bad_lexical_cast& e) {
640 cerr << e.what() << endl;
644 else if(count == 2) {
645 Iinstr *pi = disasm.decode(*tok_iter);
646 cpu.setProg(addr, pi);
648 else if(count == 4) {
649 if((*tok_iter).size() > 0) {
650 progLabelStore.insert(pair<int,string>(addr, *tok_iter));
653 else if(count == 5) {
654 if((*tok_iter).size() > 0) {
655 progLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
661 if((*tok_iter).size() > 0) {
662 commentDefer.push_back(*tok_iter);
666 if((*tok_iter).size() > 0) {
667 labelDefer.push_back(*tok_iter);
671 cerr << "i was to lazy to implement the other format types for now" << endl;
681 for(int i = 0; i <= 32; i += 4) {
682 Iinstr *pinstr = cpu.getProg(i);
684 cout << i << " : " << std::hex << i << std::dec << " " << pinstr->toString() << endl;
687 cout << "Null at " << i << " : " << std::hex << i << endl;
691 for(int i = 0; i <= 32; i += 4) {
692 CDat data = cpu.getRAM(i);
693 cout << i << " : " << std::hex << i << std::dec << " " << data << endl;
696 /* cpu.setRegister(1, 4);
697 cpu.setRegister(2, 0);
699 cpu.setRAM(4,0x66334455);
703 // following: job of the bootloader
706 //set return to nowhere for ret
711 MyCompleterContainer Completers;
713 CHelpExec HelpExec(Completers);
715 Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec), "Prints this message"));
716 Completers.push_back(CompleterElement("quit", &doExit, "Exits program"));
717 Completers.push_back(CompleterElement("exit", &doExit, "Exits program"));
718 Completers.push_back(CompleterElement("step [count]",&execStep, "Runs [count] ticks. if count is not given one tick is executed."));
719 Completers.push_back(CompleterElement("dreg [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."));
720 Completers.push_back(CompleterElement("ddata [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."));
721 Completers.push_back(CompleterElement("dprog [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."));
722 Completers.push_back(CompleterElement("break addr",&setBreak, "Sets a breakpoint for address addr."));
723 Completers.push_back(CompleterElement("listbreaks",&listBreaks, "Lists all breakpoints."));
724 Completers.push_back(CompleterElement("run",&execRun, "Runs till next breakpoint or end of program."));
725 Completers.push_back(CompleterElement("setpc [num]",&setPC, "Sets PC to num. if num is omitted 0 is used."));
726 Completers.push_back(CompleterElement("setreg [s] [num]",&setReg, "Sets Register s to num."));
727 Completers.push_back(CompleterElement("setdata [s] [num]",&setRam, "Sets RAM-Addr s to num."));
728 Completers.push_back(CompleterElement("status",&printStatus, "Prints status of CPU."));
729 Completers.push_back(CompleterElement("getperf",&getPerf, "Prints performance counter."));
730 Completers.push_back(CompleterElement("resetperf",&resetPerf, "Resets performance counter to 0."));
731 Completers.push_back(CompleterElement("extension",&applyToExtensions, "Write to extensions."));
732 Reader.RegisterCompletions(Completers);
735 vector<string> Tokens, lastTokens;
736 bool EndOfInput = false;
738 //tilab g++44 doesn't like auto here
739 MyCompleterContainer::iterator Found(Completers.end());
741 Func lastFunc = NULL;
745 UserInput = Reader.GetLine("> ", Tokens, EndOfInput);
750 if(!Tokens.empty()) {
751 Found = find_if(Completers.begin(), Completers.end(), LookupFunctor(Tokens));
753 if(Found != Completers.end()) {
754 if((*Found).get<1>() != 0) {
755 lastFunc = (*Found).get<1>();
758 //(*Found).get<1>()(Tokens);
763 cout << "Unknown command. 'help' displays help" << endl;
767 if(lastFunc != NULL) {
768 lastFunc(lastTokens);
771 cout << "Unknown command. 'help' displays help" << endl;
778 for(int i = 0; ; i++) {
781 cout << " reg0: " << cpu.getRegister(0) << " reg1: " << cpu.getRegister(1);
782 cout << " reg2: " << cpu.getRegister(2) << " reg3: " << cpu.getRegister(3);
783 cout << " reg4: " << cpu.getRegister(4) << " reg5: " << cpu.getRegister(5);
784 cout << endl << endl;