Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: runtime/vm/simulator_arm64.cc

Issue 227593012: Adds ldr and str to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/vm/constants_arm64.h ('K') | « runtime/vm/simulator_arm64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 for (int i = 0; i < kNumberOfCpuRegisters; i++) { 56 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
57 registers_[i] = 0; 57 registers_[i] = 0;
58 } 58 }
59 n_flag_ = false; 59 n_flag_ = false;
60 z_flag_ = false; 60 z_flag_ = false;
61 c_flag_ = false; 61 c_flag_ = false;
62 v_flag_ = false; 62 v_flag_ = false;
63 63
64 // The sp is initialized to point to the bottom (high address) of the 64 // The sp is initialized to point to the bottom (high address) of the
65 // allocated stack area. 65 // allocated stack area.
66 registers_[SP] = StackTop(); 66 registers_[R31] = StackTop();
67 // The lr and pc are initialized to a known bad value that will cause an 67 // The lr and pc are initialized to a known bad value that will cause an
68 // access violation if the simulator ever tries to execute it. 68 // access violation if the simulator ever tries to execute it.
69 registers_[LR] = kBadLR; 69 registers_[LR] = kBadLR;
70 pc_ = kBadLR; 70 pc_ = kBadLR;
71 } 71 }
72 72
73 73
74 Simulator::~Simulator() { 74 Simulator::~Simulator() {
75 delete[] stack_; 75 delete[] stack_;
76 Isolate* isolate = Isolate::Current(); 76 Isolate* isolate = Isolate::Current();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 // TODO(zra): drop into debugger. 154 // TODO(zra): drop into debugger.
155 char buffer[128]; 155 char buffer[128];
156 snprintf(buffer, sizeof(buffer), 156 snprintf(buffer, sizeof(buffer),
157 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", 157 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n",
158 addr, fault_pc); 158 addr, fault_pc);
159 // The debugger will return control in non-interactive mode. 159 // The debugger will return control in non-interactive mode.
160 FATAL("Cannot continue execution after illegal memory access."); 160 FATAL("Cannot continue execution after illegal memory access.");
161 } 161 }
162 162
163 163
164 // The ARMv8 manual advises that an unaligned access may generate a fault,
165 // and if not, will likely take a number of additional cycles to execute,
166 // so let's just not generate any.
167 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) {
168 char buffer[64];
169 snprintf(buffer, sizeof(buffer),
170 "unaligned %s at 0x%" Px ", pc=%p\n", msg, addr, instr);
171 // TODO(zra): Drop into the simulator debugger when it exists.
172 // The debugger will not be able to single step past this instruction, but
173 // it will be possible to disassemble the code and inspect registers.
174 FATAL("Cannot continue execution after unaligned access.");
175 }
176
177
164 void Simulator::UnimplementedInstruction(Instr* instr) { 178 void Simulator::UnimplementedInstruction(Instr* instr) {
165 char buffer[64]; 179 char buffer[64];
166 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); 180 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
167 // TODO(zra): drop into debugger. 181 // TODO(zra): drop into debugger.
168 FATAL("Cannot continue execution after unimplemented instruction."); 182 FATAL("Cannot continue execution after unimplemented instruction.");
169 } 183 }
170 184
171 185
172 // Returns the top of the stack area to enable checking for stack pointer 186 // Returns the top of the stack area to enable checking for stack pointer
173 // validity. 187 // validity.
174 uword Simulator::StackTop() const { 188 uword Simulator::StackTop() const {
175 // To be safe in potential stack underflows we leave some buffer above and 189 // To be safe in potential stack underflows we leave some buffer above and
176 // set the stack top. 190 // set the stack top.
177 return reinterpret_cast<uword>(stack_) + 191 return reinterpret_cast<uword>(stack_) +
178 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); 192 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
179 } 193 }
180 194
181 195
196 intptr_t Simulator::ReadX(uword addr, Instr* instr) {
197 if ((addr & 7) == 0) {
198 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
199 return *ptr;
200 }
201 UnalignedAccess("read", addr, instr);
202 return 0;
203 }
204
205
206 void Simulator::WriteX(uword addr, intptr_t value, Instr* instr) {
207 if ((addr & 7) == 0) {
208 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
209 *ptr = value;
210 return;
211 }
212 UnalignedAccess("write", addr, instr);
213 }
214
215
216 uint32_t Simulator::ReadWU(uword addr, Instr* instr) {
217 if ((addr & 3) == 0) {
218 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
219 return *ptr;
220 }
221 UnalignedAccess("read unsigned single word", addr, instr);
222 return 0;
223 }
224
225
226 int32_t Simulator::ReadW(uword addr, Instr* instr) {
227 if ((addr & 3) == 0) {
228 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
229 return *ptr;
230 }
231 UnalignedAccess("read single word", addr, instr);
232 return 0;
233 }
234
235
236 void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) {
237 if ((addr & 3) == 0) {
238 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
239 *ptr = value;
240 return;
241 }
242 UnalignedAccess("write single word", addr, instr);
243 }
244
245
246 uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
247 if ((addr & 1) == 0) {
248 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
249 return *ptr;
250 }
251 UnalignedAccess("unsigned halfword read", addr, instr);
252 return 0;
253 }
254
255
256 int16_t Simulator::ReadH(uword addr, Instr* instr) {
257 if ((addr & 1) == 0) {
258 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
259 return *ptr;
260 }
261 UnalignedAccess("signed halfword read", addr, instr);
262 return 0;
263 }
264
265
266 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) {
267 if ((addr & 1) == 0) {
268 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
269 *ptr = value;
270 return;
271 }
272 UnalignedAccess("halfword write", addr, instr);
273 }
274
275
276 uint8_t Simulator::ReadBU(uword addr) {
277 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
278 return *ptr;
279 }
280
281
282 int8_t Simulator::ReadB(uword addr) {
283 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
284 return *ptr;
285 }
286
287
288 void Simulator::WriteB(uword addr, uint8_t value) {
289 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
290 *ptr = value;
291 }
292
293
182 // Unsupported instructions use Format to print an error and stop execution. 294 // Unsupported instructions use Format to print an error and stop execution.
183 void Simulator::Format(Instr* instr, const char* format) { 295 void Simulator::Format(Instr* instr, const char* format) {
184 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", 296 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n",
185 instr, 297 instr,
186 format); 298 format);
187 UNIMPLEMENTED(); 299 UNIMPLEMENTED();
188 } 300 }
189 301
190 302
191 // Calculate and set the Negative and Zero flags. 303 // Calculate and set the Negative and Zero flags.
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } else if (instr->IsSystemOp()) { 535 } else if (instr->IsSystemOp()) {
424 DecodeSystem(instr); 536 DecodeSystem(instr);
425 } else if (instr->IsUnconditionalBranchRegOp()) { 537 } else if (instr->IsUnconditionalBranchRegOp()) {
426 DecodeUnconditionalBranchReg(instr); 538 DecodeUnconditionalBranchReg(instr);
427 } else { 539 } else {
428 UnimplementedInstruction(instr); 540 UnimplementedInstruction(instr);
429 } 541 }
430 } 542 }
431 543
432 544
545 void Simulator::DecodeLoadStoreReg(Instr* instr) {
546 // TODO(zra): SIMD loads and stores have bit 26 (V) set.
547 // (bit 25 is never set for loads and stores).
548 if (instr->Bits(25, 2) != 0) {
549 UnimplementedInstruction(instr);
550 return;
551 }
552
553 // Calculate the address.
554 const Register rn = instr->RnField();
555 const Register rt = instr->RtField();
556 const int64_t rn_val = get_register(rn, R31IsSP);
557 const uint32_t size = instr->SzField();
558 uword address = 0;
559 uword wb_address = 0;
560 bool wb = false;
561 if (instr->Bit(24) == 1) {
562 // addr = rn + scaled unsigned 12-bit immediate offset.
563 const uint32_t imm12 = static_cast<uint32_t>(instr->Imm12Field());
564 const uint32_t offset = imm12 << size;
565 address = rn_val + offset;
566 } else if (instr->Bit(10) == 1) {
567 // addr = rn + signed 9-bit immediate offset.
568 wb = true;
569 const int64_t offset = static_cast<int64_t>(instr->SImm9Field());
570 if (instr->Bit(11) == 1) {
571 // Pre-index.
572 address = rn_val + offset;
573 wb_address = address;
574 } else {
575 // Post-index.
576 address = rn_val;
577 wb_address = rn_val + offset;
578 }
579 } else if (instr->Bits(10, 2) == 2) {
580 // addr = rn + (rm EXT optionally scaled by operand instruction size).
581 const Register rm = instr->RmField();
582 const Extend ext = instr->ExtendTypeField();
583 const uint8_t scale =
584 (ext == UXTX) && (instr->Bit(12) == 1) ? size : 0;
585 const int64_t rm_val = get_register(rm, R31IsZR);
586 const int64_t offset = ExtendOperand(kXRegSizeInBits, rm_val, ext, scale);
587 address = rn_val + offset;
588 } else {
589 UnimplementedInstruction(instr);
590 }
591
592 // Check the address.
593 if (IsIllegalAddress(address)) {
594 HandleIllegalAccess(address, instr);
595 return;
596 }
597
598 // Do access.
599 if (instr->Bits(22, 2) == 0) {
600 // Format(instr, "str'sz 'rt, 'memop");
601 int32_t rt_val32 = get_wregister(rt, R31IsZR);
602 switch (size) {
603 case 0: {
604 uint8_t val = static_cast<uint8_t>(rt_val32);
605 WriteB(address, val);
606 break;
607 }
608 case 1: {
609 uint16_t val = static_cast<uint16_t>(rt_val32);
610 WriteH(address, val, instr);
611 break;
612 }
613 case 2: {
614 uint32_t val = static_cast<uint32_t>(rt_val32);
615 WriteW(address, val, instr);
616 break;
617 }
618 case 3: {
619 int64_t val = get_register(rt, R31IsZR);
620 WriteX(address, val, instr);
621 break;
622 }
623 default:
624 UNREACHABLE();
625 break;
626 }
627 } else {
628 // Format(instr, "ldr'sz 'rt, 'memop");
629 // Undefined case.
630 if ((size == 3) && (instr->Bits(22, 0) == 3)) {
631 UnimplementedInstruction(instr);
632 return;
633 }
634
635 // Read the value.
636 const bool signd = instr->Bit(23) == 1;
637 // Write the W register for signed values when size < 2.
638 // Write the W register for unsigned values when size == 2.
639 const bool use_w =
640 (signd && (instr->Bit(22) == 1)) || (!signd && (size == 2));
641 int64_t val = 0; // Sign extend into an int64_t.
642 switch (size) {
643 case 0: {
644 if (signd) {
645 val = static_cast<int64_t>(ReadB(address));
646 } else {
647 val = static_cast<int64_t>(ReadBU(address));
648 }
649 break;
650 }
651 case 1: {
652 if (signd) {
653 val = static_cast<int64_t>(ReadH(address, instr));
654 } else {
655 val = static_cast<int64_t>(ReadHU(address, instr));
656 }
657 break;
658 }
659 case 2: {
660 if (signd) {
661 val = static_cast<int64_t>(ReadW(address, instr));
662 } else {
663 val = static_cast<int64_t>(ReadWU(address, instr));
664 }
665 break;
666 }
667 case 3:
668 val = ReadX(address, instr);
669 break;
670 default:
671 UNREACHABLE();
672 break;
673 }
674
675 // Write to register.
676 if (use_w) {
677 set_wregister(rt, static_cast<int32_t>(val), R31IsZR);
678 } else {
679 set_register(rt, val, R31IsZR);
680 }
681 }
682
683 // Do writeback.
684 if (wb) {
685 set_register(rn, wb_address, R31IsSP);
686 }
687 }
688
689
433 void Simulator::DecodeLoadStore(Instr* instr) { 690 void Simulator::DecodeLoadStore(Instr* instr) {
434 UnimplementedInstruction(instr); 691 if (instr->IsLoadStoreRegOp()) {
692 DecodeLoadStoreReg(instr);
693 } else {
694 UnimplementedInstruction(instr);
695 }
435 } 696 }
436 697
437 698
438 int64_t Simulator::ShiftOperand(uint8_t reg_size, 699 int64_t Simulator::ShiftOperand(uint8_t reg_size,
439 int64_t value, 700 int64_t value,
440 Shift shift_type, 701 Shift shift_type,
441 uint8_t amount) { 702 uint8_t amount) {
442 if (amount == 0) { 703 if (amount == 0) {
443 return value; 704 return value;
444 } 705 }
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 } 907 }
647 } 908 }
648 909
649 910
650 int64_t Simulator::Call(int64_t entry, 911 int64_t Simulator::Call(int64_t entry,
651 int64_t parameter0, 912 int64_t parameter0,
652 int64_t parameter1, 913 int64_t parameter1,
653 int64_t parameter2, 914 int64_t parameter2,
654 int64_t parameter3) { 915 int64_t parameter3) {
655 // Save the SP register before the call so we can restore it. 916 // Save the SP register before the call so we can restore it.
656 int32_t sp_before_call = get_register(SP, R31IsSP); 917 intptr_t sp_before_call = get_register(R31, R31IsSP);
657 918
658 // Setup parameters. 919 // Setup parameters.
659 set_register(R0, parameter0); 920 set_register(R0, parameter0);
660 set_register(R1, parameter1); 921 set_register(R1, parameter1);
661 set_register(R2, parameter2); 922 set_register(R2, parameter2);
662 set_register(R3, parameter3); 923 set_register(R3, parameter3);
663 924
664 // Make sure the activation frames are properly aligned. 925 // Make sure the activation frames are properly aligned.
665 int32_t stack_pointer = sp_before_call; 926 intptr_t stack_pointer = sp_before_call;
666 if (OS::ActivationFrameAlignment() > 1) { 927 if (OS::ActivationFrameAlignment() > 1) {
667 stack_pointer = 928 stack_pointer =
668 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment()); 929 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
669 } 930 }
670 set_register(SP, stack_pointer, R31IsSP); 931 set_register(R31, stack_pointer, R31IsSP);
671 932
672 // Prepare to execute the code at entry. 933 // Prepare to execute the code at entry.
673 set_pc(entry); 934 set_pc(entry);
674 // Put down marker for end of simulation. The simulator will stop simulation 935 // Put down marker for end of simulation. The simulator will stop simulation
675 // when the PC reaches this value. By saving the "end simulation" value into 936 // when the PC reaches this value. By saving the "end simulation" value into
676 // the LR the simulation stops when returning to this call point. 937 // the LR the simulation stops when returning to this call point.
677 set_register(LR, kEndSimulatingPC); 938 set_register(LR, kEndSimulatingPC);
678 939
679 // Remember the values of callee-saved registers. 940 // Remember the values of callee-saved registers.
680 int64_t r19_val = get_register(R19); 941 int64_t r19_val = get_register(R19);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 set_register(R22, r22_val); 988 set_register(R22, r22_val);
728 set_register(R23, r23_val); 989 set_register(R23, r23_val);
729 set_register(R24, r24_val); 990 set_register(R24, r24_val);
730 set_register(R25, r25_val); 991 set_register(R25, r25_val);
731 set_register(R26, r26_val); 992 set_register(R26, r26_val);
732 set_register(R27, r27_val); 993 set_register(R27, r27_val);
733 set_register(R28, r28_val); 994 set_register(R28, r28_val);
734 set_register(R29, r29_val); 995 set_register(R29, r29_val);
735 996
736 // Restore the SP register and return R1:R0. 997 // Restore the SP register and return R1:R0.
737 set_register(SP, sp_before_call, R31IsSP); 998 set_register(R31, sp_before_call, R31IsSP);
738 int64_t return_value; 999 int64_t return_value;
739 return_value = get_register(R0); 1000 return_value = get_register(R0);
740 return return_value; 1001 return return_value;
741 } 1002 }
742 1003
743 } // namespace dart 1004 } // namespace dart
744 1005
745 #endif // !defined(HOST_ARCH_ARM64) 1006 #endif // !defined(HOST_ARCH_ARM64)
746 1007
747 #endif // defined TARGET_ARCH_ARM64 1008 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« runtime/vm/constants_arm64.h ('K') | « runtime/vm/simulator_arm64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698