X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=3c_disasm%2FIinstr.hpp;fp=3c_disasm%2FIinstr.hpp;h=95b5229d94c9d997e8f508e4a0df133326ca91f0;hb=b5f15e1e75a5027fc4eb3d27b0542cb3324ed3a9;hp=0000000000000000000000000000000000000000;hpb=d89f102f95f913e8ca5304d7c544592f5dcb9ec0;p=calu.git diff --git a/3c_disasm/Iinstr.hpp b/3c_disasm/Iinstr.hpp new file mode 100644 index 0000000..95b5229 --- /dev/null +++ b/3c_disasm/Iinstr.hpp @@ -0,0 +1,188 @@ +#include +#include +#include +#include + +#ifndef __IINSTR_I_ +#define __IINSTR_I_ + +/* 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))) + +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; + std::string name; + short m_ra, m_rb, m_rd; + bool m_c, m_d, m_hl, m_f, m_s; + int m_imm; + short m_cond; + boost::dynamic_bitset<> argbits; + Iinstr() : opcode(0), 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) {} + + int generate16ImmFill(const int value) { + int 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; + } + + int generate16ImmSign(const int value) { + int i = value; + if(m_hl == true) { + i <<= 16; + } + else if(m_s == true && (i & 0x8000) != 0) { + i |= 0xFFFF0000; + } + + return i; + } + + int generate12ImmSign(const int value) { + int i = value; + if(m_s == true && (i & 0x0800) != 0) { + i |= 0xFFFFF000; + } + + return i; + } + + int generate15ImmSign(const int value) { + int 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(); + } + + public: + virtual ~Iinstr() {} + virtual short getOpcode() { return this->opcode; } + virtual std::string getName() { return this->name; } + virtual void loadBits(boost::dynamic_bitset<> bits) { argbits = bits; } + virtual void evalInstr() = 0; + virtual void execInstr() = 0; + virtual std::string toString() = 0; + + void decodeCondition(short condition) { + if(condition >= 0 && condition <= 15) { + m_cond = condition; + } + else { + throw std::string("Invalid Condition!"); + } + } + + protected: + 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