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