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