sim: labels and comments are now shown
[calu.git] / 3b_sim / sim.cpp
1 #include <iostream>
2 #include <iomanip>
3 #include <fstream>
4 #include <boost/tokenizer.hpp>
5 #include <boost/program_options.hpp>
6 #include <boost/lexical_cast.hpp>
7 #include <string>
8 #include <map>
9 #include <list>
10
11 #include <boost/function.hpp>
12 #include <boost/functional.hpp>
13 #include <boost/tuple/tuple.hpp>
14
15 #include "disasm.h"
16 #include "ccpu.hpp"
17 #include "CInstrFactory.hpp"
18 #include "uint32_from_hex.hpp"
19
20 #include "SReadline/SReadline.h"
21 using namespace swift;
22
23 #define RAM_END (0x3000)
24 #define PROG_END (0x3000)
25 #define REG_COUNT (16)
26
27 typedef boost::function<void (const vector<string> &)> Func;
28 typedef boost::tuple<string, Func, string> CompleterElement;
29
30 typedef list<CompleterElement> MyCompleterContainer;
31
32 class LookupFunctor
33 {
34         public:
35                 // Creates a functor and memorises tokens
36                 LookupFunctor(const vector<string>&  tokens) : Tokens(tokens) {}
37
38                 // Compares the first token only
39                 bool operator()(const CompleterElement& ele) const
40                 {
41                         return (strncmp(Tokens.begin()->c_str(), ele.get<0>().c_str(), Tokens.begin()->size()) == 0);
42                 }
43
44         private:
45                 const vector<string> &Tokens;
46 };
47
48
49
50
51 class CHelpExec
52 {
53         private:
54                 const MyCompleterContainer &m_completers;
55
56         public:
57                 CHelpExec(const MyCompleterContainer &cont) : m_completers(cont) {}
58
59                 void operator() (const vector<string>&)
60                 {
61                         cout << "Available commands: " << endl;
62                         for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) {
63                                 cout << setw(19) << setfill(' ') << (*iter).get<0>() << ": " << (*iter).get<2>() << endl;
64                         }
65                 }
66 };
67
68 void close_prog(const std::vector<std::string> &);
69
70 CCpu* Iinstr::m_cpu;
71 disasm* Iinstr::m_disasm;
72
73 CCpu* global_cpu = NULL;
74
75 vector<CDat> breakpoints;
76
77 #include <map>
78
79 multimap<int,string> dataCommentsStore, progCommentsStore, dataLabelStore, progLabelStore;
80 map<int,string> dataLineCommentStore, progLineCommentStore;
81
82 bool ignoreBreak = false;
83
84 bool exitProg = false;
85
86 void doExit(const vector<string>&)
87 {
88         exitProg = true;
89 }
90
91 unsigned int convertStringToNum(const std::string& in)
92 {
93         if(in.substr(0,2) == "0x") {
94                 return lexical_cast<uint32_from_hex>(in);
95         }
96         else {
97                 return lexical_cast<unsigned int>(in);
98         }
99 }
100
101
102 void execStep(const vector<string>& in)
103 {
104         int count = 1;
105         if(in.size() == 2) {
106                 try {
107                         count = convertStringToNum(in.back());
108                 }
109                 catch(bad_cast&) {
110                         cerr << "given parameter to step is not a number" << endl;
111                 }
112         }
113         while(count > 0) {
114                 try {
115                         auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
116                         if(breakp == breakpoints.end() || ignoreBreak) {
117                                 global_cpu->tick();
118                                 ignoreBreak = false;
119                         }
120                         else {
121                                 ignoreBreak = true;
122                                 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
123                                 break;
124                         }
125                 }
126                 catch(std::string& e) {
127                         cerr << e << endl;
128                 }
129                 count--;
130         }
131 }
132
133 void execRun(const vector<string>&)
134 {
135         while(1) {
136                 try {
137                         auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
138                         if(breakp == breakpoints.end() || ignoreBreak) {
139                                 global_cpu->tick();
140                                 ignoreBreak = false;
141                         }
142                         else {
143                                 ignoreBreak = true;
144                                 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
145                                 return;
146                         }
147                 }
148                 catch(std::string& e) {
149                         cerr << e << endl;
150                         return;
151                 }
152         }
153 }
154
155 void setPC(const vector<string>& in)
156 {
157         CDat addr = 0;
158         if(in.size() == 2) {
159                 try {
160                         addr = convertStringToNum(in.back());
161                 }
162                 catch(bad_cast&) {
163                         cerr << "given parameter is not a number" << endl;
164                         return;
165                 }
166         }
167         global_cpu->setNextPC(addr);
168         cout << "Set programcounter to 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << endl;
169 }
170
171
172 void printReg(const vector<string>& in)
173 {
174         int i, start = 0, end = REG_COUNT-1;
175         /* Todo: 
176          * 1) make 2 columns
177          */
178
179         if(in.size() >= 2) {
180                 try {
181                         start = convertStringToNum(in[1]);
182                         if(start < 0 || start > (REG_COUNT-1)) {
183                                 cerr << "start is out of range" << endl;
184                                 return;
185                         }
186                         end = start;
187                 }
188                 catch(bad_cast&) {
189                         cerr << "given parameter is not a number" << endl;
190                         return;
191                 }
192         }
193
194         if(in.size() >= 3) {
195                 try {
196                         end = convertStringToNum(in[2]);
197                         if(start > end || end > (REG_COUNT-1)) {
198                                 cerr << "end is out of range or smaller than start" << endl;
199                                 return;
200                         }
201                 }
202                 catch(bad_cast&) {
203                         cerr << "given parameter is not a number" << endl;
204                         return;
205                 }
206         }
207         
208         for(i = start; i <= end; i++) {
209                 cout << setw(2) << setfill('0') << i << ": 0x";
210                 cout << std::hex <<  setw(8) << setfill('0') << global_cpu->getRegister(i) << " ";
211                 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRegister(i) << " ";
212                 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRegister(i) << endl;
213         }
214 }
215
216 void setReg(const vector<string>& in)
217 {
218         int reg = 0;
219         CDat val = 0;
220
221         if(in.size() >= 3) {
222                 try {
223                         reg = convertStringToNum(in[1]);
224                         if(reg < 0 || reg > (REG_COUNT-1)) {
225                                 cerr << "register is out of range" << endl;
226                                 return;
227                         }
228
229                         val = convertStringToNum(in[2]);
230
231                         cout << "Setting register " << reg << " to 0x" << std::hex << setw(8) << setfill('0') << val << std::dec << endl;
232                         global_cpu->setRegister(reg,val);
233                 }
234                 catch(bad_cast&) {
235                         cerr << "given parameter is not a number" << endl;
236                         return;
237                 }
238         }
239 }
240
241 void printRAM(const vector<string>& in)
242 {
243         int i, start = 0, end = 15;
244         /* Todo: 
245          * 1) make 2 columns
246          */
247
248         if(in.size() >= 2) {
249                 try {
250                         start = convertStringToNum(in[1]);
251                         if(start < 0 || start > (RAM_END-1)) {
252                                 cerr << "start is out of range" << endl;
253                                 return;
254                         }
255                         start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
256                         end = start;
257                 }
258                 catch(bad_cast&) {
259                         cerr << "given parameter is not a number" << endl;
260                         return;
261                 }
262         }
263
264         if(in.size() >= 3) {
265                 try {
266                         end = convertStringToNum(in[2]);
267                         if(start > end || end > (RAM_END-1)) {
268                                 cerr << "end is out of range or smaller than start" << endl;
269                                 return;
270                         }
271                         if(end % BYTE_COUNT != 0) {
272                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
273                         }
274                         else {
275                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
276                         }
277                 }
278                 catch(bad_cast&) {
279                         cerr << "given parameter is not a number" << endl;
280                         return;
281                 }
282         }
283         for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
284                 {
285                         auto range = dataLabelStore.equal_range(i);
286                         for(auto iter = range.first; iter != range.second; ++iter) {
287                                 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
288                         }
289                 }
290                 {
291                         auto range = dataCommentsStore.equal_range(i);
292                         for(auto iter = range.first; iter != range.second; ++iter) {
293                                 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
294                         }
295                 }
296                 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": 0x";
297                 cout << std::hex << setw(8)  << setfill('0') << global_cpu->getRAM(i) << " ";
298                 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRAM(i) << " ";
299                 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRAM(i);
300
301                 auto iter = dataLineCommentStore.find(i);
302                 if(iter != dataLineCommentStore.end()) {
303                         cout << color(blue,black) << " ;" << iter->second << color(white,black);
304                 }
305                 cout << endl;
306
307         }
308 }
309
310 void setRam(const vector<string>& in)
311 {
312         int addr = 0;
313         CDat val = 0;
314
315         if(in.size() >= 3) {
316                 try {
317                         addr = convertStringToNum(in[1]);
318                         if(addr < 0 || addr > (RAM_END-1)) {
319                                 cerr << "RAM-Address is out of range" << endl;
320                                 return;
321                         }
322
323                         addr = (addr & (~(BYTE_COUNT-1))) / BYTE_COUNT;
324                         val = convertStringToNum(in[2]);
325
326                         addr *= BYTE_COUNT;
327
328                         cout << "Setting RAM-Address 0x" << std::hex << setw(8) << setfill('0') << addr;
329                         cout << " to 0x" << setw(8) << setfill('0') << val << std::dec << endl;
330                         global_cpu->setRAM(addr,val);
331                 }
332                 catch(bad_cast&) {
333                         cerr << "given parameter is not a number" << endl;
334                         return;
335                 }
336         }
337 }
338 void printPROG(const vector<string>& in)
339 {
340         int i, start = 0, end = 15;
341         /* Todo: 
342          * 1) make 2 columns
343          */
344
345         if(in.size() >= 2 && in[1][0] == 'c') {
346                 start = global_cpu->getCurPC() / BYTE_COUNT;
347                 end = start + 9;
348         }
349         else if(in.size() >= 2) {
350                 try {
351                         start = convertStringToNum(in[1]);
352                         if(start < 0 || start > (PROG_END-1)) {
353                                 cerr << "start is out of range" << endl;
354                                 return;
355                         }
356                         start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
357                         end = start;
358                 }
359                 catch(bad_cast&) {
360                         cerr << "given parameter is not a number" << endl;
361                         return;
362                 }
363         }
364
365         if(in.size() >= 3) {
366                 try {
367                         end = convertStringToNum(in[2]);
368                         if(start > end || end > (PROG_END-1)) {
369                                 cerr << "end is out of range or smaller than start" << endl;
370                                 return;
371                         }
372                         if(end % BYTE_COUNT != 0) {
373                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
374                         }
375                         else {
376                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
377                         }
378
379                 }
380                 catch(bad_cast&) {
381                         cerr << "given parameter is not a number" << endl;
382                         return;
383                 }
384         }
385
386         
387         for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
388                 {
389                         auto range = progLabelStore.equal_range(i);
390                         for(auto iter = range.first; iter != range.second; ++iter) {
391                                 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
392                         }
393                 }
394                 {
395                         auto range = progCommentsStore.equal_range(i);
396                         for(auto iter = range.first; iter != range.second; ++iter) {
397                                 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
398                         }
399                 }
400
401                 Iinstr* pi = global_cpu->getProg(i);
402                 if(pi == NULL) {
403                         cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": NOP";
404                 }
405                 else {
406                         cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": " << std::dec << pi->toString();
407                 }
408                 auto iter = progLineCommentStore.find(i);
409                 if(iter != progLineCommentStore.end()) {
410                         cout << color(blue,black) << " ;" << iter->second << color(white,black);
411                 }
412                 cout << endl;
413         }
414 }
415
416 void setBreak(const vector<string>& in)
417 {
418         unsigned int addr = 0;
419         if(in.size() == 2) {
420                 try {
421                         addr = convertStringToNum(in.back());
422                         breakpoints.push_back(addr);
423                         cout << "Breakpoint 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << " set" << endl;
424                 }
425                 catch(bad_cast&) {
426                         cerr << "Given parameter is not a valid address" << endl;
427                 }
428         }
429         else {
430                 cerr << "Invalid parameter count!" << endl;
431         }
432 }
433
434 void listBreaks(const vector<string>&)
435 {
436         for(auto iter = breakpoints.begin(); iter != breakpoints.end(); ++iter) {
437                 cout << "Breakpoint at 0x" << std::hex << setw(8) << setfill('0') << *iter << std::dec << endl;
438         }
439 }
440
441 void getPerf(const vector<string>&)
442 {
443         cout << "current perfcounter is " << std::dec << global_cpu->getPerf() << endl;
444 }
445
446 void resetPerf(const vector<string>&)
447 {
448         cout << "reset perfcounter" << endl;
449         global_cpu->setPerf(0);
450 }
451
452 void printStatus(const vector<string>&)
453 {
454         CDat stackp = global_cpu->getStack();
455         CDat stackd = global_cpu->getRAM(stackp);
456         cout << "Stack pointer: 0x" << std::hex << setw(8) << setfill('0') << stackp << " @stackpointer: 0x" << setw(8) << stackd << std::dec << " (" << stackd << ")" << endl;
457         cout << "PSW: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getFlags() << std::dec << endl;
458         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;
459
460 }
461
462 using boost::lexical_cast;
463 using boost::bad_lexical_cast;
464
465 using namespace std;
466
467 using namespace boost::program_options;
468 namespace po = boost::program_options;
469
470 std::string progName;
471
472 int main(int argc, char* argv[])
473 {
474         progName = argv[0];
475         ifstream inFile;
476         try {
477                 po::options_description desc("Allowed options");
478                 desc.add_options()
479                 ("help,h","produce help message")
480                 ("file,f",value<string>(), "input file")
481                 ;
482
483                 po::positional_options_description p;
484                 p.add("file",1);
485
486                 po::variables_map vm;
487                 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
488                 po::notify(vm);
489
490                 if(vm.count("help")) {
491                         cout << desc << endl;
492                         return EXIT_FAILURE;
493                 }
494
495                 if(vm.count("file")) {
496 #ifdef DEBUG 
497                         cout << "going to open file " << vm["file"].as<string>() << endl;
498 #endif
499                         inFile.open(vm["file"].as<string>(), ios::in);
500                         if(!inFile) {
501                                 cerr << "Error opening file " << vm["file"].as<string>() << endl;
502                                 return EXIT_FAILURE;
503                         }
504                 }
505                 else {
506                         cout << "not input file given!" << endl << endl;
507                         cout << desc << endl;
508                         return EXIT_FAILURE;
509                 }
510         }
511         catch(std::exception& ex) {
512                 cout << ex.what() << endl;
513         }
514
515
516         string dir = "./instr/";
517
518         map<short, Iinstr*> instr;
519
520         CInstrFactory instrFab;
521         try {
522                 instrFab.loadLibsIntoMap(instr, dir);
523         }
524         catch(std::bad_alloc& e) {
525                 cerr << progName << ": bad_alloc caught " << e.what() << endl;
526                 exit(EXIT_FAILURE); 
527         }
528         catch(std::string& s) {
529                 cerr << progName << ": " << s << endl;
530                 exit(EXIT_FAILURE);
531         }
532
533         CCpu cpu(REG_COUNT, RAM_END, PROG_END);
534
535         global_cpu = &cpu;
536
537         Iinstr::setCPU(&cpu);
538
539         disasm disasm(instr);
540
541         Iinstr::setDisasm(&disasm);
542
543         vector<string> commentDefer;
544         vector<string> labelDefer;
545         std::string str = "";
546         int addr = 0;
547         boost::char_separator<char> sep(";", "", boost::keep_empty_tokens);
548         boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
549         while(getline(inFile, str)) {
550                 int count = 0;
551                 tokens.assign(str);
552                 stringstream out;
553                 int type = 0;
554                 for(auto tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
555                         if(tok_iter == tokens.begin()) {
556                                 try {
557                                         type = lexical_cast<int>(*tok_iter);
558                                         count++;
559                                         continue;
560                                 }
561                                 catch(bad_lexical_cast &) {
562                                         break;
563                                 }
564                                 cout << endl;
565                         }
566                         switch(type) {
567                                 case 0:
568                                         if(count == 1) {
569                                                 try {
570                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
571                                                         for(unsigned int i = 0; i < commentDefer.size(); i++) {
572                                                                 dataCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
573                                                         }
574                                                         for(unsigned int i = 0; i < labelDefer.size(); i++) {
575                                                                 dataLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
576                                                         }
577
578                                                         commentDefer.clear();
579                                                         labelDefer.clear();
580                                                 }
581                                                 catch(bad_lexical_cast& e) {
582                                                         cerr << e.what() << endl;
583                                                         exit(EXIT_FAILURE);
584                                                 }
585                                         }
586                                         else if(count == 2) {
587                                                 try {
588                                                         CDat data = lexical_cast<uint32_from_hex>(*tok_iter);
589                                                         cpu.setRAM(addr, data);
590                                                 }
591                                                 catch(bad_lexical_cast& e) {
592                                                         cerr << e.what() << endl;
593                                                         exit(EXIT_FAILURE);
594                                                 }
595                                         }
596                                         else if(count == 4) {
597                                                 if((*tok_iter).size() > 0) {
598                                                         dataLabelStore.insert(pair<int,string>(addr, *tok_iter));
599                                                 }
600                                         }
601                                         else if(count == 5) {
602                                                 if((*tok_iter).size() > 0) {
603                                                         dataLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
604                                                 }
605                                         }
606                                         break;
607                                 case 1:
608                                         if(count == 1) {
609                                                 try {
610                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
611                                                         for(unsigned int i = 0; i < commentDefer.size(); i++) {
612                                                                 progCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
613                                                         }
614                                                         for(unsigned int i = 0; i < labelDefer.size(); i++) {
615                                                                 progLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
616                                                         }
617
618                                                         commentDefer.clear();
619                                                         labelDefer.clear();
620                                                 }
621                                                 catch(bad_lexical_cast& e) {
622                                                         cerr << e.what() << endl;
623                                                         exit(EXIT_FAILURE);
624                                                 }
625                                         }
626                                         else if(count == 2) {
627                                                 Iinstr *pi = disasm.decode(*tok_iter);
628                                                 cpu.setProg(addr, pi);
629                                         }
630                                         else if(count == 4) {
631                                                 if((*tok_iter).size() > 0) {
632                                                         progLabelStore.insert(pair<int,string>(addr, *tok_iter));
633                                                 }
634                                         }
635                                         else if(count == 5) {
636                                                 if((*tok_iter).size() > 0) {
637                                                         progLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
638                                                 }
639                                         }
640
641                                         break;
642                                 case 2:
643                                         if((*tok_iter).size() > 0) {
644                                                 commentDefer.push_back(*tok_iter);
645                                         }
646                                         break;
647                                 case 3:
648                                         if((*tok_iter).size() > 0) {
649                                                 labelDefer.push_back(*tok_iter);
650                                         }
651                                         break;
652                                 default:
653                                         cerr << "i was to lazy to implement the other format types for now" << endl;
654                         }
655                         count++;
656                 }
657         }
658         inFile.close();
659
660         cout << endl;
661
662 /*
663         for(int i = 0; i <= 32; i += 4) {
664                 Iinstr *pinstr = cpu.getProg(i);
665                 if(pinstr != NULL) {
666                         cout << i << " : " << std::hex << i << std::dec << " " << pinstr->toString() << endl;
667                 }
668                 else {
669                         cout << "Null at " << i << " : " << std::hex << i << endl;
670                 }
671         }
672
673         for(int i = 0; i <= 32; i += 4) {
674                 CDat data = cpu.getRAM(i);
675                 cout << i << " : " << std::hex << i << std::dec << " " << data << endl;
676         }
677 */
678 /*      cpu.setRegister(1, 4);
679         cpu.setRegister(2, 0);
680         cpu.setRAM(0,5);
681         cpu.setRAM(4,0x66334455);
682         cpu.setRAM(8,32);
683         cpu.setRAM(12,45);
684 */
685         // following: job of the bootloader
686         //set stackpointer
687         cpu.setStack(500);
688         //set return to nowhere for ret
689         cpu.setRAM(500,500);
690
691         SReadline Reader;
692
693         MyCompleterContainer Completers;
694
695         CHelpExec HelpExec(Completers);
696
697         Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec), "Prints this message"));
698         Completers.push_back(CompleterElement("quit", &doExit, "Exits program"));
699         Completers.push_back(CompleterElement("exit", &doExit, "Exits program"));
700         Completers.push_back(CompleterElement("step [count]",&execStep, "Runs [count] ticks. if count is not given one tick is executed."));
701         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."));
702         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."));
703         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."));
704         Completers.push_back(CompleterElement("break addr",&setBreak, "Sets a breakpoint for address addr."));
705         Completers.push_back(CompleterElement("listbreaks",&listBreaks, "Lists all breakpoints."));
706         Completers.push_back(CompleterElement("run",&execRun, "Runs till next breakpoint or end of program."));
707         Completers.push_back(CompleterElement("setpc [num]",&setPC, "Sets PC to num. if num is omitted 0 is used."));
708         Completers.push_back(CompleterElement("setreg [s] [num]",&setReg, "Sets Register s to num."));
709         Completers.push_back(CompleterElement("setdata [s] [num]",&setRam, "Sets RAM-Addr s to num."));
710         Completers.push_back(CompleterElement("status",&printStatus, "Prints status of CPU."));
711         Completers.push_back(CompleterElement("getperf",&getPerf, "Prints performance counter."));
712         Completers.push_back(CompleterElement("resetperf",&resetPerf, "Resets performance counter to 0."));
713
714         Reader.RegisterCompletions(Completers);
715
716         string UserInput;
717         vector<string> Tokens, lastTokens;
718         bool EndOfInput = false;
719
720         //tilab g++44 doesn't like auto here
721         MyCompleterContainer::iterator Found(Completers.end());
722
723         Func lastFunc = NULL;
724
725
726         while(!exitProg) {
727                 UserInput = Reader.GetLine("> ", Tokens, EndOfInput);
728                 if(EndOfInput) {
729                         break;
730                 }
731
732                 if(!Tokens.empty()) {
733                         Found = find_if(Completers.begin(), Completers.end(), LookupFunctor(Tokens));
734
735                         if(Found != Completers.end()) {
736                                 if((*Found).get<1>() != 0) {
737                                         lastFunc = (*Found).get<1>();
738                                         lastFunc(Tokens);
739                                         lastTokens = Tokens;
740                                         //(*Found).get<1>()(Tokens);
741                                 }
742                         }
743                         else {
744                                 lastFunc = NULL;
745                                 cout << "Unknown command. 'help' displays help" << endl;
746                         }
747                 }
748                 else {
749                         if(lastFunc != NULL) {
750                                 lastFunc(lastTokens);
751                         }
752                         else {
753                                 cout << "Unknown command. 'help' displays help" << endl;
754                         }
755                 }
756         }
757
758
759 /*
760         for(int i = 0; ; i++) {
761                 try {
762                         cpu.tick();
763                         cout << " reg0: " << cpu.getRegister(0) <<  " reg1: " << cpu.getRegister(1);
764                         cout << " reg2: " << cpu.getRegister(2) <<  " reg3: " << cpu.getRegister(3);
765                         cout << " reg4: " << cpu.getRegister(4) <<  " reg5: " << cpu.getRegister(5);
766                         cout << endl << endl;
767
768                 }
769                 catch(string& e) {
770                         cerr << e << endl;
771                         break;
772                 }
773         }
774 */
775         return EXIT_SUCCESS;
776 }