copyleft: gplv3 added and set repo to public
[calu.git] / 3c_disasm / instr / branchreg.cpp
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 #include "../Iinstr.hpp"
23
24 class Cbranchreg : public Iinstr {
25         private:
26                 bool m_taken;
27                 char m_typ;
28         public:
29                 Cbranchreg();
30                 void evalInstr();
31                 void execInstr();
32                 std::string toString();
33                 Iinstr* getNew();
34 };
35
36 /**
37  * Name:      create_instruction
38  * Purpose:   if compiled as shared library, this functions creates the 
39               instruction object
40
41  * Returns:   pointer to instruction object
42  */
43 extern "C" Iinstr* create_instruction() {
44     return new Cbranchreg();
45 }
46
47 Iinstr* Cbranchreg::getNew()
48 {
49         return new Cbranchreg();
50 }
51 /**
52  * Name:      destroy_instruction
53  * Purpose:   if compiled as shared library, this functions destoys the 
54               instruction object
55
56  * Parameter: IInstruction - the instruction object to delete
57  */
58 extern "C" void destroy_instruction(Iinstr* p) {
59     delete p;
60 }
61
62 Cbranchreg::Cbranchreg() : m_taken(1), m_typ(0)
63 {
64         opcode = B5(10111);
65         name = "branchreg";
66 }
67
68 void Cbranchreg::evalInstr()
69 {
70         argbits >>= 2;
71
72         dynamic_bitset<> type = argbits;
73         type.resize(1);
74         this->m_typ = type.to_ulong();
75
76         switch(this->m_typ) {
77                 case 0:
78                         this->name = "brr";
79                         break;
80                 case 1:
81                         this->name = "callr";
82                         break;
83                 default:
84                         cerr << "What have you done? 1 bits that have more than 2 values?!" << endl;
85         }
86
87         argbits >>= 17;
88         m_rd = this->getRegister(argbits);
89 }
90
91 void Cbranchreg::execInstr()
92 {
93         //cout << "should exec " << this->toString() << endl;
94         CDat pc = this->m_cpu->getRegister(this->m_rd);
95         pc *= 4; //komisch fix?
96
97         if(this->m_typ == 1) {
98                 CDat sp = this->m_cpu->getStack();
99                 sp -= 4;
100                 this->m_cpu->setRAM(sp, this->m_cpu->getNextPC());
101                 this->m_cpu->setStack(sp);
102         }
103         this->m_cpu->setNextPC(pc);
104 }
105
106 std::string Cbranchreg::toString()
107 {
108         stringstream op;
109         op << this->getName();
110
111         op << this->getConditionFlag();
112         op << " r" << m_rd;
113         return op.str();
114 }