e5a5245b1fb721336ce13fb23559493929a070cb
[calu.git] / 3c_disasm / instr / shift.cpp
1 #include "../Iinstr.hpp"
2
3 class Cshift : public Iinstr {
4                 char m_typ;
5         public:
6                 Cshift();
7                 void evalInstr();
8                 void execInstr();
9                 std::string toString();
10                 Iinstr* getNew();
11 };
12
13 /**
14  * Name:      create_instruction
15  * Purpose:   if compiled as shared library, this functions creates the 
16               instruction object
17
18  * Returns:   pointer to instruction object
19  */
20 extern "C" Iinstr* create_instruction() {
21     return new Cshift();
22 }
23
24 Iinstr* Cshift::getNew()
25 {
26         return new Cshift();
27 }
28 /**
29  * Name:      destroy_instruction
30  * Purpose:   if compiled as shared library, this functions destoys the 
31               instruction object
32
33  * Parameter: IInstruction - the instruction object to delete
34  */
35 extern "C" void destroy_instruction(Iinstr* p) {
36     delete p;
37 }
38
39 Cshift::Cshift() : m_typ(0)
40 {
41         opcode = B5(01010);
42         name = "shift";
43 }
44
45 void Cshift::evalInstr()
46 {
47         this->m_d = argbits[0];
48         this->m_c = argbits[1];
49         argbits >>= 2;
50
51         dynamic_bitset<> type = argbits;
52         type.resize(2);
53         this->m_typ = type.to_ulong();
54
55         switch(this->m_typ) {
56                 case 1:
57                         cerr << "INVALID shift type, using logic left shift!" << endl;
58                         this->m_typ = 0;
59                 case 0:
60                         this->name = "lls";
61                         break;
62                 case 2:
63                         this->name = "lrs";
64                         break;
65                 case 3:
66                         this->name = "ars";
67                         break;
68                 default:
69                         cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
70         }
71
72         argbits >>= 8;
73         dynamic_bitset<> immb = argbits;
74         immb.resize(5);
75         this->m_imm = immb.to_ulong();
76         argbits >>= 5;
77         m_ra = this->getRegister(argbits);
78         argbits >>= 4;
79         m_rd = this->getRegister(argbits);
80 }
81
82 void Cshift::execInstr()
83 {
84         CDatd val = this->m_cpu->getRegister(m_ra);
85         switch(this->m_typ) {
86                 case 0:
87                 case 1:
88 //                      this->name = "lls";
89                         for(unsigned int i = 0; i < m_imm; i++) {
90                                 val = val << 1;
91                         }
92                         //carry
93                         if(m_c) {
94                                 this->m_cpu->updateCarry(((val >> BIT_LEN) & 0x1) != 0);
95                         }
96                         break;
97                 case 2:
98 //                      this->name = "lrs";
99                         {
100                                 bool carry = this->m_cpu->getCarry();
101                                 for(unsigned int i = 0; i < m_imm; i++) {
102                                         val = val >> 1;
103
104                                         //carry!
105                                         //if user wants carry, and carry is set
106                                         if(this->m_c && carry) {
107                                                 //set highest bit 1
108                                                 val |= (CDat)(1<<(BIT_LEN-1));
109                                         }
110                                         else {
111                                                 //set highest bit 0
112                                                 val &= (~(1<<(BIT_LEN-1)));
113                                         }
114                                 }
115                         }
116                         break;
117                 case 3:
118 //                      this->name = "ars";
119                         //>> is a ars, but val is CDatd => we have to set the MSB manually
120                         {
121                                 bool msb = (val & (1<<(BIT_LEN-1)) >> (BIT_LEN-1));
122                                 for(unsigned int i = 0; i < m_imm; i++) {
123                                         val = val >> 1;
124                                         if(msb) {
125                                                 //set highest bit 1
126                                                 val |= (CDat)(1<<(BIT_LEN-1));
127                                         }
128                                         else {
129                                         //set highest bit 0
130                                         val &= (~(1<<(BIT_LEN-1)));
131                                         }
132                                 }
133                         }
134                         break;
135                 default:
136                         cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
137         }
138         this->m_cpu->setRegister(m_rd, val);
139 }
140
141 std::string Cshift::toString()
142 {
143         stringstream op;
144         op << this->getName();
145         if(m_c) op << "C";
146         if(m_d) op << "D";
147
148         op << this->getConditionFlag();
149         op << " r" << m_rd << ", r" << m_ra << ", " << m_imm;
150         return op.str();
151 }