copyleft: gplv3 added and set repo to public
[calu.git] / 3c_disasm / Iinstr.hpp
1 /*   `Deep Thought', a softcore CPU implemented on a FPGA
2
3     Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4     Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5     Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6     Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7     Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8
9     This program is free software: you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation, either version 3 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22 #ifndef __IINSTR_I_
23 #define __IINSTR_I_
24
25 #include <string>
26 #include <boost/dynamic_bitset.hpp>
27 #include <iostream>
28 #include <sstream>
29
30 class CCpu;
31
32 #include "ccpu.hpp"
33
34 class disasm;
35
36 #include "disasm.h"
37
38
39 /* concept from https://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f */
40 #define to_HEX__(x) 0x##x##LU
41
42 #define to_B5__(x) ((x & 0x0000FUL) ?  1 : 0) \
43                   +((x & 0x000F0UL) ?  2 : 0) \
44                   +((x & 0x00F00UL) ?  4 : 0) \
45                   +((x & 0x0F000UL) ?  8 : 0) \
46                   +((x & 0xF0000UL) ? 16 : 0) 
47
48 #define B5(x) ((unsigned char)to_B5__(to_HEX__(x)))
49 /* end concept */
50
51 using namespace std;
52 using namespace boost;
53
54 enum CONDITIONS {
55         NOT_EQUAL = 0,
56         EQUAL = 1,
57         NOT_OVERFLOW =2,
58         OVER_FLOW = 3,
59         NOT_CARRY = 4,
60         CARRY = 5,
61         NOT_SIGNED = 6,
62         SIGNED = 7,
63         ABOVE = 8,
64         BELOW_EQ = 9,
65         GREATER_EQ = 10,
66         LESS = 11,
67         GREATER = 12,
68         LESS_EQ = 13,
69         ALWAYS = 14,
70         NEVER = 15
71 };
72
73 class Iinstr {
74         protected:
75                 short opcode, clockcount;
76                 std::string name;
77                 short m_ra, m_rb, m_rd;
78                 bool m_c, m_d, m_hl, m_f, m_s;
79                 CDat m_imm;
80                 short m_cond;
81                 boost::dynamic_bitset<> argbits;
82                 CDat hexdump;
83                 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) {}
84
85                 CDat generate16ImmFill(const CDat value) const {
86                         CDat i = value;
87                         if(m_hl == true && m_f == true) {
88                                 i <<= 16;
89                                 i |= 0x0000FFFF;
90                         }
91                         else if(m_hl == true && m_f == false) {
92                                 i <<= 16;
93                                 i &= 0xFFFF0000;
94                         }
95                         else if(m_hl == false && m_f == true) {
96                                 i |= 0xFFFF0000;
97                         }
98                         else {
99                                 i &= 0x0000FFFF;
100                         }
101
102                         return i; 
103                 }
104
105                 CDat generate16ImmSign(const CDat value) const {
106                         CDat i = value;
107                         if(m_hl == true) {
108                                 i <<= 16;
109                         }
110                         else if(m_s == true && (i & 0x8000) != 0) {
111                                         i |= 0xFFFF0000;
112                         }
113
114                         return i; 
115                 }
116
117                 CDat generate12ImmSign(const CDat value) const {
118                         CDat i = value;
119                         if(m_s == true && (i & 0x0800) != 0) {
120                                         i |= 0xFFFFF000;
121                         }
122
123                         return i; 
124                 }
125
126                 CDat generate15ImmSign(const CDat value) const {
127                         CDat i = value;
128                         if(m_s == true && (i & 0x4000) != 0) {
129                                         i |= 0xFFFF8000;
130                         }
131
132                         return i; 
133                 }
134
135
136
137                 int getRegister(boost::dynamic_bitset<> bits) {
138                         bits.resize(4);
139                         return bits.to_ulong();
140                 }
141
142                 static CCpu* m_cpu;
143                 static disasm* m_disasm;
144
145         public:
146
147                 static void setCPU(CCpu* cpu) { m_cpu = cpu; }
148                 static void setDisasm(disasm* dasm) { m_disasm = dasm; }
149
150                 virtual ~Iinstr() {}
151                 virtual short getOpcode() { return this->opcode; }
152                 virtual std::string getName() { return this->name; }
153                 virtual void loadBits(boost::dynamic_bitset<> bits) { argbits = bits; this->constructHex(); }
154                 virtual void evalInstr() = 0;
155                 virtual void execInstr() = 0;
156                 virtual std::string toString() = 0;
157                 virtual Iinstr* getNew() = 0;
158
159                 unsigned long toNum() { return this->hexdump; }
160
161                 short getCondition() {
162                         return m_cond;
163                 }
164
165                 short getClockCount() {
166                         return clockcount;
167                 }
168
169                 void decodeCondition(short condition) {
170                         if(condition >= 0 && condition <= 15) {
171                                 m_cond = condition;
172                         }
173                         else {
174                                 throw std::string("Invalid Condition!");
175                         }
176                 }
177
178         protected:
179
180                 void constructHex()
181                 {
182                         hexdump = this->m_cond;
183                         hexdump <<= 5;
184                         hexdump += this->opcode;
185                         hexdump <<= 23;
186                         hexdump += this->argbits.to_ulong();
187                 }
188
189                 std::string getConditionFlag()
190                 {
191                         stringstream cond;
192                         switch(m_cond) {
193                                 case NOT_EQUAL:
194                                         cond << "{nq,nz}";
195                                         break;
196                                 case EQUAL:
197                                         cond << "{eq,zs}";
198                                         break;
199                                 case NOT_OVERFLOW:
200                                         cond << "no";
201                                         break;
202                                 case OVER_FLOW:
203                                         cond << "ov";
204                                         break;
205                                 case NOT_CARRY:
206                                         cond << "{nc,ae}";
207                                         break;
208                                 case CARRY:
209                                         cond << "{cs,bl}";
210                                         break;
211                                 case NOT_SIGNED:
212                                         cond << "{ns,nn}";
213                                         break;
214                                 case SIGNED:
215                                         cond << "{ss,ns}";
216                                         break;
217                                 case ABOVE:
218                                         cond << "ab";
219                                         break;
220                                 case BELOW_EQ:
221                                         cond << "be";
222                                         break;
223                                 case GREATER_EQ:
224                                         cond << "ge";
225                                         break;
226                                 case LESS:
227                                         cond << "lt";
228                                         break;
229                                 case GREATER:
230                                         cond << "gt";
231                                         break;
232                                 case LESS_EQ:
233                                         cond << "le";
234                                         break;
235                                 case ALWAYS:
236                                         cond << "";
237                                         break;
238                                 case NEVER:
239                                         cond << "nv";
240                                         break;
241                                 default:
242                                         cerr << "What did you do? more than 16 values in 5 bits?!" << endl;
243                         }
244
245                         return cond.str();
246                 }
247 };
248
249 #endif