[2] | 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 |
|
---|
| 9 | using namespace std;
|
---|
| 10 |
|
---|
| 11 | bool IsGlobal(Symbol * sym); // Is the specified symbol a global variable?
|
---|
| 12 |
|
---|
| 13 | MRegisterType 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.
|
---|
| 36 | MRegisterType 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 |
|
---|
| 55 | MRegisterType RegisterManager::tmp_registers[tmp_reg_size] = {
|
---|
| 56 | R_A0,
|
---|
| 57 | R_A1,
|
---|
| 58 | R_A2,
|
---|
| 59 | R_A3
|
---|
| 60 | };
|
---|
| 61 |
|
---|
| 62 | RegisterManager::RegisterManager(StackFrameManager& sfm, AssemblerCode& ac)
|
---|
| 63 | : sfm(sfm), ac(ac), int_symbols(), float_symbols() {
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | MRegisterType RegisterManager::GetRegister(Symbol *symbol) {
|
---|
| 67 | if (symbol->GetReturnType() == RT_REAL) {
|
---|
| 68 | return GetFloatRegister(symbol);
|
---|
| 69 | }
|
---|
| 70 | return GetIntRegister(symbol);
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | MRegisterType 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 |
|
---|
| 90 | MRegisterType 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 |
|
---|
| 107 | void 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 |
|
---|
| 120 | int 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 |
|
---|
| 129 | int 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 |
|
---|
| 138 | int RegisterManager::PickSpillRegister(MRegisterType [], int size) const {
|
---|
| 139 | return rand() % size;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | void RegisterManager::SpillIntRegister(int idx) {
|
---|
| 143 | GenerateIntSpillCode(int_registers[idx], int_symbols[idx]);
|
---|
| 144 | int_symbols[idx] = NULL;
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | void RegisterManager::SpillFloatRegister(int idx) {
|
---|
| 148 | GenerateFloatSpillCode(float_registers[idx], float_symbols[idx]);
|
---|
| 149 | float_symbols[idx] = NULL;
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | void 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 |
|
---|
| 175 | void 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 |
|
---|
| 198 | void 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 |
|
---|
| 221 | void 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 |
|
---|
| 244 | MRegisterType 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 | }
|
---|