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