#ifndef __IINSTR_I_ #define __IINSTR_I_ #include #include #include #include class CCpu; #include "ccpu.hpp" class disasm; #include "disasm.h" /* concept from https://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f */ #define to_HEX__(x) 0x##x##LU #define to_B5__(x) ((x & 0x0000FUL) ? 1 : 0) \ +((x & 0x000F0UL) ? 2 : 0) \ +((x & 0x00F00UL) ? 4 : 0) \ +((x & 0x0F000UL) ? 8 : 0) \ +((x & 0xF0000UL) ? 16 : 0) #define B5(x) ((unsigned char)to_B5__(to_HEX__(x))) /* end concept */ using namespace std; using namespace boost; enum CONDITIONS { NOT_EQUAL = 0, EQUAL = 1, NOT_OVERFLOW =2, OVER_FLOW = 3, NOT_CARRY = 4, CARRY = 5, NOT_SIGNED = 6, SIGNED = 7, ABOVE = 8, BELOW_EQ = 9, GREATER_EQ = 10, LESS = 11, GREATER = 12, LESS_EQ = 13, ALWAYS = 14, NEVER = 15 }; class Iinstr { protected: short opcode, clockcount; std::string name; short m_ra, m_rb, m_rd; bool m_c, m_d, m_hl, m_f, m_s; CDat m_imm; short m_cond; boost::dynamic_bitset<> argbits; CDat hexdump; Iinstr() : opcode(0), clockcount(1), name(""), m_ra(0), m_rb(0), m_rd(0), m_c(0), m_d(0), m_hl(0), m_f(0), m_s(0), m_imm(0), m_cond(ALWAYS), argbits(32), hexdump(0) {} CDat generate16ImmFill(const CDat value) const { CDat i = value; if(m_hl == true && m_f == true) { i <<= 16; i |= 0x0000FFFF; } else if(m_hl == true && m_f == false) { i <<= 16; i &= 0xFFFF0000; } else if(m_hl == false && m_f == true) { i |= 0xFFFF0000; } else { i &= 0x0000FFFF; } return i; } CDat generate16ImmSign(const CDat value) const { CDat i = value; if(m_hl == true) { i <<= 16; } else if(m_s == true && (i & 0x8000) != 0) { i |= 0xFFFF0000; } return i; } CDat generate12ImmSign(const CDat value) const { CDat i = value; if(m_s == true && (i & 0x0800) != 0) { i |= 0xFFFFF000; } return i; } CDat generate15ImmSign(const CDat value) const { CDat i = value; if(m_s == true && (i & 0x4000) != 0) { i |= 0xFFFF8000; } return i; } int getRegister(boost::dynamic_bitset<> bits) { bits.resize(4); return bits.to_ulong(); } static CCpu* m_cpu; static disasm* m_disasm; public: static void setCPU(CCpu* cpu) { m_cpu = cpu; } static void setDisasm(disasm* dasm) { m_disasm = dasm; } virtual ~Iinstr() {} virtual short getOpcode() { return this->opcode; } virtual std::string getName() { return this->name; } virtual void loadBits(boost::dynamic_bitset<> bits) { argbits = bits; this->constructHex(); } virtual void evalInstr() = 0; virtual void execInstr() = 0; virtual std::string toString() = 0; virtual Iinstr* getNew() = 0; unsigned long toNum() { return this->hexdump; } short getCondition() { return m_cond; } short getClockCount() { return clockcount; } void decodeCondition(short condition) { if(condition >= 0 && condition <= 15) { m_cond = condition; } else { throw std::string("Invalid Condition!"); } } protected: void constructHex() { hexdump = this->m_cond; hexdump <<= 5; hexdump += this->opcode; hexdump <<= 23; hexdump += this->argbits.to_ulong(); } std::string getConditionFlag() { stringstream cond; switch(m_cond) { case NOT_EQUAL: cond << "{nq,nz}"; break; case EQUAL: cond << "{eq,zs}"; break; case NOT_OVERFLOW: cond << "no"; break; case OVER_FLOW: cond << "ov"; break; case NOT_CARRY: cond << "{nc,ae}"; break; case CARRY: cond << "{cs,bl}"; break; case NOT_SIGNED: cond << "{ns,nn}"; break; case SIGNED: cond << "{ss,ns}"; break; case ABOVE: cond << "ab"; break; case BELOW_EQ: cond << "be"; break; case GREATER_EQ: cond << "ge"; break; case LESS: cond << "lt"; break; case GREATER: cond << "gt"; break; case LESS_EQ: cond << "le"; break; case ALWAYS: cond << ""; break; case NEVER: cond << "nv"; break; default: cerr << "What did you do? more than 16 values in 5 bits?!" << endl; } return cond.str(); } }; #endif