00001
00008 #ifndef INSTRUCTIONS_H
00009 #define INSTRUCTIONS_H 1
00010
00011 #include "cinstruction.h"
00012 #include "ccpu.h"
00013 #include "cprogram.h"
00014
00022 template <class T>
00023 class CInstructionInc
00024 : public CInstruction<T>
00025 {
00026 typedef CInstruction<T> super;
00027
00028 public:
00029 CInstructionInc()
00030 : CInstruction<T>("inc")
00031 {}
00032
00033 CInstructionInc *factory()
00034 {
00035 return new CInstructionInc;
00036 }
00037
00038 void compile(std::list<std::string>& params);
00039 void execute(CCPU<T> *cpu);
00040
00041 protected:
00043 unsigned m_regidx1;
00044 };
00045
00046
00047
00048 template <class T>
00049 void CInstructionInc<T>::compile(std::list<std::string>& params)
00050 {
00051 if (params.size() != 1)
00052 throw CInstructionError("Invalid paramater count - must be 1");
00053 m_regidx1 = super::parseRegister(params.front());
00054 params.pop_front();
00055 }
00056
00057
00058
00059 template <class T>
00060 void CInstructionInc<T>::execute(CCPU<T> *cpu)
00061 {
00062 assert(cpu != NULL);
00063 super::checkRegister(cpu, m_regidx1);
00064 cpu->getRegisters()[ m_regidx1 ]++;
00065 }
00066
00067
00068
00076 template <class T>
00077 class CInstructionDec
00078 : public CInstruction<T>
00079 {
00080 typedef CInstruction<T> super;
00081
00082 public:
00083 CInstructionDec()
00084 : CInstruction<T>("dec")
00085 {}
00086
00087 CInstructionDec *factory()
00088 {
00089 return new CInstructionDec;
00090 }
00091
00092 void compile(std::list<std::string>& params);
00093 void execute(CCPU<T> *cpu);
00094
00095 protected:
00097 unsigned m_regidx1;
00098 };
00099
00100
00101
00102 template <class T>
00103 void CInstructionDec<T>::compile(std::list<std::string>& params)
00104 {
00105 if (params.size() != 1)
00106 throw CInstructionError("Invalid paramater count - must be 1");
00107 m_regidx1 = super::parseRegister(params.front());
00108 params.pop_front();
00109 }
00110
00111
00112
00113 template <class T>
00114 void CInstructionDec<T>::execute(CCPU<T> *cpu)
00115 {
00116 assert(cpu != NULL);
00117 super::checkRegister(cpu, m_regidx1);
00118 cpu->getRegisters()[ m_regidx1 ]--;
00119 }
00120
00121
00122
00130 template <class T>
00131 class CInstructionAdd
00132 : public CInstruction<T>
00133 {
00134 typedef CInstruction<T> super;
00135
00136 public:
00137 CInstructionAdd()
00138 : CInstruction<T>("add")
00139 {}
00140
00141 CInstructionAdd *factory()
00142 {
00143 return new CInstructionAdd;
00144 }
00145
00146 void compile(std::list<std::string>& params);
00147 void execute(CCPU<T> *cpu);
00148
00149 protected:
00151 unsigned m_regidx1;
00153 unsigned m_regidx2;
00155 unsigned m_regidx3;
00156 };
00157
00158
00159
00160 template <class T>
00161 void CInstructionAdd<T>::compile(std::list<std::string>& params)
00162 {
00163 if (params.size() != 3)
00164 throw CInstructionError("Invalid paramater count - must be 3");
00165 m_regidx1 = super::parseRegister(params.front());
00166 params.pop_front();
00167 m_regidx2 = super::parseRegister(params.front());
00168 params.pop_front();
00169 m_regidx3 = super::parseRegister(params.front());
00170 params.pop_front();
00171 }
00172
00173
00174
00175 template <class T>
00176 void CInstructionAdd<T>::execute(CCPU<T> *cpu)
00177 {
00178 assert(cpu != NULL);
00179 super::checkRegister(cpu, m_regidx1);
00180 super::checkRegister(cpu, m_regidx2);
00181 super::checkRegister(cpu, m_regidx3);
00182 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
00183 + cpu->getRegisters()[ m_regidx3 ];
00184 }
00185
00186
00187
00195 template <class T>
00196 class CInstructionSub
00197 : public CInstruction<T>
00198 {
00199 typedef CInstruction<T> super;
00200
00201 public:
00202 CInstructionSub()
00203 : CInstruction<T>("sub")
00204 {}
00205
00206 CInstructionSub *factory()
00207 {
00208 return new CInstructionSub;
00209 }
00210
00211 void compile(std::list<std::string>& params);
00212 void execute(CCPU<T> *cpu);
00213
00214 protected:
00216 unsigned m_regidx1;
00218 unsigned m_regidx2;
00220 unsigned m_regidx3;
00221 };
00222
00223
00224
00225 template <class T>
00226 void CInstructionSub<T>::compile(std::list<std::string>& params)
00227 {
00228 if (params.size() != 3)
00229 throw CInstructionError("Invalid paramater count - must be 3");
00230 m_regidx1 = super::parseRegister(params.front());
00231 params.pop_front();
00232 m_regidx2 = super::parseRegister(params.front());
00233 params.pop_front();
00234 m_regidx3 = super::parseRegister(params.front());
00235 params.pop_front();
00236 }
00237
00238
00239
00240 template <class T>
00241 void CInstructionSub<T>::execute(CCPU<T> *cpu)
00242 {
00243 assert(cpu != NULL);
00244 super::checkRegister(cpu, m_regidx1);
00245 super::checkRegister(cpu, m_regidx2);
00246 super::checkRegister(cpu, m_regidx3);
00247 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
00248 - cpu->getRegisters()[ m_regidx3 ];
00249 }
00250
00251
00252
00260 template <class T>
00261 class CInstructionMul
00262 : public CInstruction<T>
00263 {
00264 typedef CInstruction<T> super;
00265
00266 public:
00267 CInstructionMul()
00268 : CInstruction<T>("mul")
00269 {}
00270
00271 CInstructionMul *factory()
00272 {
00273 return new CInstructionMul;
00274 }
00275
00276 void compile(std::list<std::string>& params);
00277 void execute(CCPU<T> *cpu);
00278
00279 protected:
00281 unsigned m_regidx1;
00283 unsigned m_regidx2;
00285 unsigned m_regidx3;
00286 };
00287
00288
00289
00290 template <class T>
00291 void CInstructionMul<T>::compile(std::list<std::string>& params)
00292 {
00293 if (params.size() != 3)
00294 throw CInstructionError("Invalid paramater count - must be 3");
00295 m_regidx1 = super::parseRegister(params.front());
00296 params.pop_front();
00297 m_regidx2 = super::parseRegister(params.front());
00298 params.pop_front();
00299 m_regidx3 = super::parseRegister(params.front());
00300 params.pop_front();
00301 }
00302
00303
00304
00305 template <class T>
00306 void CInstructionMul<T>::execute(CCPU<T> *cpu)
00307 {
00308 super::checkRegister(cpu, m_regidx1);
00309 super::checkRegister(cpu, m_regidx2);
00310 super::checkRegister(cpu, m_regidx3);
00311 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
00312 * cpu->getRegisters()[ m_regidx3 ];
00313 }
00314
00315
00316
00324 template <class T>
00325 class CInstructionDiv
00326 : public CInstruction<T>
00327 {
00328 typedef CInstruction<T> super;
00329
00330 public:
00331 CInstructionDiv()
00332 : CInstruction<T>("div")
00333 {}
00334
00335 CInstructionDiv *factory()
00336 {
00337 return new CInstructionDiv;
00338 }
00339
00340 void compile(std::list<std::string>& params);
00341 void execute(CCPU<T> *cpu);
00342
00343 protected:
00345 unsigned m_regidx1;
00347 unsigned m_regidx2;
00349 unsigned m_regidx3;
00350 };
00351
00352
00353
00354 template <class T>
00355 void CInstructionDiv<T>::compile(std::list<std::string>& params)
00356 {
00357 if (params.size() != 3)
00358 throw CInstructionError("Invalid paramater count - must be 3");
00359 m_regidx1 = super::parseRegister(params.front());
00360 params.pop_front();
00361 m_regidx2 = super::parseRegister(params.front());
00362 params.pop_front();
00363 m_regidx3 = super::parseRegister(params.front());
00364 params.pop_front();
00365 }
00366
00367
00368
00369 template <class T>
00370 void CInstructionDiv<T>::execute(CCPU<T> *cpu)
00371 {
00372 assert(cpu != NULL);
00373 super::checkRegister(cpu, m_regidx1);
00374 super::checkRegister(cpu, m_regidx2);
00375 super::checkRegister(cpu, m_regidx3);
00376 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
00377 / cpu->getRegisters()[ m_regidx3 ];
00378 }
00379
00380
00381
00389 template <class T>
00390 class CInstructionLoad
00391 : public CInstruction<T>
00392 {
00393 typedef CInstruction<T> super;
00394
00395 public:
00396 CInstructionLoad()
00397 : CInstruction<T>("load")
00398 {}
00399
00400 CInstructionLoad *factory()
00401 {
00402 return new CInstructionLoad;
00403 }
00404
00405 void compile(std::list<std::string>& params);
00406 void execute(CCPU<T> *cpu);
00407
00408 protected:
00410 unsigned m_regidx1;
00412 unsigned m_regidx2;
00413 };
00414
00415
00416
00417 template <class T>
00418 void CInstructionLoad<T>::compile(std::list<std::string>& params)
00419 {
00420 if (params.size() != 2)
00421 throw CInstructionError("Invalid paramater count - must be 2");
00422 m_regidx1 = super::parseRegister(params.front());
00423 params.pop_front();
00424 m_regidx2 = super::parseRegister(params.front());
00425 params.pop_front();
00426 }
00427
00428
00429
00430 template <class T>
00431 void CInstructionLoad<T>::execute(CCPU<T> *cpu)
00432 {
00433 assert(cpu != NULL);
00434 assert(cpu->getMemory() != NULL);
00435 super::checkRegister(cpu, m_regidx1);
00436 super::checkRegister(cpu, m_regidx2);
00437 T val(cpu->getRegisters()[ m_regidx2 ]);
00438 cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ];
00439 }
00440
00441
00442
00450 template <class T>
00451 class CInstructionStore
00452 : public CInstruction<T>
00453 {
00454 typedef CInstruction<T> super;
00455
00456 public:
00457 CInstructionStore()
00458 : CInstruction<T>("store")
00459 {}
00460
00461 CInstructionStore *factory()
00462 {
00463 return new CInstructionStore;
00464 }
00465
00466 void compile(std::list<std::string>& params);
00467 void execute(CCPU<T> *cpu);
00468
00469 protected:
00471 unsigned m_regidx1;
00473 unsigned m_regidx2;
00474 };
00475
00476
00477
00478 template <class T>
00479 void CInstructionStore<T>::compile(std::list<std::string>& params)
00480 {
00481 if (params.size() != 2)
00482 throw CInstructionError("Invalid paramater count - must be 2");
00483 m_regidx1 = super::parseRegister(params.front());
00484 params.pop_front();
00485 m_regidx2 = super::parseRegister(params.front());
00486 params.pop_front();
00487 }
00488
00489
00490
00491 template <class T>
00492 void CInstructionStore<T>::execute(CCPU<T> *cpu)
00493 {
00494 assert(cpu != NULL);
00495 assert(cpu->getMemory() != NULL);
00496 super::checkRegister(cpu, m_regidx1);
00497 super::checkRegister(cpu, m_regidx2);
00498 T val(cpu->getRegisters()[ m_regidx2 ]);
00499 (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ];
00500 }
00501
00502
00503
00511 template <class T>
00512 class CInstructionTest
00513 : public CInstruction<T>
00514 {
00515 typedef CInstruction<T> super;
00516
00517 public:
00518 CInstructionTest()
00519 : CInstruction<T>("test")
00520 {}
00521
00522 CInstructionTest *factory()
00523 {
00524 return new CInstructionTest;
00525 }
00526
00527 void compile(std::list<std::string>& params);
00528 void execute(CCPU<T> *cpu);
00529
00530 protected:
00532 unsigned m_regidx1;
00533 };
00534
00535
00536
00537 template <class T>
00538 void CInstructionTest<T>::compile(std::list<std::string>& params)
00539 {
00540 if (params.size() != 1)
00541 throw CInstructionError("Invalid paramater count - must be 1");
00542 m_regidx1 = super::parseRegister(params.front());
00543 params.pop_front();
00544 }
00545
00546
00547
00548 template <class T>
00549 void CInstructionTest<T>::execute(CCPU<T> *cpu)
00550 {
00551 assert(cpu != NULL);
00552 super::checkRegister(cpu, m_regidx1);
00553 if (cpu->getRegisters()[ m_regidx1 ] == T(0))
00554 cpu->setFlagZero(true);
00555 if (cpu->getRegisters()[ m_regidx1 ] < T(0))
00556 cpu->setFlagSign(true);
00557 }
00558
00559
00560
00567 template <class T>
00568 class CInstructionLabel
00569 : public CInstruction<T>
00570 {
00571 typedef CInstruction<T> super;
00572
00573 public:
00574 CInstructionLabel()
00575 : CInstruction<T>("label")
00576 {}
00577
00578 CInstructionLabel *factory()
00579 {
00580 return new CInstructionLabel;
00581 }
00582
00583 void compile(std::list<std::string>& params)
00584 {}
00585
00586 void execute(CCPU<T> *cpu)
00587 {}
00588 };
00589
00590
00591
00599 template <class T>
00600 class CInstructionJumpA
00601 : public CInstruction<T>
00602 {
00603 typedef CInstruction<T> super;
00604
00605 public:
00606 CInstructionJumpA()
00607 : CInstruction<T>("jumpa"), m_addr("")
00608 {}
00609
00610 CInstructionJumpA *factory()
00611 {
00612 return new CInstructionJumpA;
00613 }
00614
00615 void compile(std::list<std::string>& params);
00616 void execute(CCPU<T> *cpu);
00617
00618 protected:
00620 std::string m_addr;
00621 };
00622
00623
00624
00625 template <class T>
00626 void CInstructionJumpA<T>::compile(std::list<std::string>& params)
00627 {
00628 if (params.size() != 1)
00629 throw CInstructionError("Invalid paramater count - must be 1");
00630 m_addr = params.front();
00631 params.pop_front();
00632 }
00633
00634
00635
00636 template <class T>
00637 void CInstructionJumpA<T>::execute(CCPU<T> *cpu)
00638 {
00639 assert(cpu != NULL);
00640 assert(cpu->getProgram() != NULL);
00641 if (m_addr.empty())
00642 throw CInstructionError("Empty address");
00643 try
00644 {
00645 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
00646 }
00647 catch(CProgramError& ex)
00648 {
00649 throw CInstructionError(ex.what());
00650 }
00651 }
00652
00653
00654
00662 template <class T>
00663 class CInstructionJumpZ
00664 : public CInstruction<T>
00665 {
00666 typedef CInstruction<T> super;
00667
00668 public:
00669 CInstructionJumpZ()
00670 : CInstruction<T>("jumpz"), m_addr("")
00671 {}
00672
00673 CInstructionJumpZ *factory()
00674 {
00675 return new CInstructionJumpZ;
00676 }
00677
00678 void compile(std::list<std::string>& params);
00679 void execute(CCPU<T> *cpu);
00680
00681 protected:
00683 std::string m_addr;
00684 };
00685
00686
00687
00688 template <class T>
00689 void CInstructionJumpZ<T>::compile(std::list<std::string>& params)
00690 {
00691 if (params.size() != 1)
00692 throw CInstructionError("Invalid paramater count - must be 1");
00693 m_addr = params.front();
00694 params.pop_front();
00695 }
00696
00697
00698
00699 template <class T>
00700 void CInstructionJumpZ<T>::execute(CCPU<T> *cpu)
00701 {
00702 assert(cpu != NULL);
00703 assert(cpu->getProgram() != NULL);
00704 if (!cpu->getFlagZero())
00705 return;
00706 if (m_addr.empty())
00707 throw CInstructionError("Empty address");
00708 try
00709 {
00710 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
00711 }
00712 catch(CProgramError& ex)
00713 {
00714 throw CInstructionError(ex.what());
00715 }
00716 }
00717
00718
00719
00727 template <class T>
00728 class CInstructionJumpS
00729 : public CInstruction<T>
00730 {
00731 typedef CInstruction<T> super;
00732
00733 public:
00734 CInstructionJumpS()
00735 : CInstruction<T>("jumps"), m_addr("")
00736 {}
00737
00738 CInstructionJumpS *factory()
00739 {
00740 return new CInstructionJumpS;
00741 }
00742
00743 void compile(std::list<std::string>& params);
00744 void execute(CCPU<T> *cpu);
00745
00746 protected:
00748 std::string m_addr;
00749 };
00750
00751
00752
00753 template <class T>
00754 void CInstructionJumpS<T>::compile(std::list<std::string>& params)
00755 {
00756 if (params.size() != 1)
00757 throw CInstructionError("Invalid paramater count - must be 1");
00758 m_addr = params.front();
00759 params.pop_front();
00760 }
00761
00762
00763
00764 template <class T>
00765 void CInstructionJumpS<T>::execute(CCPU<T> *cpu)
00766 {
00767 assert(cpu != NULL);
00768 assert(cpu->getProgram() != NULL);
00769 if (!cpu->getFlagSign())
00770 return;
00771 if (m_addr.empty())
00772 throw CInstructionError("Empty address");
00773 try
00774 {
00775 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
00776 }
00777 catch(CProgramError& ex)
00778 {
00779 throw CInstructionError(ex.what());
00780 }
00781 }
00782
00783
00784
00792 template <class T>
00793 class CInstructionWrite
00794 : public CInstruction<T>
00795 {
00796 typedef CInstruction<T> super;
00797 typedef typename std::set<CDisplay<T> *>::iterator setiterator;
00798
00799 public:
00800 CInstructionWrite()
00801 : CInstruction<T>("write"), m_dev("")
00802 {}
00803
00804 CInstructionWrite *factory()
00805 {
00806 return new CInstructionWrite;
00807 }
00808
00809 void compile(std::list<std::string>& params);
00810 void execute(CCPU<T> *cpu);
00811
00812 protected:
00814 unsigned m_regidx1;
00816 std::string m_dev;
00817 };
00818
00819
00820
00821 template <class T>
00822 void CInstructionWrite<T>::compile(std::list<std::string>& params)
00823 {
00824 if (params.size() != 2)
00825 throw CInstructionError("Invalid paramater count - must be 2");
00826 m_dev = params.front();
00827 params.pop_front();
00828 m_regidx1 = super::parseRegister(params.front());
00829 params.pop_front();
00830 }
00831
00832
00833
00834 template <class T>
00835 void CInstructionWrite<T>::execute(CCPU<T> *cpu)
00836 {
00837 assert(cpu != NULL);
00838 super::checkRegister(cpu, m_regidx1);
00839 if (m_dev.empty())
00840 throw CInstructionError("Empty device");
00841
00842 CDisplay<T> *display = NULL;
00843 std::set<CDisplay<T> *> displays = cpu->getDisplays();
00844 for(setiterator it = displays.begin(); it != displays.end(); ++it)
00845 {
00846 if ((*it)->getName() == m_dev)
00847 {
00848 display = *it;
00849 break;
00850 }
00851 }
00852 if (display == NULL)
00853 throw CInstructionError("Unknown display");
00854
00855 display->display(cpu->getRegisters()[ m_regidx1 ]);
00856 }
00857
00858 #endif
00859
00860