Download | Plain Text | 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
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 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)
{
assert(cpu != NULL);
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: */