source: liacs/coco/assignment4/RegisterManager.cc@ 62

Last change on this file since 62 was 2, checked in by Rick van der Zwet, 15 years ago

Initial import of data of old repository ('data') worth keeping (e.g. tracking
means of URL access statistics)

File size: 6.4 KB
Line 
1#include "RegisterManager.h"
2
3#include "Symbol.h"
4#include "StackFrameManager.h"
5#include "types.h"
6#include "debug.h"
7#include <cassert>
8
9using namespace std;
10
11bool IsGlobal(Symbol * sym); // Is the specified symbol a global variable?
12
13MRegisterType RegisterManager::int_registers[int_reg_size] = {
14 R_T0,
15 R_T1,
16 R_T2,
17 R_T3,
18 R_T4,
19 R_T5,
20 R_T6,
21 R_T7,
22 R_S0,
23 R_S1,
24 R_S2,
25 R_S3,
26 R_S4,
27 R_S5,
28 R_S6,
29 R_S7,
30 R_T8,
31 R_T9
32};
33
34// According to the spim documentation all floating point operations use only
35// even registers, as doubles require two. Even for operations on singles.
36MRegisterType RegisterManager::float_registers[float_reg_size] = {
37// R_FO, /* Claimed for temporary use within code */
38 R_F2,
39 R_F4,
40 R_F6,
41 R_F8,
42 R_F10,
43 R_F12,
44 R_F14,
45 R_F16,
46 R_F18,
47 R_F20,
48 R_F22,
49 R_F24,
50 R_F26,
51 R_F28,
52 R_F30
53};
54
55MRegisterType RegisterManager::tmp_registers[tmp_reg_size] = {
56 R_A0,
57 R_A1,
58 R_A2,
59 R_A3
60};
61
62RegisterManager::RegisterManager(StackFrameManager& sfm, AssemblerCode& ac)
63: sfm(sfm), ac(ac), int_symbols(), float_symbols() {
64}
65
66MRegisterType RegisterManager::GetRegister(Symbol *symbol) {
67 if (symbol->GetReturnType() == RT_REAL) {
68 return GetFloatRegister(symbol);
69 }
70 return GetIntRegister(symbol);
71}
72
73MRegisterType RegisterManager::GetIntRegister(Symbol *symbol) {
74 int idx = FindSymbol(int_symbols, int_reg_size, symbol);
75 if (idx != -1) {
76 return int_registers[idx];
77 }
78 // symbol not yet used
79 idx = FindUnused(int_symbols, int_reg_size);
80 if (idx == -1) {
81 // no more unused registers
82 idx = PickSpillRegister(int_registers, int_reg_size);
83 SpillIntRegister(idx);
84 }
85 GenerateIntLoadCode(int_registers[idx], symbol);
86 int_symbols[idx] = symbol;
87 return int_registers[idx];
88}
89
90MRegisterType RegisterManager::GetFloatRegister(Symbol *symbol) {
91 int idx = FindSymbol(float_symbols, float_reg_size, symbol);
92 if (idx != -1) {
93 return float_registers[idx];
94 }
95 // symbol not yet used
96 idx = FindUnused(float_symbols, float_reg_size);
97 if (idx == -1) {
98 // no more unused registers
99 idx = PickSpillRegister(float_registers, float_reg_size);
100 SpillFloatRegister(idx);
101 }
102 GenerateFloatLoadCode(float_registers[idx], symbol);
103 float_symbols[idx] = symbol;
104 return float_registers[idx];
105}
106
107void RegisterManager::SpillAll() {
108 for (int i = 0; i < int_reg_size; ++i) {
109 if (int_symbols[i] != NULL) {
110 SpillIntRegister(i);
111 }
112 }
113 for (int i = 0; i < float_reg_size; ++i) {
114 if (float_symbols[i] != NULL) {
115 SpillFloatRegister(i);
116 }
117 }
118}
119
120int RegisterManager::FindSymbol(Symbol *symbols[], int size, Symbol *symbol) const {
121 for (int i = 0; i < size; ++i) {
122 if (symbols[i] != NULL && symbols[i]->GetName() == symbol->GetName()) {
123 return i;
124 }
125 }
126 return -1;
127}
128
129int RegisterManager::FindUnused(Symbol *symbols[], int size) const {
130 for (int i = 0; i < size; ++i) {
131 if (symbols[i] == NULL) {
132 return i;
133 }
134 }
135 return -1;
136}
137
138int RegisterManager::PickSpillRegister(MRegisterType [], int size) const {
139 return rand() % size;
140}
141
142void RegisterManager::SpillIntRegister(int idx) {
143 GenerateIntSpillCode(int_registers[idx], int_symbols[idx]);
144 int_symbols[idx] = NULL;
145}
146
147void RegisterManager::SpillFloatRegister(int idx) {
148 GenerateFloatSpillCode(float_registers[idx], float_symbols[idx]);
149 float_symbols[idx] = NULL;
150}
151
152void RegisterManager::GenerateIntSpillCode(MRegisterType reg, Symbol *symbol) {
153 if (IsGlobal(symbol)) {
154 string name = SYMBOL_PREFIX;
155 name += symbol->GetName();
156 MOperator instr;
157 MOperand *mop1, *mop2;
158
159 instr = MOP_SW;
160 mop1 = new MOperand(MT_REGISTER, reg);
161 mop2 = new MOperand(MT_LABEL, name);
162 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Write back integer register"));
163 } else {
164 int offset = symbol->GetOffset();
165 MOperator instr;
166 MOperand *mop1, *mop2;
167
168 instr = MOP_SW;
169 mop1 = new MOperand(MT_REGISTER, reg);
170 mop2 = new MOperand(MT_OFFSET, R_FP, offset);
171 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Write back integer register"));
172 }
173}
174
175void RegisterManager::GenerateFloatSpillCode(MRegisterType reg, Symbol *symbol) {
176 if (IsGlobal(symbol)) {
177 string name = SYMBOL_PREFIX;
178 name += symbol->GetName();
179 MOperator instr;
180 MOperand *mop1, *mop2;
181
182 instr = MOP_S_S;
183 mop1 = new MOperand(MT_REGISTER, reg);
184 mop2 = new MOperand(MT_LABEL, name);
185 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Write back float register"));
186 } else {
187 int offset = symbol->GetOffset();
188 MOperator instr;
189 MOperand *mop1, *mop2;
190
191 instr = MOP_S_S;
192 mop1 = new MOperand(MT_REGISTER, reg);
193 mop2 = new MOperand(MT_OFFSET, R_FP, offset);
194 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Write back float register"));
195 }
196}
197
198void RegisterManager::GenerateIntLoadCode(MRegisterType reg, Symbol *symbol) {
199 if (IsGlobal(symbol)) {
200 string name = SYMBOL_PREFIX;
201 name += symbol->GetName();
202 MOperator instr;
203 MOperand *mop1, *mop2;
204
205 instr = MOP_LW;
206 mop1 = new MOperand(MT_REGISTER, reg);
207 mop2 = new MOperand(MT_LABEL, name);
208 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Load integer Register"));
209 } else {
210 int offset = symbol->GetOffset();
211 MOperator instr;
212 MOperand *mop1, *mop2;
213
214 instr = MOP_LW;
215 mop1 = new MOperand(MT_REGISTER, reg);
216 mop2 = new MOperand(MT_OFFSET, R_FP, offset);
217 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Load integer Register"));
218 }
219}
220
221void RegisterManager::GenerateFloatLoadCode(MRegisterType reg, Symbol *symbol) {
222 if (IsGlobal(symbol)) {
223 string name = SYMBOL_PREFIX;
224 name += symbol->GetName();
225 MOperator instr;
226 MOperand *mop1, *mop2;
227
228 instr = MOP_L_S;
229 mop1 = new MOperand(MT_REGISTER, reg);
230 mop2 = new MOperand(MT_LABEL, name);
231 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Load float Register"));
232 } else {
233 int offset = symbol->GetOffset();
234 MOperator instr;
235 MOperand *mop1, *mop2;
236
237 instr = MOP_L_S;
238 mop1 = new MOperand(MT_REGISTER, reg);
239 mop2 = new MOperand(MT_OFFSET, R_FP, offset);
240 ac.AppendStatement(new MStatement(instr, mop1, mop2, "Load float Register"));
241 }
242}
243
244MRegisterType RegisterManager::GetTempRegister(){
245 /* Ping pong between two active registers as temporary storage */
246 static int currentRegister = -1;
247 currentRegister = (currentRegister == 4) ? 0 : currentRegister+1;
248 pmesg(100, "DEBUG: %i\n", currentRegister);
249 return(tmp_registers[currentRegister]);
250}
Note: See TracBrowser for help on using the repository browser.