mycpu/instructions.h

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 /* vim: set et sw=2 ts=2: */

Generated on Sat May 30 16:32:35 2009 for mycpu by  doxygen 1.5.3