/** * @module instructions * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief TODO * @date 10.05.2009 */ #include "instructions.h" using namespace std; void CInstructionInc::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_regidx1 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionInc::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); cpu->getRegisters()[ m_regidx1 ]++; } /*============================================================================*/ void CInstructionDec::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_regidx1 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionDec::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); cpu->getRegisters()[ m_regidx1 ]--; } /*============================================================================*/ void CInstructionAdd::compile(std::list& params) { if (params.size() != 3) throw runtime_error("Invalid paramater count - must be 3"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); m_regidx3 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionAdd::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); checkRegister(cpu, m_regidx3); cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] + cpu->getRegisters()[ m_regidx3 ]; } /*============================================================================*/ void CInstructionSub::compile(std::list& params) { if (params.size() != 3) throw runtime_error("Invalid paramater count - must be 3"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); m_regidx3 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionSub::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); checkRegister(cpu, m_regidx3); cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] - cpu->getRegisters()[ m_regidx3 ]; } /*============================================================================*/ void CInstructionMul::compile(std::list& params) { if (params.size() != 3) throw runtime_error("Invalid paramater count - must be 3"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); m_regidx3 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionMul::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); checkRegister(cpu, m_regidx3); cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] * cpu->getRegisters()[ m_regidx3 ]; } /*============================================================================*/ void CInstructionDiv::compile(std::list& params) { if (params.size() != 3) throw runtime_error("Invalid paramater count - must be 3"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); m_regidx3 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionDiv::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); checkRegister(cpu, m_regidx3); cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] / cpu->getRegisters()[ m_regidx3 ]; } /*============================================================================*/ void CInstructionLoad::compile(std::list& params) { if (params.size() != 2) throw runtime_error("Invalid paramater count - must be 2"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionLoad::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); CDat val = cpu->getRegisters()[ m_regidx2 ]; cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ]; } /*============================================================================*/ void CInstructionStore::compile(std::list& params) { if (params.size() != 2) throw runtime_error("Invalid paramater count - must be 2"); m_regidx1 = parseRegister(params.front()); params.pop_front(); m_regidx2 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionStore::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); checkRegister(cpu, m_regidx2); CDat val = cpu->getRegisters()[ m_regidx2 ]; (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ]; } /*============================================================================*/ void CInstructionTest::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_regidx1 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionTest::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); if (cpu->getRegisters()[ m_regidx1 ] == CDat(0)) cpu->setFlagZero(true); if (cpu->getRegisters()[ m_regidx1 ] < CDat(0)) cpu->setFlagSign(true); } /*============================================================================*/ void CInstructionLabel::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); string label = params.front(); params.pop_front(); if (label.length() < 2 || label[ label.length() - 1] != ':') throw runtime_error("Label has invalid syntax"); m_label = label.substr(0, label.length() - 1); } /*----------------------------------------------------------------------------*/ void CInstructionLabel::execute(CCPU *cpu) { if (m_label.empty()) throw runtime_error("Empty label"); } /*============================================================================*/ void CInstructionJumpA::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionJumpA::execute(CCPU *cpu) { if (m_addr.empty()) throw runtime_error("Empty address"); const CProgram *progam = cpu->getProgram(); for(unsigned i = 0; i < progam->size(); i++) { if (progam->at(i)->isLabel() && progam->at(i)->getLabelName() == m_addr) { cpu->getRegisters()[ 0 ] = i; return; } } throw runtime_error("Unknown label '" + m_addr + "'"); } /*============================================================================*/ void CInstructionJumpZ::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionJumpZ::execute(CCPU *cpu) { if (!cpu->getFlagZero()) return; if (m_addr.empty()) throw runtime_error("Empty address"); const CProgram *progam = cpu->getProgram(); for(unsigned i = 0; i < progam->size(); i++) { if (progam->at(i)->isLabel() && progam->at(i)->getLabelName() == m_addr) { cpu->getRegisters()[ 0 ] = i; return; } } throw runtime_error("Unknown label '" + m_addr + "'"); } /*============================================================================*/ void CInstructionJumpS::compile(std::list& params) { if (params.size() != 1) throw runtime_error("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionJumpS::execute(CCPU *cpu) { if (!cpu->getFlagSign()) return; if (m_addr.empty()) throw runtime_error("Empty address"); const CProgram *progam = cpu->getProgram(); for(unsigned i = 0; i < progam->size(); i++) { if (progam->at(i)->isLabel() && progam->at(i)->getLabelName() == m_addr) { cpu->getRegisters()[ 0 ] = i; return; } } throw runtime_error("Unknown label '" + m_addr + "'"); } /*============================================================================*/ void CInstructionWrite::compile(std::list& params) { if (params.size() != 2) throw runtime_error("Invalid paramater count - must be 2"); m_dev = params.front(); params.pop_front(); m_regidx1 = parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ void CInstructionWrite::execute(CCPU *cpu) { checkRegister(cpu, m_regidx1); if (m_dev.empty()) throw runtime_error("Empty device"); CDisplay *display = NULL; std::set displays = cpu->getDisplays(); std::set::iterator it; for(it = displays.begin(); it != displays.end(); ++it) { if ((*it)->getName() == m_dev) { display = *it; break; } } if (display == NULL) throw runtime_error("Unknown display"); display->display(cpu->getRegisters()[ m_regidx1 ]); } /* vim: set et sw=2 ts=2: */