Download | Plain Text | No Line Numbers
- /**
- * @module instructions
- * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
- * @brief Implementations of CInstruction
- * @date 26.05.2009
- */
-
- #ifndef INSTRUCTIONS_H
- #define INSTRUCTIONS_H 1
-
- #include "cinstruction.h"
- #include "ccpu.h"
- #include "cprogram.h"
-
- /**
- * @class CInstructionInc
- *
- * Implementation of assembler command "inc"
- * Syntax: inc R1
- * (R1++)
- */
- template <class T>
- class CInstructionInc
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionInc()
- : CInstruction<T>("inc")
- {}
-
- CInstructionInc *factory()
- {
- return new CInstructionInc;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionInc<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionInc<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- cpu->getRegisters()[ m_regidx1 ]++;
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionDec
- *
- * Implementation of assembler command "dec"
- * Syntax: dec R1
- * (R1--)
- */
- template <class T>
- class CInstructionDec
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionDec()
- : CInstruction<T>("dec")
- {}
-
- CInstructionDec *factory()
- {
- return new CInstructionDec;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionDec<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionDec<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- cpu->getRegisters()[ m_regidx1 ]--;
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionAdd
- *
- * Implementation of assembler command "add"
- * Syntax: add R1, R2, R3
- * (R1 = R2 + R3)
- */
- template <class T>
- class CInstructionAdd
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionAdd()
- : CInstruction<T>("add")
- {}
-
- CInstructionAdd *factory()
- {
- return new CInstructionAdd;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- /** register number */
- unsigned m_regidx3;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionAdd<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 3)
- throw CInstructionError("Invalid paramater count - must be 3");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx3 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionAdd<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- super::checkRegister(cpu, m_regidx3);
- cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
- + cpu->getRegisters()[ m_regidx3 ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionSub
- *
- * Implementation of assembler command "sub"
- * Syntax: sub R1, R2, R3
- * (R1 = R2 - R3)
- */
- template <class T>
- class CInstructionSub
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionSub()
- : CInstruction<T>("sub")
- {}
-
- CInstructionSub *factory()
- {
- return new CInstructionSub;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- /** register number */
- unsigned m_regidx3;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionSub<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 3)
- throw CInstructionError("Invalid paramater count - must be 3");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx3 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionSub<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- super::checkRegister(cpu, m_regidx3);
- cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
- - cpu->getRegisters()[ m_regidx3 ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionMul
- *
- * Implementation of assembler command "mul"
- * Syntax: mul R1, R2, R3
- * (R1 = R2 * R3)
- */
- template <class T>
- class CInstructionMul
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionMul()
- : CInstruction<T>("mul")
- {}
-
- CInstructionMul *factory()
- {
- return new CInstructionMul;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- /** register number */
- unsigned m_regidx3;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionMul<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 3)
- throw CInstructionError("Invalid paramater count - must be 3");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx3 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionMul<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- super::checkRegister(cpu, m_regidx3);
- cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
- * cpu->getRegisters()[ m_regidx3 ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionDiv
- *
- * Implementation of assembler command "div"
- * Syntax: div R1, R2, R3
- * (R1 = R2 / R3)
- */
- template <class T>
- class CInstructionDiv
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionDiv()
- : CInstruction<T>("div")
- {}
-
- CInstructionDiv *factory()
- {
- return new CInstructionDiv;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- /** register number */
- unsigned m_regidx3;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionDiv<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 3)
- throw CInstructionError("Invalid paramater count - must be 3");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx3 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionDiv<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- super::checkRegister(cpu, m_regidx3);
- cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
- / cpu->getRegisters()[ m_regidx3 ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionLoad
- *
- * Implementation of assembler command "load"
- * Syntax: load R1, R2
- * (R1 = memory[R2])
- */
- template <class T>
- class CInstructionLoad
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionLoad()
- : CInstruction<T>("load")
- {}
-
- CInstructionLoad *factory()
- {
- return new CInstructionLoad;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionLoad<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 2)
- throw CInstructionError("Invalid paramater count - must be 2");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionLoad<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- T val(cpu->getRegisters()[ m_regidx2 ]);
- cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionStore
- *
- * Implementation of assembler command "store"
- * Syntax: store R1, R2
- * (memory[R2] = R1)
- */
- template <class T>
- class CInstructionStore
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionStore()
- : CInstruction<T>("store")
- {}
-
- CInstructionStore *factory()
- {
- return new CInstructionStore;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** register number */
- unsigned m_regidx2;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionStore<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 2)
- throw CInstructionError("Invalid paramater count - must be 2");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- m_regidx2 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionStore<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- super::checkRegister(cpu, m_regidx2);
- T val(cpu->getRegisters()[ m_regidx2 ]);
- (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ];
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionTest
- *
- * Implementation of assembler command "test"
- * Syntax: test R1
- * (R1 == 0: zeroflag: true, R1 < 0: signflag: true)
- */
- template <class T>
- class CInstructionTest
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionTest()
- : CInstruction<T>("test")
- {}
-
- CInstructionTest *factory()
- {
- return new CInstructionTest;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionTest<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionTest<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- if (cpu->getRegisters()[ m_regidx1 ] == T(0))
- cpu->setFlagZero(true);
- if (cpu->getRegisters()[ m_regidx1 ] < T(0))
- cpu->setFlagSign(true);
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionLabel
- *
- * Implementation of assembler command "label"
- * Syntax: label name:
- */
- template <class T>
- class CInstructionLabel
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionLabel()
- : CInstruction<T>("label")
- {}
-
- CInstructionLabel *factory()
- {
- return new CInstructionLabel;
- }
-
- void compile(std::list<std::string>& params)
- {}
-
- void execute(CCPU<T> *cpu)
- {}
- };
-
- /*============================================================================*/
-
- /**
- * @class CInstructionJumpA
- *
- * Implementation of assembler command "jumpa"
- * Syntax: jumpa labelname
- * (jump to labelname)
- */
- template <class T>
- class CInstructionJumpA
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionJumpA()
- : CInstruction<T>("jumpa"), m_addr("")
- {}
-
- CInstructionJumpA *factory()
- {
- return new CInstructionJumpA;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** labelname */
- std::string m_addr;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpA<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_addr = params.front();
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpA<T>::execute(CCPU<T> *cpu)
- {
- if (m_addr.empty())
- throw CInstructionError("Empty address");
- try
- {
- cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
- }
- catch(CProgramError& ex)
- {
- throw CInstructionError(ex.what());
- }
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionJumpZ
- *
- * Implementation of assembler command "jumpz"
- * Syntax: jumpz labelname
- * (jump to labelname if zeroflag)
- */
- template <class T>
- class CInstructionJumpZ
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionJumpZ()
- : CInstruction<T>("jumpz"), m_addr("")
- {}
-
- CInstructionJumpZ *factory()
- {
- return new CInstructionJumpZ;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** labelname */
- std::string m_addr;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpZ<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_addr = params.front();
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpZ<T>::execute(CCPU<T> *cpu)
- {
- if (!cpu->getFlagZero())
- return;
- if (m_addr.empty())
- throw CInstructionError("Empty address");
- try
- {
- cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
- }
- catch(CProgramError& ex)
- {
- throw CInstructionError(ex.what());
- }
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionJumpS
- *
- * Implementation of assembler command "jumps"
- * Syntax: jumps labelname
- * (jump to labelname if signflag)
- */
- template <class T>
- class CInstructionJumpS
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
-
- public:
- CInstructionJumpS()
- : CInstruction<T>("jumps"), m_addr("")
- {}
-
- CInstructionJumpS *factory()
- {
- return new CInstructionJumpS;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** labelname */
- std::string m_addr;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpS<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 1)
- throw CInstructionError("Invalid paramater count - must be 1");
- m_addr = params.front();
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionJumpS<T>::execute(CCPU<T> *cpu)
- {
- if (!cpu->getFlagSign())
- return;
- if (m_addr.empty())
- throw CInstructionError("Empty address");
- try
- {
- cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
- }
- catch(CProgramError& ex)
- {
- throw CInstructionError(ex.what());
- }
- }
-
- /*============================================================================*/
-
- /**
- * @class CInstructionWrite
- *
- * Implementation of assembler command "write"
- * Syntax: write DEV, R1
- * (write R1 to DEV, which is a name of a display)
- */
- template <class T>
- class CInstructionWrite
- : public CInstruction<T>
- {
- typedef CInstruction<T> super;
- typedef typename std::set<CDisplay<T> *>::iterator setiterator;
-
- public:
- CInstructionWrite()
- : CInstruction<T>("write"), m_dev("")
- {}
-
- CInstructionWrite *factory()
- {
- return new CInstructionWrite;
- }
-
- void compile(std::list<std::string>& params);
- void execute(CCPU<T> *cpu);
-
- protected:
- /** register number */
- unsigned m_regidx1;
- /** device name */
- std::string m_dev;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionWrite<T>::compile(std::list<std::string>& params)
- {
- if (params.size() != 2)
- throw CInstructionError("Invalid paramater count - must be 2");
- m_dev = params.front();
- params.pop_front();
- m_regidx1 = super::parseRegister(params.front());
- params.pop_front();
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CInstructionWrite<T>::execute(CCPU<T> *cpu)
- {
- super::checkRegister(cpu, m_regidx1);
- if (m_dev.empty())
- throw CInstructionError("Empty device");
-
- CDisplay<T> *display = NULL;
- std::set<CDisplay<T> *> displays = cpu->getDisplays();
- for(setiterator it = displays.begin(); it != displays.end(); ++it)
- {
- if ((*it)->getName() == m_dev)
- {
- display = *it;
- break;
- }
- }
- if (display == NULL)
- throw CInstructionError("Unknown display");
-
- display->display(cpu->getRegisters()[ m_regidx1 ]);
- }
-
- #endif
-
- /* vim: set et sw=2 ts=2: */
-