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