Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 // Only build the simulator if not compiling for real MIPS hardware. | 8 // Only build the simulator if not compiling for real MIPS hardware. |
| 9 #if !defined(HOST_ARCH_MIPS) | 9 #if !defined(HOST_ARCH_MIPS) |
| 10 | 10 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 return reinterpret_cast<uword>(stack_) + | 93 return reinterpret_cast<uword>(stack_) + |
| 94 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 94 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
| 95 } | 95 } |
| 96 | 96 |
| 97 | 97 |
| 98 void Simulator::Format(Instr* instr, const char* format) { | 98 void Simulator::Format(Instr* instr, const char* format) { |
| 99 OS::PrintErr("Simulator - unknown instruction: %s\n", format); | 99 OS::PrintErr("Simulator - unknown instruction: %s\n", format); |
| 100 UNIMPLEMENTED(); | 100 UNIMPLEMENTED(); |
| 101 } | 101 } |
| 102 | 102 |
| 103 | |
| 104 bool Simulator::OverflowFrom(int32_t alu_out, | |
| 105 int32_t left, int32_t right, bool addition) { | |
| 106 bool overflow; | |
| 107 if (addition) { | |
| 108 // Operands have the same sign. | |
| 109 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | |
| 110 // And operands and result have different sign. | |
| 111 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 112 } else { | |
| 113 // Operands have different signs. | |
| 114 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | |
| 115 // And first operand and result have different signs. | |
| 116 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 117 } | |
| 118 return overflow; | |
| 119 } | |
| 120 | |
| 121 | |
| 103 void Simulator::DecodeSpecial(Instr* instr) { | 122 void Simulator::DecodeSpecial(Instr* instr) { |
| 104 switch (instr->FunctionField()) { | 123 switch (instr->FunctionField()) { |
| 124 case ADDU: { | |
| 125 ASSERT(instr->SaField() == 0); | |
| 126 // Format(instr, "addu 'rd, 'rs, 'rt"); | |
| 127 int32_t rs_val = get_register(instr->RsField()); | |
| 128 int32_t rt_val = get_register(instr->RtField()); | |
| 129 set_register(instr->RdField(), rs_val + rt_val); | |
| 130 break; | |
| 131 } | |
| 132 case AND: { | |
| 133 ASSERT(instr->SaField() == 0); | |
| 134 // Format(instr, "and 'rd, 'rs, 'rt"); | |
| 135 int32_t rs_val = get_register(instr->RsField()); | |
| 136 int32_t rt_val = get_register(instr->RtField()); | |
| 137 set_register(instr->RdField(), rs_val & rt_val); | |
| 138 break; | |
| 139 } | |
| 140 case DIV: { | |
| 141 ASSERT(instr->RdField() == 0); | |
| 142 ASSERT(instr->SaField() == 0); | |
| 143 // Format(instr, "div 'rs, 'rt"); | |
| 144 int32_t rs_val = get_register(instr->RsField()); | |
| 145 int32_t rt_val = get_register(instr->RtField()); | |
| 146 if (rt_val == 0) { | |
| 147 // Results are unpredictable. | |
| 148 set_hi_register(0); | |
| 149 set_lo_register(0); | |
| 150 // TODO(zra): Drop into the debugger here. | |
| 151 break; | |
| 152 } | |
| 153 | |
| 154 if ((rs_val == static_cast<int32_t>(0x80000000)) && | |
| 155 (rt_val == static_cast<int32_t>(0xffffffff))) { | |
| 156 set_lo_register(0x80000000); | |
| 157 set_hi_register(0); | |
| 158 } else { | |
| 159 set_lo_register(rs_val / rt_val); | |
| 160 set_hi_register(rs_val % rt_val); | |
| 161 } | |
| 162 break; | |
| 163 } | |
| 164 case DIVU: { | |
| 165 ASSERT(instr->RdField() == 0); | |
| 166 ASSERT(instr->SaField() == 0); | |
| 167 // Format(instr, "divu 'rs, 'rt"); | |
| 168 uint32_t rs_val = get_register(instr->RsField()); | |
| 169 uint32_t rt_val = get_register(instr->RtField()); | |
| 170 if (rt_val == 0) { | |
| 171 // Results are unpredictable. | |
| 172 set_hi_register(0); | |
| 173 set_lo_register(0); | |
| 174 // TODO(zra): Drop into the debugger here. | |
| 175 break; | |
| 176 } | |
| 177 | |
| 178 set_lo_register(rs_val / rt_val); | |
| 179 set_hi_register(rs_val % rt_val); | |
| 180 break; | |
| 181 } | |
| 182 case MFHI: { | |
| 183 ASSERT(instr->RsField() == 0); | |
| 184 ASSERT(instr->RtField() == 0); | |
| 185 ASSERT(instr->SaField() == 0); | |
| 186 // Format(instr, "mfhi 'rd"); | |
| 187 set_register(instr->RdField(), get_hi_register()); | |
| 188 break; | |
| 189 } | |
| 190 case MFLO: { | |
| 191 ASSERT(instr->RsField() == 0); | |
| 192 ASSERT(instr->RtField() == 0); | |
| 193 ASSERT(instr->SaField() == 0); | |
| 194 // Format(instr, "mflo 'rd"); | |
| 195 set_register(instr->RdField(), get_lo_register()); | |
| 196 break; | |
| 197 } | |
| 105 case SLL: { | 198 case SLL: { |
| 199 ASSERT(instr->RsField() == 0); | |
| 106 if ((instr->RdField() == R0) && | 200 if ((instr->RdField() == R0) && |
| 107 (instr->RtField() == R0) && | 201 (instr->RtField() == R0) && |
| 108 (instr->SaField() == 0)) { | 202 (instr->SaField() == 0)) { |
| 109 // Format(instr, "nop"); | 203 // Format(instr, "nop"); |
| 110 // Nothing to be done for NOP. | 204 // Nothing to be done for NOP. |
| 111 } else { | 205 } else { |
| 112 Format(instr, "sll 'rd, 'rt, 'sa"); | 206 int32_t rt_val = get_register(instr->RtField()); |
| 207 int sa = instr->SaField(); | |
| 208 set_register(instr->RdField(), rt_val << sa); | |
| 113 } | 209 } |
| 114 break; | 210 break; |
| 115 } | 211 } |
| 116 case JR: { | 212 case JR: { |
| 117 ASSERT(instr->RtField() == R0); | 213 ASSERT(instr->RtField() == R0); |
| 118 ASSERT(instr->RdField() == R0); | 214 ASSERT(instr->RdField() == R0); |
| 119 ASSERT(!delay_slot_); | 215 ASSERT(!delay_slot_); |
| 120 // Format(instr, "jr'hint 'rs"); | 216 // Format(instr, "jr'hint 'rs"); |
| 121 uword next_pc = get_register(instr->RsField()); | 217 uword next_pc = get_register(instr->RsField()); |
| 122 ExecuteDelaySlot(); | 218 ExecuteDelaySlot(); |
| 123 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. | 219 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. |
| 124 break; | 220 break; |
| 125 } | 221 } |
| 126 default: { | 222 default: { |
| 127 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); | 223 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); |
| 128 UNREACHABLE(); | 224 UNREACHABLE(); |
| 129 break; | 225 break; |
| 130 } | 226 } |
| 131 } | 227 } |
| 132 } | 228 } |
| 133 | 229 |
| 134 | 230 |
| 231 void Simulator::DecodeSpecial2(Instr* instr) { | |
| 232 switch (instr->FunctionField()) { | |
| 233 case CLO: { | |
| 234 ASSERT(instr->SaField() == 0); | |
| 235 ASSERT(instr->RtField() == instr->RdField()); | |
| 236 // Format(instr, "clo 'rd, 'rs"); | |
| 237 int32_t rs_val = get_register(instr->RsField()); | |
| 238 int32_t bitcount = 0; | |
| 239 while (rs_val < 0) { | |
| 240 bitcount++; | |
| 241 rs_val <<= 1; | |
| 242 } | |
| 243 set_register(instr->RdField(), bitcount); | |
| 244 break; | |
| 245 } | |
| 246 case CLZ: { | |
| 247 ASSERT(instr->SaField() == 0); | |
| 248 ASSERT(instr->RtField() == instr->RdField()); | |
| 249 // Format(instr, "clz 'rd, 'rs"); | |
| 250 int32_t rs_val = get_register(instr->RsField()); | |
| 251 int32_t bitcount = 0; | |
| 252 if (rs_val != 0) { | |
| 253 while (rs_val > 0) { | |
| 254 bitcount++; | |
| 255 rs_val <<= 1; | |
| 256 } | |
| 257 } else { | |
| 258 bitcount = 32; | |
| 259 } | |
| 260 set_register(instr->RdField(), bitcount); | |
| 261 break; | |
| 262 } | |
| 263 default: { | |
| 264 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); | |
| 265 UNREACHABLE(); | |
| 266 break; | |
| 267 } | |
| 268 } | |
| 269 } | |
| 270 | |
| 271 | |
| 135 void Simulator::InstructionDecode(Instr* instr) { | 272 void Simulator::InstructionDecode(Instr* instr) { |
| 136 switch (instr->OpcodeField()) { | 273 switch (instr->OpcodeField()) { |
| 137 case SPECIAL: { | 274 case SPECIAL: { |
| 138 DecodeSpecial(instr); | 275 DecodeSpecial(instr); |
| 139 break; | 276 break; |
| 140 } | 277 } |
| 278 case SPECIAL2: { | |
| 279 DecodeSpecial2(instr); | |
| 280 break; | |
| 281 } | |
| 282 case ADDI: { | |
| 283 // Format(instr, "addi 'rt, 'rs, 'immu"); | |
| 284 int32_t rs_val = get_register(instr->RsField()); | |
| 285 int32_t imm_val = instr->SImmField(); | |
| 286 int32_t res = rs_val + imm_val; | |
| 287 // Rt is not set on overflow. | |
| 288 if (!OverflowFrom(res, rs_val, imm_val, true)) { | |
| 289 set_register(instr->RtField(), res); | |
|
Ivan Posva
2013/03/11 06:03:27
Shouldn't this also dispatch to a trap handler?
zra
2013/03/11 15:46:03
Yes. I've added a TODO for myself that I'll fill i
| |
| 290 } | |
| 291 break; | |
| 292 } | |
| 293 case ADDIU: { | |
| 294 // Format(instr, "addiu 'rt, 'rs, 'immu"); | |
| 295 int32_t rs_val = get_register(instr->RsField()); | |
| 296 int32_t imm_val = instr->SImmField(); | |
| 297 int32_t res = rs_val + imm_val; | |
| 298 // Rt is set even on overflow. | |
| 299 set_register(instr->RtField(), res); | |
| 300 break; | |
| 301 } | |
| 302 case ANDI: { | |
| 303 // Format(instr, "andi 'rt, 'rs, 'immu"); | |
| 304 int32_t rs_val = get_register(instr->RsField()); | |
| 305 set_register(instr->RtField(), rs_val & instr->UImmField()); | |
| 306 break; | |
| 307 } | |
| 308 case LUI: { | |
| 309 ASSERT(instr->RsField() == 0); | |
| 310 set_register(instr->RtField(), instr->UImmField() << 16); | |
| 311 break; | |
| 312 } | |
| 141 case ORI: { | 313 case ORI: { |
| 142 // Format(instr, "ori 'rt, 'rs, 'immu"); | 314 // Format(instr, "ori 'rt, 'rs, 'immu"); |
| 143 int32_t rs_val = get_register(instr->RsField()); | 315 int32_t rs_val = get_register(instr->RsField()); |
| 144 set_register(instr->RtField(), rs_val | instr->UImmField()); | 316 set_register(instr->RtField(), rs_val | instr->UImmField()); |
| 145 break; | 317 break; |
| 146 } | 318 } |
| 147 default: { | 319 default: { |
| 148 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); | 320 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); |
| 149 UNREACHABLE(); | 321 UNREACHABLE(); |
| 150 break; | 322 break; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 // Restore the SP register and return R1:R0. | 443 // Restore the SP register and return R1:R0. |
| 272 set_register(SP, sp_before_call); | 444 set_register(SP, sp_before_call); |
| 273 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 445 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
| 274 } | 446 } |
| 275 | 447 |
| 276 } // namespace dart | 448 } // namespace dart |
| 277 | 449 |
| 278 #endif // !defined(HOST_ARCH_MIPS) | 450 #endif // !defined(HOST_ARCH_MIPS) |
| 279 | 451 |
| 280 #endif // defined TARGET_ARCH_MIPS | 452 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |