/** * @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 CInstructionInc : public CInstruction { typedef CInstruction super; public: CInstructionInc() : CInstruction("inc") {} CInstructionInc *factory() { return new CInstructionInc; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; /*----------------------------------------------------------------------------*/ template void CInstructionInc::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionInc::execute(CCPU *cpu) { assert(cpu != NULL); super::checkRegister(cpu, m_regidx1); cpu->getRegisters()[ m_regidx1 ]++; } /*============================================================================*/ /** * @class CInstructionDec * * Implementation of assembler command "dec" * Syntax: dec R1 * (R1--) */ template class CInstructionDec : public CInstruction { typedef CInstruction super; public: CInstructionDec() : CInstruction("dec") {} CInstructionDec *factory() { return new CInstructionDec; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; /*----------------------------------------------------------------------------*/ template void CInstructionDec::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionDec::execute(CCPU *cpu) { assert(cpu != NULL); 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 CInstructionAdd : public CInstruction { typedef CInstruction super; public: CInstructionAdd() : CInstruction("add") {} CInstructionAdd *factory() { return new CInstructionAdd; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; /** register number */ unsigned m_regidx3; }; /*----------------------------------------------------------------------------*/ template void CInstructionAdd::compile(std::list& 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 void CInstructionAdd::execute(CCPU *cpu) { assert(cpu != NULL); 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 CInstructionSub : public CInstruction { typedef CInstruction super; public: CInstructionSub() : CInstruction("sub") {} CInstructionSub *factory() { return new CInstructionSub; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; /** register number */ unsigned m_regidx3; }; /*----------------------------------------------------------------------------*/ template void CInstructionSub::compile(std::list& 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 void CInstructionSub::execute(CCPU *cpu) { assert(cpu != NULL); 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 CInstructionMul : public CInstruction { typedef CInstruction super; public: CInstructionMul() : CInstruction("mul") {} CInstructionMul *factory() { return new CInstructionMul; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; /** register number */ unsigned m_regidx3; }; /*----------------------------------------------------------------------------*/ template void CInstructionMul::compile(std::list& 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 void CInstructionMul::execute(CCPU *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 CInstructionDiv : public CInstruction { typedef CInstruction super; public: CInstructionDiv() : CInstruction("div") {} CInstructionDiv *factory() { return new CInstructionDiv; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; /** register number */ unsigned m_regidx3; }; /*----------------------------------------------------------------------------*/ template void CInstructionDiv::compile(std::list& 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 void CInstructionDiv::execute(CCPU *cpu) { assert(cpu != NULL); 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 CInstructionLoad : public CInstruction { typedef CInstruction super; public: CInstructionLoad() : CInstruction("load") {} CInstructionLoad *factory() { return new CInstructionLoad; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; }; /*----------------------------------------------------------------------------*/ template void CInstructionLoad::compile(std::list& 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 void CInstructionLoad::execute(CCPU *cpu) { assert(cpu != NULL); assert(cpu->getMemory() != NULL); 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 CInstructionStore : public CInstruction { typedef CInstruction super; public: CInstructionStore() : CInstruction("store") {} CInstructionStore *factory() { return new CInstructionStore; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** register number */ unsigned m_regidx2; }; /*----------------------------------------------------------------------------*/ template void CInstructionStore::compile(std::list& 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 void CInstructionStore::execute(CCPU *cpu) { assert(cpu != NULL); assert(cpu->getMemory() != NULL); 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 CInstructionTest : public CInstruction { typedef CInstruction super; public: CInstructionTest() : CInstruction("test") {} CInstructionTest *factory() { return new CInstructionTest; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; /*----------------------------------------------------------------------------*/ template void CInstructionTest::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionTest::execute(CCPU *cpu) { assert(cpu != NULL); 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 CInstructionLabel : public CInstruction { typedef CInstruction super; public: CInstructionLabel() : CInstruction("label") {} CInstructionLabel *factory() { return new CInstructionLabel; } void compile(std::list& params) {} void execute(CCPU *cpu) {} }; /*============================================================================*/ /** * @class CInstructionJumpA * * Implementation of assembler command "jumpa" * Syntax: jumpa labelname * (jump to labelname) */ template class CInstructionJumpA : public CInstruction { typedef CInstruction super; public: CInstructionJumpA() : CInstruction("jumpa"), m_addr("") {} CInstructionJumpA *factory() { return new CInstructionJumpA; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; /*----------------------------------------------------------------------------*/ template void CInstructionJumpA::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionJumpA::execute(CCPU *cpu) { assert(cpu != NULL); assert(cpu->getProgram() != NULL); 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 CInstructionJumpZ : public CInstruction { typedef CInstruction super; public: CInstructionJumpZ() : CInstruction("jumpz"), m_addr("") {} CInstructionJumpZ *factory() { return new CInstructionJumpZ; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; /*----------------------------------------------------------------------------*/ template void CInstructionJumpZ::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionJumpZ::execute(CCPU *cpu) { assert(cpu != NULL); assert(cpu->getProgram() != NULL); 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 CInstructionJumpS : public CInstruction { typedef CInstruction super; public: CInstructionJumpS() : CInstruction("jumps"), m_addr("") {} CInstructionJumpS *factory() { return new CInstructionJumpS; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; /*----------------------------------------------------------------------------*/ template void CInstructionJumpS::compile(std::list& params) { if (params.size() != 1) throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ template void CInstructionJumpS::execute(CCPU *cpu) { assert(cpu != NULL); assert(cpu->getProgram() != NULL); 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 CInstructionWrite : public CInstruction { typedef CInstruction super; typedef typename std::set *>::iterator setiterator; public: CInstructionWrite() : CInstruction("write"), m_dev("") {} CInstructionWrite *factory() { return new CInstructionWrite; } void compile(std::list& params); void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; /** device name */ std::string m_dev; }; /*----------------------------------------------------------------------------*/ template void CInstructionWrite::compile(std::list& 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 void CInstructionWrite::execute(CCPU *cpu) { assert(cpu != NULL); super::checkRegister(cpu, m_regidx1); if (m_dev.empty()) throw CInstructionError("Empty device"); CDisplay *display = NULL; std::set *> 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: */