e16c26c13a90200373d6de7e9af94d2d28a121f2
[calu.git] / 3c_disasm / Iinstr.hpp
1 #ifndef __IINSTR_I_
2 #define __IINSTR_I_
3
4 #include <string>
5 #include <boost/dynamic_bitset.hpp>
6 #include <iostream>
7 #include <sstream>
8
9 class CCpu;
10
11 #include "ccpu.hpp"
12
13 class disasm;
14
15 #include "disasm.h"
16
17
18 /* concept from https://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f */
19 #define to_HEX__(x) 0x##x##LU
20
21 #define to_B5__(x) ((x & 0x0000FUL) ?  1 : 0) \
22                   +((x & 0x000F0UL) ?  2 : 0) \
23                   +((x & 0x00F00UL) ?  4 : 0) \
24                   +((x & 0x0F000UL) ?  8 : 0) \
25                   +((x & 0xF0000UL) ? 16 : 0) 
26
27 #define B5(x) ((unsigned char)to_B5__(to_HEX__(x)))
28 /* end concept */
29
30 using namespace std;
31 using namespace boost;
32
33 enum CONDITIONS {
34         NOT_EQUAL = 0,
35         EQUAL = 1,
36         NOT_OVERFLOW =2,
37         OVER_FLOW = 3,
38         NOT_CARRY = 4,
39         CARRY = 5,
40         NOT_SIGNED = 6,
41         SIGNED = 7,
42         ABOVE = 8,
43         BELOW_EQ = 9,
44         GREATER_EQ = 10,
45         LESS = 11,
46         GREATER = 12,
47         LESS_EQ = 13,
48         ALWAYS = 14,
49         NEVER = 15
50 };
51
52 class Iinstr {
53         protected:
54                 short opcode, clockcount;
55                 std::string name;
56                 short m_ra, m_rb, m_rd;
57                 bool m_c, m_d, m_hl, m_f, m_s;
58                 CDat m_imm;
59                 short m_cond;
60                 boost::dynamic_bitset<> argbits;
61                 CDat hexdump;
62                 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) {}
63
64                 CDat generate16ImmFill(const CDat value) const {
65                         CDat i = value;
66                         if(m_hl == true && m_f == true) {
67                                 i <<= 16;
68                                 i |= 0x0000FFFF;
69                         }
70                         else if(m_hl == true && m_f == false) {
71                                 i <<= 16;
72                                 i &= 0xFFFF0000;
73                         }
74                         else if(m_hl == false && m_f == true) {
75                                 i |= 0xFFFF0000;
76                         }
77                         else {
78                                 i &= 0x0000FFFF;
79                         }
80
81                         return i; 
82                 }
83
84                 CDat generate16ImmSign(const CDat value) const {
85                         CDat i = value;
86                         if(m_hl == true) {
87                                 i <<= 16;
88                         }
89                         else if(m_s == true && (i & 0x8000) != 0) {
90                                         i |= 0xFFFF0000;
91                         }
92
93                         return i; 
94                 }
95
96                 CDat generate12ImmSign(const CDat value) const {
97                         CDat i = value;
98                         if(m_s == true && (i & 0x0800) != 0) {
99                                         i |= 0xFFFFF000;
100                         }
101
102                         return i; 
103                 }
104
105                 CDat generate15ImmSign(const CDat value) const {
106                         CDat i = value;
107                         if(m_s == true && (i & 0x4000) != 0) {
108                                         i |= 0xFFFF8000;
109                         }
110
111                         return i; 
112                 }
113
114
115
116                 int getRegister(boost::dynamic_bitset<> bits) {
117                         bits.resize(4);
118                         return bits.to_ulong();
119                 }
120
121                 static CCpu* m_cpu;
122                 static disasm* m_disasm;
123
124         public:
125
126                 static void setCPU(CCpu* cpu) { m_cpu = cpu; }
127                 static void setDisasm(disasm* dasm) { m_disasm = dasm; }
128
129                 virtual ~Iinstr() {}
130                 virtual short getOpcode() { return this->opcode; }
131                 virtual std::string getName() { return this->name; }
132                 virtual void loadBits(boost::dynamic_bitset<> bits) { argbits = bits; this->constructHex(); }
133                 virtual void evalInstr() = 0;
134                 virtual void execInstr() = 0;
135                 virtual std::string toString() = 0;
136                 virtual Iinstr* getNew() = 0;
137
138                 unsigned long toNum() { return this->hexdump; }
139
140                 short getCondition() {
141                         return m_cond;
142                 }
143
144                 short getClockCount() {
145                         return clockcount;
146                 }
147
148                 void decodeCondition(short condition) {
149                         if(condition >= 0 && condition <= 15) {
150                                 m_cond = condition;
151                         }
152                         else {
153                                 throw std::string("Invalid Condition!");
154                         }
155                 }
156
157         protected:
158
159                 void constructHex()
160                 {
161                         hexdump = this->m_cond;
162                         hexdump <<= 5;
163                         hexdump += this->opcode;
164                         hexdump <<= 23;
165                         hexdump += this->argbits.to_ulong();
166                 }
167
168                 std::string getConditionFlag()
169                 {
170                         stringstream cond;
171                         switch(m_cond) {
172                                 case NOT_EQUAL:
173                                         cond << "{nq,nz}";
174                                         break;
175                                 case EQUAL:
176                                         cond << "{eq,zs}";
177                                         break;
178                                 case NOT_OVERFLOW:
179                                         cond << "no";
180                                         break;
181                                 case OVER_FLOW:
182                                         cond << "ov";
183                                         break;
184                                 case NOT_CARRY:
185                                         cond << "{nc,ae}";
186                                         break;
187                                 case CARRY:
188                                         cond << "{cs,bl}";
189                                         break;
190                                 case NOT_SIGNED:
191                                         cond << "{ns,nn}";
192                                         break;
193                                 case SIGNED:
194                                         cond << "{ss,ns}";
195                                         break;
196                                 case ABOVE:
197                                         cond << "ab";
198                                         break;
199                                 case BELOW_EQ:
200                                         cond << "be";
201                                         break;
202                                 case GREATER_EQ:
203                                         cond << "ge";
204                                         break;
205                                 case LESS:
206                                         cond << "lt";
207                                         break;
208                                 case GREATER:
209                                         cond << "gt";
210                                         break;
211                                 case LESS_EQ:
212                                         cond << "le";
213                                         break;
214                                 case ALWAYS:
215                                         cond << "";
216                                         break;
217                                 case NEVER:
218                                         cond << "nv";
219                                         break;
220                                 default:
221                                         cerr << "What did you do? more than 16 values in 5 bits?!" << endl;
222                         }
223
224                         return cond.str();
225                 }
226 };
227
228 #endif