| 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)); | 520 ASSERT((reg != R31) || (r31t != R31IsUndef)); |
| 408 if ((reg != R31) || (r31t != R31IsZR)) { | 521 if ((reg != R31) || (r31t != R31IsZR)) { |
| 409 registers_[reg] = value; | 522 registers_[reg] = value; |
| 410 } | 523 } |
| 411 } | 524 } |
| 412 | 525 |
| 413 | 526 |
| 414 // Get the register from the architecture state. | 527 // Get the register from the architecture state. |
| 415 int64_t Simulator::get_register(Register reg, R31Type r31t) const { | 528 int64_t Simulator::get_register(Register reg, R31Type r31t) const { |
| 416 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 529 ASSERT(((reg >= 0) && (reg < kNumberOfCpuRegisters)) || (reg == SPREG)); |
| 417 ASSERT((reg != R31) || (r31t != R31IsUndef)); | 530 ASSERT((reg != R31) || (r31t != R31IsUndef)); |
| 418 if ((reg == R31) && (r31t == R31IsZR)) { | 531 if ((reg == R31) && (r31t == R31IsZR)) { |
| 419 return 0; | 532 return 0; |
| 533 } else if (reg == SPREG) { |
| 534 // SPREG is used from architecture independent code. It is only ever passed |
| 535 // to Simulator::get_register(). Calls to get_register() from architecture |
| 536 // independent code don't include an R31Type, so if we were to define |
| 537 // SPREG to be R31, we wouldn't be able to distinguish from ZR. Therefore we |
| 538 // use another value, and check for it in get_register(). |
| 539 return registers_[R31]; |
| 420 } else { | 540 } else { |
| 421 return registers_[reg]; | 541 return registers_[reg]; |
| 422 } | 542 } |
| 423 } | 543 } |
| 424 | 544 |
| 425 | 545 |
| 426 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { | 546 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { |
| 427 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 547 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 428 ASSERT((reg != R31) || (r31t != R31IsUndef)); | 548 ASSERT((reg != R31) || (r31t != R31IsUndef)); |
| 429 // When setting in W mode, clear the high bits. | 549 // When setting in W mode, clear the high bits. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 441 return 0; | 561 return 0; |
| 442 } else { | 562 } else { |
| 443 return registers_[reg]; | 563 return registers_[reg]; |
| 444 } | 564 } |
| 445 } | 565 } |
| 446 | 566 |
| 447 | 567 |
| 448 // Raw access to the PC register. | 568 // Raw access to the PC register. |
| 449 void Simulator::set_pc(int64_t value) { | 569 void Simulator::set_pc(int64_t value) { |
| 450 pc_modified_ = true; | 570 pc_modified_ = true; |
| 571 last_pc_ = pc_; |
| 451 pc_ = value; | 572 pc_ = value; |
| 452 } | 573 } |
| 453 | 574 |
| 454 | 575 |
| 455 // Raw access to the PC register without the special adjustment when reading. | 576 // Raw access to the pc. |
| 456 int64_t Simulator::get_pc() const { | 577 int64_t Simulator::get_pc() const { |
| 457 return pc_; | 578 return pc_; |
| 458 } | 579 } |
| 459 | 580 |
| 460 | 581 |
| 582 int64_t Simulator::get_last_pc() const { |
| 583 return last_pc_; |
| 584 } |
| 585 |
| 586 |
| 461 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 587 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 462 uword fault_pc = get_pc(); | 588 uword fault_pc = get_pc(); |
| 589 uword last_pc = get_last_pc(); |
| 463 // TODO(zra): drop into debugger. | 590 // TODO(zra): drop into debugger. |
| 464 char buffer[128]; | 591 char buffer[128]; |
| 465 snprintf(buffer, sizeof(buffer), | 592 snprintf(buffer, sizeof(buffer), |
| 466 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", | 593 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px"\n", |
| 467 addr, fault_pc); | 594 addr, fault_pc, last_pc); |
| 595 SimulatorDebugger dbg(this); |
| 596 dbg.Stop(instr, buffer); |
| 468 // The debugger will return control in non-interactive mode. | 597 // The debugger will return control in non-interactive mode. |
| 469 FATAL("Cannot continue execution after illegal memory access."); | 598 FATAL("Cannot continue execution after illegal memory access."); |
| 470 } | 599 } |
| 471 | 600 |
| 472 | 601 |
| 473 // The ARMv8 manual advises that an unaligned access may generate a fault, | 602 // 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, | 603 // and if not, will likely take a number of additional cycles to execute, |
| 475 // so let's just not generate any. | 604 // so let's just not generate any. |
| 476 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 605 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
| 477 char buffer[64]; | 606 char buffer[64]; |
| 478 snprintf(buffer, sizeof(buffer), | 607 snprintf(buffer, sizeof(buffer), |
| 479 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); | 608 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr); |
| 480 // TODO(zra): Drop into the simulator debugger when it exists. | 609 SimulatorDebugger dbg(this); |
| 610 dbg.Stop(instr, buffer); |
| 481 // The debugger will not be able to single step past this instruction, but | 611 // 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. | 612 // it will be possible to disassemble the code and inspect registers. |
| 483 FATAL("Cannot continue execution after unaligned access."); | 613 FATAL("Cannot continue execution after unaligned access."); |
| 484 } | 614 } |
| 485 | 615 |
| 486 | 616 |
| 487 void Simulator::UnimplementedInstruction(Instr* instr) { | 617 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 488 char buffer[64]; | 618 char buffer[64]; |
| 489 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 619 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 490 // TODO(zra): drop into debugger. | 620 SimulatorDebugger dbg(this); |
| 621 dbg.Stop(instr, buffer); |
| 491 FATAL("Cannot continue execution after unimplemented instruction."); | 622 FATAL("Cannot continue execution after unimplemented instruction."); |
| 492 } | 623 } |
| 493 | 624 |
| 494 | 625 |
| 495 // Returns the top of the stack area to enable checking for stack pointer | 626 // Returns the top of the stack area to enable checking for stack pointer |
| 496 // validity. | 627 // validity. |
| 497 uword Simulator::StackTop() const { | 628 uword Simulator::StackTop() const { |
| 498 // To be safe in potential stack underflows we leave some buffer above and | 629 // To be safe in potential stack underflows we leave some buffer above and |
| 499 // set the stack top. | 630 // set the stack top. |
| 500 return reinterpret_cast<uword>(stack_) + | 631 return reinterpret_cast<uword>(stack_) + |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 UnimplementedInstruction(instr); | 1049 UnimplementedInstruction(instr); |
| 919 } | 1050 } |
| 920 const int64_t imm19 = instr->SImm19Field(); | 1051 const int64_t imm19 = instr->SImm19Field(); |
| 921 const int64_t dest = get_pc() + (imm19 << 2); | 1052 const int64_t dest = get_pc() + (imm19 << 2); |
| 922 if (ConditionallyExecute(instr)) { | 1053 if (ConditionallyExecute(instr)) { |
| 923 set_pc(dest); | 1054 set_pc(dest); |
| 924 } | 1055 } |
| 925 } | 1056 } |
| 926 | 1057 |
| 927 | 1058 |
| 1059 // Calls into the Dart runtime are based on this interface. |
| 1060 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 1061 |
| 1062 // Calls to leaf Dart runtime functions are based on this interface. |
| 1063 typedef int32_t (*SimulatorLeafRuntimeCall)( |
| 1064 int64_t r0, int64_t r1, int64_t r2, int64_t r3); |
| 1065 |
| 1066 // Calls to leaf float Dart runtime functions are based on this interface. |
| 1067 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
| 1068 |
| 1069 // Calls to native Dart functions are based on this interface. |
| 1070 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
| 1071 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
| 1072 |
| 1073 |
| 1074 void Simulator::DoRedirectedCall(Instr* instr) { |
| 1075 SimulatorSetjmpBuffer buffer(this); |
| 1076 if (!setjmp(buffer.buffer_)) { |
| 1077 int64_t saved_lr = get_register(LR); |
| 1078 Redirection* redirection = Redirection::FromHltInstruction(instr); |
| 1079 uword external = redirection->external_function(); |
| 1080 if (FLAG_trace_sim) { |
| 1081 OS::Print("Call to host function at 0x%" Pd "\n", external); |
| 1082 } |
| 1083 |
| 1084 if ((redirection->call_kind() == kRuntimeCall) || |
| 1085 (redirection->call_kind() == kBootstrapNativeCall) || |
| 1086 (redirection->call_kind() == kNativeCall)) { |
| 1087 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1088 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1089 } |
| 1090 if (redirection->call_kind() == kRuntimeCall) { |
| 1091 NativeArguments arguments; |
| 1092 ASSERT(sizeof(NativeArguments) == 4*kWordSize); |
| 1093 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0)); |
| 1094 arguments.argc_tag_ = get_register(R1); |
| 1095 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2)); |
| 1096 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3)); |
| 1097 SimulatorRuntimeCall target = |
| 1098 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1099 target(arguments); |
| 1100 set_register(R0, icount_); // Zap result register from void function. |
| 1101 set_register(R1, icount_); |
| 1102 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
| 1103 ASSERT((0 <= redirection->argument_count()) && |
| 1104 (redirection->argument_count() <= 4)); |
| 1105 int64_t r0 = get_register(R0); |
| 1106 int64_t r1 = get_register(R1); |
| 1107 int64_t r2 = get_register(R2); |
| 1108 int64_t r3 = get_register(R3); |
| 1109 SimulatorLeafRuntimeCall target = |
| 1110 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
| 1111 r0 = target(r0, r1, r2, r3); |
| 1112 set_register(R0, r0); // Set returned result from function. |
| 1113 set_register(R1, icount_); // Zap unused result register. |
| 1114 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
| 1115 // TODO(zra): leaf float runtime calls. |
| 1116 UNIMPLEMENTED(); |
| 1117 } else if (redirection->call_kind() == kBootstrapNativeCall) { |
| 1118 NativeArguments* arguments; |
| 1119 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1120 SimulatorBootstrapNativeCall target = |
| 1121 reinterpret_cast<SimulatorBootstrapNativeCall>(external); |
| 1122 target(arguments); |
| 1123 set_register(R0, icount_); // Zap result register from void function. |
| 1124 } else { |
| 1125 ASSERT(redirection->call_kind() == kNativeCall); |
| 1126 NativeArguments* arguments; |
| 1127 arguments = reinterpret_cast<NativeArguments*>(get_register(R0)); |
| 1128 uword target_func = get_register(R1); |
| 1129 SimulatorNativeCall target = |
| 1130 reinterpret_cast<SimulatorNativeCall>(external); |
| 1131 target(arguments, target_func); |
| 1132 set_register(R0, icount_); // Zap result register from void function. |
| 1133 set_register(R1, icount_); |
| 1134 } |
| 1135 set_top_exit_frame_info(0); |
| 1136 |
| 1137 // Zap caller-saved registers, since the actual runtime call could have |
| 1138 // used them. |
| 1139 set_register(R2, icount_); |
| 1140 set_register(R3, icount_); |
| 1141 set_register(R4, icount_); |
| 1142 set_register(R5, icount_); |
| 1143 set_register(R6, icount_); |
| 1144 set_register(R7, icount_); |
| 1145 set_register(R8, icount_); |
| 1146 set_register(R9, icount_); |
| 1147 set_register(R10, icount_); |
| 1148 set_register(R11, icount_); |
| 1149 set_register(R12, icount_); |
| 1150 set_register(R13, icount_); |
| 1151 set_register(R14, icount_); |
| 1152 set_register(R15, icount_); |
| 1153 set_register(IP0, icount_); |
| 1154 set_register(IP1, icount_); |
| 1155 set_register(R18, icount_); |
| 1156 set_register(LR, icount_); |
| 1157 |
| 1158 // TODO(zra): Zap caller-saved fpu registers. |
| 1159 |
| 1160 // Return. |
| 1161 set_pc(saved_lr); |
| 1162 } else { |
| 1163 // Coming via long jump from a throw. Continue to exception handler. |
| 1164 set_top_exit_frame_info(0); |
| 1165 } |
| 1166 } |
| 1167 |
| 1168 |
| 928 void Simulator::DecodeExceptionGen(Instr* instr) { | 1169 void Simulator::DecodeExceptionGen(Instr* instr) { |
| 929 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 1170 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
| 930 (instr->Bits(21, 3) == 0)) { | 1171 (instr->Bits(21, 3) == 0)) { |
| 931 // Format(instr, "svc 'imm16"); | 1172 // Format(instr, "svc 'imm16"); |
| 932 UnimplementedInstruction(instr); | 1173 UnimplementedInstruction(instr); |
| 933 } 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) && |
| 934 (instr->Bits(21, 3) == 1)) { | 1175 (instr->Bits(21, 3) == 1)) { |
| 935 // Format(instr, "brk 'imm16"); | 1176 // Format(instr, "brk 'imm16"); |
| 936 UnimplementedInstruction(instr); | 1177 UnimplementedInstruction(instr); |
| 937 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1178 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 938 (instr->Bits(21, 3) == 2)) { | 1179 (instr->Bits(21, 3) == 2)) { |
| 939 // Format(instr, "hlt 'imm16"); | 1180 // Format(instr, "hlt 'imm16"); |
| 940 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); | 1181 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); |
| 941 if (imm == kImmExceptionIsDebug) { | 1182 if (imm == kImmExceptionIsDebug) { |
| 942 SimulatorDebugger dbg(this); | 1183 SimulatorDebugger dbg(this); |
| 943 const char* message = *reinterpret_cast<const char**>( | 1184 const char* message = *reinterpret_cast<const char**>( |
| 944 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1185 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 945 set_pc(get_pc() + Instr::kInstrSize); | 1186 set_pc(get_pc() + Instr::kInstrSize); |
| 946 dbg.Stop(instr, message); | 1187 dbg.Stop(instr, message); |
| 947 } else if (imm == kImmExceptionIsPrintf) { | 1188 } else if (imm == kImmExceptionIsPrintf) { |
| 948 const char* message = *reinterpret_cast<const char**>( | 1189 const char* message = *reinterpret_cast<const char**>( |
| 949 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1190 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 950 OS::Print("Simulator hit: %s", message); | 1191 OS::Print("Simulator hit: %s", message); |
| 1192 } else if (imm == kImmExceptionIsRedirectedCall) { |
| 1193 DoRedirectedCall(instr); |
| 951 } else { | 1194 } else { |
| 952 UnimplementedInstruction(instr); | 1195 UnimplementedInstruction(instr); |
| 953 } | 1196 } |
| 954 } | 1197 } |
| 955 } | 1198 } |
| 956 | 1199 |
| 957 | 1200 |
| 958 void Simulator::DecodeSystem(Instr* instr) { | 1201 void Simulator::DecodeSystem(Instr* instr) { |
| 959 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && | 1202 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && |
| 960 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && | 1203 (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); | 1988 set_register(R21, r21_val); |
| 1746 set_register(R22, r22_val); | 1989 set_register(R22, r22_val); |
| 1747 set_register(R23, r23_val); | 1990 set_register(R23, r23_val); |
| 1748 set_register(R24, r24_val); | 1991 set_register(R24, r24_val); |
| 1749 set_register(R25, r25_val); | 1992 set_register(R25, r25_val); |
| 1750 set_register(R26, r26_val); | 1993 set_register(R26, r26_val); |
| 1751 set_register(R27, r27_val); | 1994 set_register(R27, r27_val); |
| 1752 set_register(R28, r28_val); | 1995 set_register(R28, r28_val); |
| 1753 set_register(R29, r29_val); | 1996 set_register(R29, r29_val); |
| 1754 | 1997 |
| 1755 // Restore the SP register and return R1:R0. | 1998 // Restore the SP register and return R0. |
| 1756 set_register(R31, sp_before_call, R31IsSP); | 1999 set_register(R31, sp_before_call, R31IsSP); |
| 1757 int64_t return_value; | 2000 int64_t return_value; |
| 1758 return_value = get_register(R0); | 2001 return_value = get_register(R0); |
| 1759 return return_value; | 2002 return return_value; |
| 1760 } | 2003 } |
| 1761 | 2004 |
| 1762 } // namespace dart | 2005 } // namespace dart |
| 1763 | 2006 |
| 1764 #endif // !defined(HOST_ARCH_ARM64) | 2007 #endif // !defined(HOST_ARCH_ARM64) |
| 1765 | 2008 |
| 1766 #endif // defined TARGET_ARCH_ARM64 | 2009 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |