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