| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM64) | 10 #if defined(TARGET_ARCH_ARM64) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); | 28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); |
| 29 | 29 |
| 30 | 30 |
| 31 // This macro provides a platform independent use of sscanf. The reason for | 31 // This macro provides a platform independent use of sscanf. The reason for |
| 32 // SScanF not being implemented in a platform independent way through | 32 // SScanF not being implemented in a platform independent way through |
| 33 // OS in the same way as SNPrint is that the Windows C Run-Time | 33 // OS in the same way as SNPrint is that the Windows C Run-Time |
| 34 // Library does not provide vsscanf. | 34 // Library does not provide vsscanf. |
| 35 #define SScanF sscanf // NOLINT | 35 #define SScanF sscanf // NOLINT |
| 36 | 36 |
| 37 | 37 |
| 38 // SimulatorSetjmpBuffer are linked together, and the last created one |
| 39 // is referenced by the Simulator. When an exception is thrown, the exception |
| 40 // runtime looks at where to jump and finds the corresponding |
| 41 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. |
| 42 // The runtime then does a Longjmp on that buffer to return to the simulator. |
| 43 class SimulatorSetjmpBuffer { |
| 44 public: |
| 45 int Setjmp() { return setjmp(buffer_); } |
| 46 void Longjmp() { |
| 47 // "This" is now the last setjmp buffer. |
| 48 simulator_->set_last_setjmp_buffer(this); |
| 49 longjmp(buffer_, 1); |
| 50 } |
| 51 |
| 52 explicit SimulatorSetjmpBuffer(Simulator* sim) { |
| 53 simulator_ = sim; |
| 54 link_ = sim->last_setjmp_buffer(); |
| 55 sim->set_last_setjmp_buffer(this); |
| 56 sp_ = static_cast<uword>(sim->get_register(R31, R31IsSP)); |
| 57 native_sp_ = reinterpret_cast<uword>(&sim); // Current C++ stack pointer. |
| 58 } |
| 59 |
| 60 ~SimulatorSetjmpBuffer() { |
| 61 ASSERT(simulator_->last_setjmp_buffer() == this); |
| 62 simulator_->set_last_setjmp_buffer(link_); |
| 63 } |
| 64 |
| 65 SimulatorSetjmpBuffer* link() { return link_; } |
| 66 |
| 67 uword sp() { return sp_; } |
| 68 uword native_sp() { return native_sp_; } |
| 69 |
| 70 private: |
| 71 uword sp_; |
| 72 uword native_sp_; |
| 73 Simulator* simulator_; |
| 74 SimulatorSetjmpBuffer* link_; |
| 75 jmp_buf buffer_; |
| 76 |
| 77 friend class Simulator; |
| 78 }; |
| 79 |
| 80 |
| 38 // The SimulatorDebugger class is used by the simulator while debugging | 81 // The SimulatorDebugger class is used by the simulator while debugging |
| 39 // simulated ARM64 code. | 82 // simulated ARM64 code. |
| 40 class SimulatorDebugger { | 83 class SimulatorDebugger { |
| 41 public: | 84 public: |
| 42 explicit SimulatorDebugger(Simulator* sim); | 85 explicit SimulatorDebugger(Simulator* sim); |
| 43 ~SimulatorDebugger(); | 86 ~SimulatorDebugger(); |
| 44 | 87 |
| 45 void Stop(Instr* instr, const char* message); | 88 void Stop(Instr* instr, const char* message); |
| 46 void Debug(); | 89 void Debug(); |
| 47 char* ReadLine(const char* prompt); | 90 char* ReadLine(const char* prompt); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 | 425 |
| 383 Simulator::~Simulator() { | 426 Simulator::~Simulator() { |
| 384 delete[] stack_; | 427 delete[] stack_; |
| 385 Isolate* isolate = Isolate::Current(); | 428 Isolate* isolate = Isolate::Current(); |
| 386 if (isolate != NULL) { | 429 if (isolate != NULL) { |
| 387 isolate->set_simulator(NULL); | 430 isolate->set_simulator(NULL); |
| 388 } | 431 } |
| 389 } | 432 } |
| 390 | 433 |
| 391 | 434 |
| 435 // When the generated code calls an external reference we need to catch that in |
| 436 // the simulator. The external reference will be a function compiled for the |
| 437 // host architecture. We need to call that function instead of trying to |
| 438 // execute it with the simulator. We do that by redirecting the external |
| 439 // reference to a svc (supervisor call) instruction that is handled by |
| 440 // the simulator. We write the original destination of the jump just at a known |
| 441 // offset from the svc instruction so the simulator knows what to call. |
| 442 class Redirection { |
| 443 public: |
| 444 uword address_of_hlt_instruction() { |
| 445 return reinterpret_cast<uword>(&hlt_instruction_); |
| 446 } |
| 447 |
| 448 uword external_function() const { return external_function_; } |
| 449 |
| 450 Simulator::CallKind call_kind() const { return call_kind_; } |
| 451 |
| 452 int argument_count() const { return argument_count_; } |
| 453 |
| 454 static Redirection* Get(uword external_function, |
| 455 Simulator::CallKind call_kind, |
| 456 int argument_count) { |
| 457 Redirection* current; |
| 458 for (current = list_; current != NULL; current = current->next_) { |
| 459 if (current->external_function_ == external_function) return current; |
| 460 } |
| 461 return new Redirection(external_function, call_kind, argument_count); |
| 462 } |
| 463 |
| 464 static Redirection* FromHltInstruction(Instr* hlt_instruction) { |
| 465 char* addr_of_hlt = reinterpret_cast<char*>(hlt_instruction); |
| 466 char* addr_of_redirection = |
| 467 addr_of_hlt - OFFSET_OF(Redirection, hlt_instruction_); |
| 468 return reinterpret_cast<Redirection*>(addr_of_redirection); |
| 469 } |
| 470 |
| 471 private: |
| 472 static const int32_t kRedirectInstruction = Instr::kRedirectInstruction; |
| 473 Redirection(uword external_function, |
| 474 Simulator::CallKind call_kind, |
| 475 int argument_count) |
| 476 : external_function_(external_function), |
| 477 call_kind_(call_kind), |
| 478 argument_count_(argument_count), |
| 479 hlt_instruction_(kRedirectInstruction), |
| 480 next_(list_) { |
| 481 list_ = this; |
| 482 } |
| 483 |
| 484 uword external_function_; |
| 485 Simulator::CallKind call_kind_; |
| 486 int argument_count_; |
| 487 uint32_t hlt_instruction_; |
| 488 Redirection* next_; |
| 489 static Redirection* list_; |
| 490 }; |
| 491 |
| 492 |
| 493 Redirection* Redirection::list_ = NULL; |
| 494 |
| 495 |
| 496 uword Simulator::RedirectExternalReference(uword function, |
| 497 CallKind call_kind, |
| 498 int argument_count) { |
| 499 Redirection* redirection = |
| 500 Redirection::Get(function, call_kind, argument_count); |
| 501 return redirection->address_of_hlt_instruction(); |
| 502 } |
| 503 |
| 504 |
| 392 // Get the active Simulator for the current isolate. | 505 // Get the active Simulator for the current isolate. |
| 393 Simulator* Simulator::Current() { | 506 Simulator* Simulator::Current() { |
| 394 Simulator* simulator = Isolate::Current()->simulator(); | 507 Simulator* simulator = Isolate::Current()->simulator(); |
| 395 if (simulator == NULL) { | 508 if (simulator == NULL) { |
| 396 simulator = new Simulator(); | 509 simulator = new Simulator(); |
| 397 Isolate::Current()->set_simulator(simulator); | 510 Isolate::Current()->set_simulator(simulator); |
| 398 } | 511 } |
| 399 return simulator; | 512 return simulator; |
| 400 } | 513 } |
| 401 | 514 |
| 402 | 515 |
| 403 // Sets the register in the architecture state. | 516 // Sets the register in the architecture state. |
| 404 void Simulator::set_register(Register reg, int64_t value, R31Type r31t) { | 517 void Simulator::set_register(Register reg, int64_t value, R31Type r31t) { |
| 405 // register is in range, and if it is R31, a mode is specified. | 518 // register is in range, and if it is R31, a mode is specified. |
| 406 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 519 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 407 ASSERT((reg != R31) || (r31t != R31IsUndef)); | |
| 408 if ((reg != R31) || (r31t != R31IsZR)) { | 520 if ((reg != R31) || (r31t != R31IsZR)) { |
| 409 registers_[reg] = value; | 521 registers_[reg] = value; |
| 410 } | 522 } |
| 411 } | 523 } |
| 412 | 524 |
| 413 | 525 |
| 414 // Get the register from the architecture state. | 526 // Get the register from the architecture state. |
| 415 int64_t Simulator::get_register(Register reg, R31Type r31t) const { | 527 int64_t Simulator::get_register(Register reg, R31Type r31t) const { |
| 416 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 528 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 417 ASSERT((reg != R31) || (r31t != R31IsUndef)); | |
| 418 if ((reg == R31) && (r31t == R31IsZR)) { | 529 if ((reg == R31) && (r31t == R31IsZR)) { |
| 419 return 0; | 530 return 0; |
| 420 } else { | 531 } else { |
| 421 return registers_[reg]; | 532 return registers_[reg]; |
| 422 } | 533 } |
| 423 } | 534 } |
| 424 | 535 |
| 425 | 536 |
| 426 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { | 537 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { |
| 427 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 538 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 428 ASSERT((reg != R31) || (r31t != R31IsUndef)); | |
| 429 // When setting in W mode, clear the high bits. | 539 // When setting in W mode, clear the high bits. |
| 430 if ((reg != R31) || (r31t != R31IsZR)) { | 540 if ((reg != R31) || (r31t != R31IsZR)) { |
| 431 registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0); | 541 registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0); |
| 432 } | 542 } |
| 433 } | 543 } |
| 434 | 544 |
| 435 | 545 |
| 436 // Get the register from the architecture state. | 546 // Get the register from the architecture state. |
| 437 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { | 547 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { |
| 438 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 548 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 439 ASSERT((reg != R31) || (r31t != R31IsUndef)); | |
| 440 if ((reg == R31) && (r31t == R31IsZR)) { | 549 if ((reg == R31) && (r31t == R31IsZR)) { |
| 441 return 0; | 550 return 0; |
| 442 } else { | 551 } else { |
| 443 return registers_[reg]; | 552 return registers_[reg]; |
| 444 } | 553 } |
| 445 } | 554 } |
| 446 | 555 |
| 447 | 556 |
| 448 // Raw access to the PC register. | 557 // Raw access to the PC register. |
| 449 void Simulator::set_pc(int64_t value) { | 558 void Simulator::set_pc(int64_t value) { |
| 450 pc_modified_ = true; | 559 pc_modified_ = true; |
| 560 last_pc_ = pc_; |
| 451 pc_ = value; | 561 pc_ = value; |
| 452 } | 562 } |
| 453 | 563 |
| 454 | 564 |
| 455 // Raw access to the PC register without the special adjustment when reading. | 565 // Raw access to the pc. |
| 456 int64_t Simulator::get_pc() const { | 566 int64_t Simulator::get_pc() const { |
| 457 return pc_; | 567 return pc_; |
| 458 } | 568 } |
| 459 | 569 |
| 460 | 570 |
| 571 int64_t Simulator::get_last_pc() const { |
| 572 return last_pc_; |
| 573 } |
| 574 |
| 575 |
| 461 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 576 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 462 uword fault_pc = get_pc(); | 577 uword fault_pc = get_pc(); |
| 578 uword last_pc = get_last_pc(); |
| 463 // TODO(zra): drop into debugger. | 579 // TODO(zra): drop into debugger. |
| 464 char buffer[128]; | 580 char buffer[128]; |
| 465 snprintf(buffer, sizeof(buffer), | 581 snprintf(buffer, sizeof(buffer), |
| 466 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", | 582 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px"\n", |
| 467 addr, fault_pc); | 583 addr, fault_pc, last_pc); |
| 584 SimulatorDebugger dbg(this); |
| 585 dbg.Stop(instr, buffer); |
| 468 // The debugger will return control in non-interactive mode. | 586 // The debugger will return control in non-interactive mode. |
| 469 FATAL("Cannot continue execution after illegal memory access."); | 587 FATAL("Cannot continue execution after illegal memory access."); |
| 470 } | 588 } |
| 471 | 589 |
| 472 | 590 |
| 473 // The ARMv8 manual advises that an unaligned access may generate a fault, | 591 // The ARMv8 manual advises that an unaligned access may generate a fault, |
| 474 // and if not, will likely take a number of additional cycles to execute, | 592 // and if not, will likely take a number of additional cycles to execute, |
| 475 // so let's just not generate any. | 593 // so let's just not generate any. |
| 476 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 594 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
| 477 char buffer[64]; | 595 char buffer[64]; |
| 478 snprintf(buffer, sizeof(buffer), | 596 snprintf(buffer, sizeof(buffer), |
| 479 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); | 597 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); |
| 480 // TODO(zra): Drop into the simulator debugger when it exists. | 598 SimulatorDebugger dbg(this); |
| 599 dbg.Stop(instr, buffer); |
| 481 // The debugger will not be able to single step past this instruction, but | 600 // The debugger will not be able to single step past this instruction, but |
| 482 // it will be possible to disassemble the code and inspect registers. | 601 // it will be possible to disassemble the code and inspect registers. |
| 483 FATAL("Cannot continue execution after unaligned access."); | 602 FATAL("Cannot continue execution after unaligned access."); |
| 484 } | 603 } |
| 485 | 604 |
| 486 | 605 |
| 487 void Simulator::UnimplementedInstruction(Instr* instr) { | 606 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 488 char buffer[64]; | 607 char buffer[64]; |
| 489 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 608 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 490 // TODO(zra): drop into debugger. | 609 SimulatorDebugger dbg(this); |
| 610 dbg.Stop(instr, buffer); |
| 491 FATAL("Cannot continue execution after unimplemented instruction."); | 611 FATAL("Cannot continue execution after unimplemented instruction."); |
| 492 } | 612 } |
| 493 | 613 |
| 494 | 614 |
| 495 // Returns the top of the stack area to enable checking for stack pointer | 615 // Returns the top of the stack area to enable checking for stack pointer |
| 496 // validity. | 616 // validity. |
| 497 uword Simulator::StackTop() const { | 617 uword Simulator::StackTop() const { |
| 498 // To be safe in potential stack underflows we leave some buffer above and | 618 // To be safe in potential stack underflows we leave some buffer above and |
| 499 // set the stack top. | 619 // set the stack top. |
| 500 return reinterpret_cast<uword>(stack_) + | 620 return reinterpret_cast<uword>(stack_) + |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 UnimplementedInstruction(instr); | 1038 UnimplementedInstruction(instr); |
| 919 } | 1039 } |
| 920 const int64_t imm19 = instr->SImm19Field(); | 1040 const int64_t imm19 = instr->SImm19Field(); |
| 921 const int64_t dest = get_pc() + (imm19 << 2); | 1041 const int64_t dest = get_pc() + (imm19 << 2); |
| 922 if (ConditionallyExecute(instr)) { | 1042 if (ConditionallyExecute(instr)) { |
| 923 set_pc(dest); | 1043 set_pc(dest); |
| 924 } | 1044 } |
| 925 } | 1045 } |
| 926 | 1046 |
| 927 | 1047 |
| 1048 // Calls into the Dart runtime are based on this interface. |
| 1049 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 1050 |
| 1051 // Calls to leaf Dart runtime functions are based on this interface. |
| 1052 typedef int32_t (*SimulatorLeafRuntimeCall)( |
| 1053 int64_t r0, int64_t r1, int64_t r2, int64_t r3, |
| 1054 int64_t r4, int64_t r5, int64_t r6, int64_t r7); |
| 1055 |
| 1056 // Calls to leaf float Dart runtime functions are based on this interface. |
| 1057 typedef double (*SimulatorLeafFloatRuntimeCall)( |
| 1058 double d0, double d1, double d2, double d3, |
| 1059 double d4, double d5, double d6, double d7); |
| 1060 |
| 1061 // Calls to native Dart functions are based on this interface. |
| 1062 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
| 1063 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
| 1064 |
| 1065 |
| 1066 void Simulator::DoRedirectedCall(Instr* instr) { |
| 1067 SimulatorSetjmpBuffer buffer(this); |
| 1068 if (!setjmp(buffer.buffer_)) { |
| 1069 int64_t saved_lr = get_register(LR); |
| 1070 Redirection* redirection = Redirection::FromHltInstruction(instr); |
| 1071 uword external = redirection->external_function(); |
| 1072 if (FLAG_trace_sim) { |
| 1073 OS::Print("Call to host function at 0x%" Pd "\n", external); |
| 1074 } |
| 1075 |
| 1076 if ((redirection->call_kind() == kRuntimeCall) || |
| 1077 (redirection->call_kind() == kBootstrapNativeCall) || |
| 1078 (redirection->call_kind() == kNativeCall)) { |
| 1079 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1080 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1081 } |
| 1082 if (redirection->call_kind() == kRuntimeCall) { |
| 1083 NativeArguments arguments; |
| 1084 ASSERT(sizeof(NativeArguments) == 4*kWordSize); |
| 1085 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); |
| 1086 arguments.argc_tag_ = get_register(R1); |
| 1087 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); |
| 1088 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); |
| 1089 SimulatorRuntimeCall target = |
| 1090 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1091 target(arguments); |
| 1092 set_register(R0, icount_); // Zap result register from void function. |
| 1093 set_register(R1, icount_); |
| 1094 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
| 1095 ASSERT((0 <= redirection->argument_count()) && |
| 1096 (redirection->argument_count() <= 8)); |
| 1097 int64_t r0 = get_register(R0); |
| 1098 int64_t r1 = get_register(R1); |
| 1099 int64_t r2 = get_register(R2); |
| 1100 int64_t r3 = get_register(R3); |
| 1101 int64_t r4 = get_register(R4); |
| 1102 int64_t r5 = get_register(R5); |
| 1103 int64_t r6 = get_register(R6); |
| 1104 int64_t r7 = get_register(R7); |
| 1105 SimulatorLeafRuntimeCall target = |
| 1106 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
| 1107 r0 = target(r0, r1, r2, r3, r4, r5, r6, r7); |
| 1108 set_register(R0, r0); // Set returned result from function. |
| 1109 set_register(R1, icount_); // Zap unused result register. |
| 1110 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
| 1111 // TODO(zra): leaf float runtime calls. |
| 1112 UNIMPLEMENTED(); |
| 1113 } else if (redirection->call_kind() == kBootstrapNativeCall) { |
| 1114 NativeArguments* arguments; |
| 1115 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1116 SimulatorBootstrapNativeCall target = |
| 1117 reinterpret_cast<SimulatorBootstrapNativeCall>(external); |
| 1118 target(arguments); |
| 1119 set_register(R0, icount_); // Zap result register from void function. |
| 1120 } else { |
| 1121 ASSERT(redirection->call_kind() == kNativeCall); |
| 1122 NativeArguments* arguments; |
| 1123 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1124 uword target_func = get_register(R1); |
| 1125 SimulatorNativeCall target = |
| 1126 reinterpret_cast<SimulatorNativeCall>(external); |
| 1127 target(arguments, target_func); |
| 1128 set_register(R0, icount_); // Zap result register from void function. |
| 1129 set_register(R1, icount_); |
| 1130 } |
| 1131 set_top_exit_frame_info(0); |
| 1132 |
| 1133 // Zap caller-saved registers, since the actual runtime call could have |
| 1134 // used them. |
| 1135 set_register(R2, icount_); |
| 1136 set_register(R3, icount_); |
| 1137 set_register(R4, icount_); |
| 1138 set_register(R5, icount_); |
| 1139 set_register(R6, icount_); |
| 1140 set_register(R7, icount_); |
| 1141 set_register(R8, icount_); |
| 1142 set_register(R9, icount_); |
| 1143 set_register(R10, icount_); |
| 1144 set_register(R11, icount_); |
| 1145 set_register(R12, icount_); |
| 1146 set_register(R13, icount_); |
| 1147 set_register(R14, icount_); |
| 1148 set_register(R15, icount_); |
| 1149 set_register(IP0, icount_); |
| 1150 set_register(IP1, icount_); |
| 1151 set_register(R18, icount_); |
| 1152 set_register(LR, icount_); |
| 1153 |
| 1154 // TODO(zra): Zap caller-saved fpu registers. |
| 1155 |
| 1156 // Return. |
| 1157 set_pc(saved_lr); |
| 1158 } else { |
| 1159 // Coming via long jump from a throw. Continue to exception handler. |
| 1160 set_top_exit_frame_info(0); |
| 1161 } |
| 1162 } |
| 1163 |
| 1164 |
| 928 void Simulator::DecodeExceptionGen(Instr* instr) { | 1165 void Simulator::DecodeExceptionGen(Instr* instr) { |
| 929 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 1166 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
| 930 (instr->Bits(21, 3) == 0)) { | 1167 (instr->Bits(21, 3) == 0)) { |
| 931 // Format(instr, "svc 'imm16"); | 1168 // Format(instr, "svc 'imm16"); |
| 932 UnimplementedInstruction(instr); | 1169 UnimplementedInstruction(instr); |
| 933 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1170 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 934 (instr->Bits(21, 3) == 1)) { | 1171 (instr->Bits(21, 3) == 1)) { |
| 935 // Format(instr, "brk 'imm16"); | 1172 // Format(instr, "brk 'imm16"); |
| 936 UnimplementedInstruction(instr); | 1173 UnimplementedInstruction(instr); |
| 937 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1174 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 938 (instr->Bits(21, 3) == 2)) { | 1175 (instr->Bits(21, 3) == 2)) { |
| 939 // Format(instr, "hlt 'imm16"); | 1176 // Format(instr, "hlt 'imm16"); |
| 940 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); | 1177 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); |
| 941 if (imm == kImmExceptionIsDebug) { | 1178 if (imm == kImmExceptionIsDebug) { |
| 942 SimulatorDebugger dbg(this); | 1179 SimulatorDebugger dbg(this); |
| 943 const char* message = *reinterpret_cast<const char**>( | 1180 const char* message = *reinterpret_cast<const char**>( |
| 944 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1181 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 945 set_pc(get_pc() + Instr::kInstrSize); | 1182 set_pc(get_pc() + Instr::kInstrSize); |
| 946 dbg.Stop(instr, message); | 1183 dbg.Stop(instr, message); |
| 947 } else if (imm == kImmExceptionIsPrintf) { | 1184 } else if (imm == kImmExceptionIsPrintf) { |
| 948 const char* message = *reinterpret_cast<const char**>( | 1185 const char* message = *reinterpret_cast<const char**>( |
| 949 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1186 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 950 OS::Print("Simulator hit: %s", message); | 1187 OS::Print("Simulator hit: %s", message); |
| 1188 } else if (imm == kImmExceptionIsRedirectedCall) { |
| 1189 DoRedirectedCall(instr); |
| 951 } else { | 1190 } else { |
| 952 UnimplementedInstruction(instr); | 1191 UnimplementedInstruction(instr); |
| 953 } | 1192 } |
| 954 } | 1193 } |
| 955 } | 1194 } |
| 956 | 1195 |
| 957 | 1196 |
| 958 void Simulator::DecodeSystem(Instr* instr) { | 1197 void Simulator::DecodeSystem(Instr* instr) { |
| 959 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && | 1198 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && |
| 960 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && | 1199 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 set_register(R21, r21_val); | 1984 set_register(R21, r21_val); |
| 1746 set_register(R22, r22_val); | 1985 set_register(R22, r22_val); |
| 1747 set_register(R23, r23_val); | 1986 set_register(R23, r23_val); |
| 1748 set_register(R24, r24_val); | 1987 set_register(R24, r24_val); |
| 1749 set_register(R25, r25_val); | 1988 set_register(R25, r25_val); |
| 1750 set_register(R26, r26_val); | 1989 set_register(R26, r26_val); |
| 1751 set_register(R27, r27_val); | 1990 set_register(R27, r27_val); |
| 1752 set_register(R28, r28_val); | 1991 set_register(R28, r28_val); |
| 1753 set_register(R29, r29_val); | 1992 set_register(R29, r29_val); |
| 1754 | 1993 |
| 1755 // Restore the SP register and return R1:R0. | 1994 // Restore the SP register and return R0. |
| 1756 set_register(R31, sp_before_call, R31IsSP); | 1995 set_register(R31, sp_before_call, R31IsSP); |
| 1757 int64_t return_value; | 1996 int64_t return_value; |
| 1758 return_value = get_register(R0); | 1997 return_value = get_register(R0); |
| 1759 return return_value; | 1998 return return_value; |
| 1760 } | 1999 } |
| 1761 | 2000 |
| 1762 } // namespace dart | 2001 } // namespace dart |
| 1763 | 2002 |
| 1764 #endif // !defined(HOST_ARCH_ARM64) | 2003 #endif // !defined(HOST_ARCH_ARM64) |
| 1765 | 2004 |
| 1766 #endif // defined TARGET_ARCH_ARM64 | 2005 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |