405acc0854acaa53e6e7581a828390c4b935b519
[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                         break;
68                 case 3:
69                         this->name = "reti";
70                         break;
71                 default:
72                         cerr << "What have you done? 2 bits that have more than 4 values?!" << endl;
73         }
74
75         argbits >>= 5;
76
77         dynamic_bitset<> immb = argbits;
78         immb.resize(16);
79         this->m_imm = this->generate16ImmSign(immb.to_ulong());
80
81 }
82
83 void Cbranch::execInstr()
84 {
85         //cout << "should exec " << this->toString() << endl;
86         CDat pc = this->m_cpu->getCurPC();
87         switch(this->m_typ) {
88                 case 1:
89                         {
90                         CDat sp = this->m_cpu->getStack();
91                         this->m_cpu->setRAM(sp, pc);
92                         sp -= 4;
93                         this->m_cpu->setStack(sp);
94                         }
95                 case 0:
96                         this->m_cpu->setNextPC(pc+this->m_imm);
97                         break;
98                 case 2:
99                 case 3:
100                         this->m_cpu->setNextPC(this->m_cpu->getRAM(this->m_cpu->getStack()));
101                         this->m_cpu->setStack(this->m_cpu->getStack()+4);
102                         break;
103                 default:
104                         // nothing
105                         this->m_cpu->setNextPC(400);
106         }
107 }
108
109 std::string Cbranch::toString()
110 {
111         stringstream op;
112         op << this->getName();
113
114         if(m_s) op << 'S';
115
116         op << this->getConditionFlag() << (m_taken ? '+' : '-');
117         if(m_typ < 2) {
118                 op << " 0x" << std::hex << m_imm << "(" << std::dec << m_imm << ")";
119         }
120         return op.str();
121 }