/* `Deep Thought', a softcore CPU implemented on a FPGA Copyright (C) 2010 Markus Hofstaetter Copyright (C) 2010 Martin Perner Copyright (C) 2010 Stefan Rebernig Copyright (C) 2010 Manfred Schwarz Copyright (C) 2010 Bernhard Urban This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #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