| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 | 103 |
| 104 int8_t Simulator::ReadB(uword addr) { |
| 105 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
| 106 return *ptr; |
| 107 } |
| 108 |
| 109 |
| 110 uint8_t Simulator::ReadBU(uword addr) { |
| 111 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 112 return *ptr; |
| 113 } |
| 114 |
| 115 |
| 116 int16_t Simulator::ReadH(uword addr, Instr* instr) { |
| 117 if ((addr & 1) == 0) { |
| 118 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 119 return *ptr; |
| 120 } |
| 121 // TODO(zra) unaligned access. Trap into debugger. |
| 122 UNIMPLEMENTED(); |
| 123 return 0; |
| 124 } |
| 125 |
| 126 |
| 127 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { |
| 128 if ((addr & 1) == 0) { |
| 129 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 130 return *ptr; |
| 131 } |
| 132 // TODO(zra) unaligned access. Trap into debugger. |
| 133 UNIMPLEMENTED(); |
| 134 return 0; |
| 135 } |
| 136 |
| 137 |
| 138 int Simulator::ReadW(uword addr, Instr* instr) { |
| 139 if ((addr & 3) == 0) { |
| 140 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 141 return *ptr; |
| 142 } |
| 143 // TODO(zra) unaligned access. Trap into debugger. |
| 144 UNIMPLEMENTED(); |
| 145 return 0; |
| 146 } |
| 147 |
| 148 |
| 149 void Simulator::WriteB(uword addr, uint8_t value) { |
| 150 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 151 *ptr = value; |
| 152 } |
| 153 |
| 154 |
| 155 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { |
| 156 if ((addr & 1) == 0) { |
| 157 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 158 *ptr = value; |
| 159 return; |
| 160 } |
| 161 // TODO(zra) unaligned access. Trap into debugger. |
| 162 UNIMPLEMENTED(); |
| 163 } |
| 164 |
| 165 |
| 166 void Simulator::WriteW(uword addr, int value, Instr* instr) { |
| 167 if ((addr & 3) == 0) { |
| 168 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 169 *ptr = value; |
| 170 return; |
| 171 } |
| 172 // TODO(zra) unaligned access. Trap into debugger. |
| 173 UNIMPLEMENTED(); |
| 174 } |
| 175 |
| 176 |
| 104 bool Simulator::OverflowFrom(int32_t alu_out, | 177 bool Simulator::OverflowFrom(int32_t alu_out, |
| 105 int32_t left, int32_t right, bool addition) { | 178 int32_t left, int32_t right, bool addition) { |
| 106 bool overflow; | 179 bool overflow; |
| 107 if (addition) { | 180 if (addition) { |
| 108 // Operands have the same sign. | 181 // Operands have the same sign. |
| 109 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | 182 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) |
| 110 // And operands and result have different sign. | 183 // And operands and result have different sign. |
| 111 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | 184 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
| 112 } else { | 185 } else { |
| 113 // Operands have different signs. | 186 // Operands have different signs. |
| 114 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | 187 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) |
| 115 // And first operand and result have different signs. | 188 // And first operand and result have different signs. |
| 116 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | 189 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
| 117 } | 190 } |
| 118 return overflow; | 191 return overflow; |
| 119 } | 192 } |
| 120 | 193 |
| 121 | 194 |
| 122 void Simulator::DecodeSpecial(Instr* instr) { | 195 void Simulator::DecodeSpecial(Instr* instr) { |
| 196 ASSERT(instr->OpcodeField() == SPECIAL); |
| 123 switch (instr->FunctionField()) { | 197 switch (instr->FunctionField()) { |
| 124 case ADDU: { | 198 case ADDU: { |
| 125 ASSERT(instr->SaField() == 0); | 199 ASSERT(instr->SaField() == 0); |
| 126 // Format(instr, "addu 'rd, 'rs, 'rt"); | 200 // Format(instr, "addu 'rd, 'rs, 'rt"); |
| 127 int32_t rs_val = get_register(instr->RsField()); | 201 int32_t rs_val = get_register(instr->RsField()); |
| 128 int32_t rt_val = get_register(instr->RtField()); | 202 int32_t rt_val = get_register(instr->RtField()); |
| 129 set_register(instr->RdField(), rs_val + rt_val); | 203 set_register(instr->RdField(), rs_val + rt_val); |
| 130 break; | 204 break; |
| 131 } | 205 } |
| 132 case AND: { | 206 case AND: { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 default: { | 296 default: { |
| 223 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); | 297 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); |
| 224 UNREACHABLE(); | 298 UNREACHABLE(); |
| 225 break; | 299 break; |
| 226 } | 300 } |
| 227 } | 301 } |
| 228 } | 302 } |
| 229 | 303 |
| 230 | 304 |
| 231 void Simulator::DecodeSpecial2(Instr* instr) { | 305 void Simulator::DecodeSpecial2(Instr* instr) { |
| 306 ASSERT(instr->OpcodeField() == SPECIAL2); |
| 232 switch (instr->FunctionField()) { | 307 switch (instr->FunctionField()) { |
| 233 case CLO: { | 308 case CLO: { |
| 234 ASSERT(instr->SaField() == 0); | 309 ASSERT(instr->SaField() == 0); |
| 235 ASSERT(instr->RtField() == instr->RdField()); | 310 ASSERT(instr->RtField() == instr->RdField()); |
| 236 // Format(instr, "clo 'rd, 'rs"); | 311 // Format(instr, "clo 'rd, 'rs"); |
| 237 int32_t rs_val = get_register(instr->RsField()); | 312 int32_t rs_val = get_register(instr->RsField()); |
| 238 int32_t bitcount = 0; | 313 int32_t bitcount = 0; |
| 239 while (rs_val < 0) { | 314 while (rs_val < 0) { |
| 240 bitcount++; | 315 bitcount++; |
| 241 rs_val <<= 1; | 316 rs_val <<= 1; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 262 } | 337 } |
| 263 default: { | 338 default: { |
| 264 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); | 339 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); |
| 265 UNREACHABLE(); | 340 UNREACHABLE(); |
| 266 break; | 341 break; |
| 267 } | 342 } |
| 268 } | 343 } |
| 269 } | 344 } |
| 270 | 345 |
| 271 | 346 |
| 347 void Simulator::DecodeSpecial3(Instr* instr) { |
| 348 ASSERT(instr->OpcodeField() == SPECIAL3); |
| 349 switch (instr->FunctionField()) { |
| 350 default: { |
| 351 OS::PrintErr("DecodeSpecial3: 0x%x\n", instr->InstructionBits()); |
| 352 UNREACHABLE(); |
| 353 break; |
| 354 } |
| 355 } |
| 356 } |
| 357 |
| 358 |
| 272 void Simulator::InstructionDecode(Instr* instr) { | 359 void Simulator::InstructionDecode(Instr* instr) { |
| 273 switch (instr->OpcodeField()) { | 360 switch (instr->OpcodeField()) { |
| 274 case SPECIAL: { | 361 case SPECIAL: { |
| 275 DecodeSpecial(instr); | 362 DecodeSpecial(instr); |
| 276 break; | 363 break; |
| 277 } | 364 } |
| 278 case SPECIAL2: { | 365 case SPECIAL2: { |
| 279 DecodeSpecial2(instr); | 366 DecodeSpecial2(instr); |
| 280 break; | 367 break; |
| 281 } | 368 } |
| 282 case ADDI: { | 369 case SPECIAL3: { |
| 283 // Format(instr, "addi 'rt, 'rs, 'immu"); | 370 DecodeSpecial3(instr); |
| 371 break; |
| 372 } |
| 373 case ADDIU: { |
| 374 // Format(instr, "addiu 'rt, 'rs, 'imms"); |
| 284 int32_t rs_val = get_register(instr->RsField()); | 375 int32_t rs_val = get_register(instr->RsField()); |
| 285 int32_t imm_val = instr->SImmField(); | 376 int32_t imm_val = instr->SImmField(); |
| 286 int32_t res = rs_val + imm_val; | 377 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); | |
| 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. | 378 // Rt is set even on overflow. |
| 299 set_register(instr->RtField(), res); | 379 set_register(instr->RtField(), res); |
| 300 break; | 380 break; |
| 301 } | 381 } |
| 302 case ANDI: { | 382 case ANDI: { |
| 303 // Format(instr, "andi 'rt, 'rs, 'immu"); | 383 // Format(instr, "andi 'rt, 'rs, 'immu"); |
| 304 int32_t rs_val = get_register(instr->RsField()); | 384 int32_t rs_val = get_register(instr->RsField()); |
| 305 set_register(instr->RtField(), rs_val & instr->UImmField()); | 385 set_register(instr->RtField(), rs_val & instr->UImmField()); |
| 306 break; | 386 break; |
| 307 } | 387 } |
| 388 case LB: { |
| 389 // Format(instr, "lb 'rt, 'imms('rs)"); |
| 390 int32_t base_val = get_register(instr->RsField()); |
| 391 int32_t imm_val = instr->SImmField(); |
| 392 uword addr = base_val + imm_val; |
| 393 if (Simulator::IsIllegalAddress(addr)) { |
| 394 // TODO(zra) trap into debugger. |
| 395 UNIMPLEMENTED(); |
| 396 } else { |
| 397 int32_t res = ReadB(addr); |
| 398 set_register(instr->RtField(), res); |
| 399 } |
| 400 break; |
| 401 } |
| 402 case LBU: { |
| 403 // Format(instr, "lbu 'rt, 'imms('rs)"); |
| 404 int32_t base_val = get_register(instr->RsField()); |
| 405 int32_t imm_val = instr->SImmField(); |
| 406 uword addr = base_val + imm_val; |
| 407 if (Simulator::IsIllegalAddress(addr)) { |
| 408 // TODO(zra) trap into debugger. |
| 409 UNIMPLEMENTED(); |
| 410 } else { |
| 411 int32_t res = ReadBU(addr); |
| 412 set_register(instr->RtField(), res); |
| 413 } |
| 414 break; |
| 415 } |
| 416 case LH: { |
| 417 // Format(instr, "lh 'rt, 'imms('rs)"); |
| 418 int32_t base_val = get_register(instr->RsField()); |
| 419 int32_t imm_val = instr->SImmField(); |
| 420 uword addr = base_val + imm_val; |
| 421 if (Simulator::IsIllegalAddress(addr)) { |
| 422 // TODO(zra) trap into debugger. |
| 423 UNIMPLEMENTED(); |
| 424 } else { |
| 425 int32_t res = ReadH(addr, instr); |
| 426 set_register(instr->RtField(), res); |
| 427 } |
| 428 break; |
| 429 } |
| 430 case LHU: { |
| 431 // Format(instr, "lhu 'rt, 'imms('rs)"); |
| 432 int32_t base_val = get_register(instr->RsField()); |
| 433 int32_t imm_val = instr->SImmField(); |
| 434 uword addr = base_val + imm_val; |
| 435 if (Simulator::IsIllegalAddress(addr)) { |
| 436 // TODO(zra) trap into debugger. |
| 437 UNIMPLEMENTED(); |
| 438 } else { |
| 439 int32_t res = ReadHU(addr, instr); |
| 440 set_register(instr->RtField(), res); |
| 441 } |
| 442 break; |
| 443 } |
| 308 case LUI: { | 444 case LUI: { |
| 309 ASSERT(instr->RsField() == 0); | 445 ASSERT(instr->RsField() == 0); |
| 310 set_register(instr->RtField(), instr->UImmField() << 16); | 446 set_register(instr->RtField(), instr->UImmField() << 16); |
| 311 break; | 447 break; |
| 312 } | 448 } |
| 449 case LW: { |
| 450 // Format(instr, "lw 'rt, 'imms('rs)"); |
| 451 int32_t base_val = get_register(instr->RsField()); |
| 452 int32_t imm_val = instr->SImmField(); |
| 453 uword addr = base_val + imm_val; |
| 454 if (Simulator::IsIllegalAddress(addr)) { |
| 455 // TODO(zra) trap into debugger. |
| 456 UNIMPLEMENTED(); |
| 457 } else { |
| 458 int32_t res = ReadW(addr, instr); |
| 459 set_register(instr->RtField(), res); |
| 460 } |
| 461 break; |
| 462 } |
| 313 case ORI: { | 463 case ORI: { |
| 314 // Format(instr, "ori 'rt, 'rs, 'immu"); | 464 // Format(instr, "ori 'rt, 'rs, 'immu"); |
| 315 int32_t rs_val = get_register(instr->RsField()); | 465 int32_t rs_val = get_register(instr->RsField()); |
| 316 set_register(instr->RtField(), rs_val | instr->UImmField()); | 466 set_register(instr->RtField(), rs_val | instr->UImmField()); |
| 317 break; | 467 break; |
| 318 } | 468 } |
| 469 case SB: { |
| 470 // Format(instr, "sb 'rt, 'imms('rs)"); |
| 471 int32_t rt_val = get_register(instr->RtField()); |
| 472 int32_t base_val = get_register(instr->RsField()); |
| 473 int32_t imm_val = instr->SImmField(); |
| 474 uword addr = base_val + imm_val; |
| 475 if (Simulator::IsIllegalAddress(addr)) { |
| 476 // TODO(zra) trap into debugger. |
| 477 UNIMPLEMENTED(); |
| 478 } else { |
| 479 WriteB(addr, rt_val & 0xff); |
| 480 } |
| 481 break; |
| 482 } |
| 483 case SH: { |
| 484 // Format(instr, "sh 'rt, 'imms('rs)"); |
| 485 int32_t rt_val = get_register(instr->RtField()); |
| 486 int32_t base_val = get_register(instr->RsField()); |
| 487 int32_t imm_val = instr->SImmField(); |
| 488 uword addr = base_val + imm_val; |
| 489 if (Simulator::IsIllegalAddress(addr)) { |
| 490 // TODO(zra) trap into debugger. |
| 491 UNIMPLEMENTED(); |
| 492 } else { |
| 493 WriteH(addr, rt_val & 0xffff, instr); |
| 494 } |
| 495 break; |
| 496 } |
| 497 case SW: { |
| 498 // Format(instr, "sw 'rt, 'imms('rs)"); |
| 499 int32_t rt_val = get_register(instr->RtField()); |
| 500 int32_t base_val = get_register(instr->RsField()); |
| 501 int32_t imm_val = instr->SImmField(); |
| 502 uword addr = base_val + imm_val; |
| 503 if (Simulator::IsIllegalAddress(addr)) { |
| 504 // TODO(zra) trap into debugger. |
| 505 UNIMPLEMENTED(); |
| 506 } else { |
| 507 WriteW(addr, rt_val, instr); |
| 508 } |
| 509 break; |
| 510 } |
| 319 default: { | 511 default: { |
| 320 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); | 512 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); |
| 321 UNREACHABLE(); | 513 UNREACHABLE(); |
| 322 break; | 514 break; |
| 323 } | 515 } |
| 324 } | 516 } |
| 325 pc_ += Instr::kInstrSize; | 517 pc_ += Instr::kInstrSize; |
| 326 } | 518 } |
| 327 | 519 |
| 328 | 520 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // Restore the SP register and return R1:R0. | 635 // Restore the SP register and return R1:R0. |
| 444 set_register(SP, sp_before_call); | 636 set_register(SP, sp_before_call); |
| 445 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 637 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
| 446 } | 638 } |
| 447 | 639 |
| 448 } // namespace dart | 640 } // namespace dart |
| 449 | 641 |
| 450 #endif // !defined(HOST_ARCH_MIPS) | 642 #endif // !defined(HOST_ARCH_MIPS) |
| 451 | 643 |
| 452 #endif // defined TARGET_ARCH_MIPS | 644 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |