f1f9138cbfffb875d1f02aa9cb1d5db45342b8e5
[calu.git] / 3c_disasm / instr / branch.cpp
1 #include "../Iinstr.hpp"
2
3 class Cbranch : public Iinstr {
4         private:
5                 bool m_taken;
6                 char m_typ;
7         public:
8                 Cbranch();
9                 void evalInstr();
10                 void execInstr();
11                 std::string toString();
12                 Iinstr* getNew();
13 };
14
15 /**
16  * Name:      create_instruction
17  * Purpose:   if compiled as shared library, this functions creates the 
18               instruction object
19
20  * Returns:   pointer to instruction object
21  */
22 extern "C" Iinstr* create_instruction() {
23     return new Cbranch();
24 }
25
26 Iinstr* Cbranch::getNew()
27 {
28         return new Cbranch();
29 }
30 /**
31  * Name:      destroy_instruction
32  * Purpose:   if compiled as shared library, this functions destoys the 
33               instruction object
34
35  * Parameter: IInstruction - the instruction object to delete
36  */
37 extern "C" void destroy_instruction(Iinstr* p) {
38     delete p;
39 }
40
41 Cbranch::Cbranch() : m_taken(1), m_typ(0)
42 {
43         opcode = B5(10110);
44         name = "branch";
45 }
46
47 void Cbranch::evalInstr()
48 {
49         this->m_s = argbits[0];
50         this->m_taken = argbits[1];
51
52         argbits >>= 2;
53
54         dynamic_bitset<> type = argbits;
55         type.resize(2);
56         this->m_typ = type.to_ulong();
57
58         switch(this->m_typ) {
59                 case 0:
60                         this->name = "br";
61                         break;
62                 case 1:
63                         this->name = "call";
64                         break;
65                 case 2:
66                         this->name = "ret";
67                         this->clockcount = 3;
68                         break;
69                 case 3:
70                         this->name = "reti";
71                         this->clockcount = 3;
72                         break;
73                 default:
74                         cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
75         }
76
77         argbits >>= 5;
78
79         dynamic_bitset<> immb = argbits;
80         immb.resize(16);
81         this->m_imm = this->generate16ImmSign(immb.to_ulong())*4;
82
83 }
84
85 void Cbranch::execInstr()
86 {
87         //cout << "should exec " << this->toString() << endl;
88         CDat pc = this->m_cpu->getCurPC();
89         switch(this->m_typ) {
90                 case 1:
91                         {
92                         CDat sp = this->m_cpu->getStack();
93                         sp -= 4;
94                         this->m_cpu->setRAM(sp, this->m_cpu->getNextPC());
95                         this->m_cpu->setStack(sp);
96                         }
97                         /* fall through */
98                 case 0:
99                         this->m_cpu->setNextPC(pc+(this->m_imm));
100                         break;
101                 case 2:
102                 case 3:
103                         this->m_cpu->setNextPC(this->m_cpu->getRAM(this->m_cpu->getStack()));
104                         this->m_cpu->setStack(this->m_cpu->getStack()+4);
105                         break;
106                 default:
107                         // nothing
108                         this->m_cpu->setNextPC(400);
109         }
110 }
111
112 std::string Cbranch::toString()
113 {
114         stringstream op;
115         op << this->getName();
116
117         if(m_s) op << 'S';
118
119         op << this->getConditionFlag() << (m_taken ? '+' : '-');
120         if(m_typ < 2) {
121                 op << " 0x" << std::hex << m_imm << "(" << std::dec << m_imm << ", " << (int) m_imm << ")";
122         }
123         return op.str();
124 }