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

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

Issue 221133002: Begins work on ARM64, first assembler test. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: adds files 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
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/snapshot_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include <math.h> // for isnan.
6 #include <setjmp.h>
7 #include <stdlib.h>
8
9 #include "vm/globals.h"
10 #if defined(TARGET_ARCH_ARM64)
11
12 // Only build the simulator if not compiling for real ARM hardware.
13 #if !defined(HOST_ARCH_ARM64)
14
15 #include "vm/simulator.h"
16
17 #include "vm/assembler.h"
18 #include "vm/constants_arm64.h"
19 #include "vm/cpu.h"
20 #include "vm/disassembler.h"
21 #include "vm/native_arguments.h"
22 #include "vm/stack_frame.h"
23 #include "vm/thread.h"
24
25 namespace dart {
26
27 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution.");
28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
29
30
31 // This macro provides a platform independent use of sscanf. The reason for
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
34 // Library does not provide vsscanf.
35 #define SScanF sscanf // NOLINT
36
37
38 Simulator::Simulator() {
39 // Setup simulator support first. Some of this information is needed to
40 // setup the architecture state.
41 // We allocate the stack here, the size is computed as the sum of
42 // the size specified by the user and the buffer space needed for
43 // handling stack overflow exceptions. To be safe in potential
44 // stack underflows we also add some underflow buffer space.
45 stack_ = new char[(Isolate::GetSpecifiedStackSize() +
46 Isolate::kStackSizeBuffer +
47 kSimulatorStackUnderflowSize)];
48 pc_modified_ = false;
49 icount_ = 0;
50 break_pc_ = NULL;
51 break_instr_ = 0;
52 top_exit_frame_info_ = 0;
53
54 // Setup architecture state.
55 // All registers are initialized to zero to start with.
56 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
57 registers_[i] = 0;
58 }
59 n_flag_ = false;
60 z_flag_ = false;
61 c_flag_ = false;
62 v_flag_ = false;
63
64 // The sp is initialized to point to the bottom (high address) of the
65 // allocated stack area.
66 registers_[SP] = StackTop();
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.
69 registers_[LR] = kBadLR;
70 pc_ = kBadLR;
71 }
72
73
74 Simulator::~Simulator() {
75 delete[] stack_;
76 Isolate* isolate = Isolate::Current();
77 if (isolate != NULL) {
78 isolate->set_simulator(NULL);
79 }
80 }
81
82
83 // Get the active Simulator for the current isolate.
84 Simulator* Simulator::Current() {
85 Simulator* simulator = Isolate::Current()->simulator();
86 if (simulator == NULL) {
87 simulator = new Simulator();
88 Isolate::Current()->set_simulator(simulator);
89 }
90 return simulator;
91 }
92
93
94 // Sets the register in the architecture state.
95 void Simulator::set_register(Register reg, int64_t value, R31Type r31t) {
96 // register is in range, and if it is R31, a mode is specified.
97 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
98 ASSERT((reg != R31) || (r31t != R31IsUndef));
99 if ((reg != R31) || (r31t != R31IsZR)) {
100 registers_[reg] = value;
101 }
102 }
103
104
105 // Get the register from the architecture state.
106 int64_t Simulator::get_register(Register reg, R31Type r31t) const {
107 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
108 ASSERT((reg != R31) || (r31t != R31IsUndef));
109 if ((reg == R31) && (r31t == R31IsZR)) {
110 return 0;
111 } else {
112 return registers_[reg];
113 }
114 }
115
116
117 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) {
118 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
119 ASSERT((reg != R31) || (r31t != R31IsUndef));
120 // When setting in W mode, clear the high bits.
121 if ((reg != R31) || (r31t != R31IsZR)) {
122 registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0);
123 }
124 }
125
126
127 // Get the register from the architecture state.
128 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const {
129 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
130 ASSERT((reg != R31) || (r31t != R31IsUndef));
131 if ((reg == R31) && (r31t == R31IsZR)) {
132 return 0;
133 } else {
134 return registers_[reg];
135 }
136 }
137
138
139 // Raw access to the PC register.
140 void Simulator::set_pc(int64_t value) {
141 pc_modified_ = true;
142 pc_ = value;
143 }
144
145
146 // Raw access to the PC register without the special adjustment when reading.
147 int64_t Simulator::get_pc() const {
148 return pc_;
149 }
150
151
152 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
153 uword fault_pc = get_pc();
154 // TODO(zra): drop into debugger.
155 char buffer[128];
156 snprintf(buffer, sizeof(buffer),
157 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n",
158 addr, fault_pc);
159 // The debugger will return control in non-interactive mode.
160 FATAL("Cannot continue execution after illegal memory access.");
161 }
162
163
164 void Simulator::UnimplementedInstruction(Instr* instr) {
165 char buffer[64];
166 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
167 // TODO(zra): drop into debugger.
168 FATAL("Cannot continue execution after unimplemented instruction.");
169 }
170
171
172 // Returns the top of the stack area to enable checking for stack pointer
173 // validity.
174 uword Simulator::StackTop() const {
175 // To be safe in potential stack underflows we leave some buffer above and
176 // set the stack top.
177 return reinterpret_cast<uword>(stack_) +
178 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
179 }
180
181
182 // Unsupported instructions use Format to print an error and stop execution.
183 void Simulator::Format(Instr* instr, const char* format) {
184 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n",
185 instr,
186 format);
187 UNIMPLEMENTED();
188 }
189
190
191 // Calculate and set the Negative and Zero flags.
192 void Simulator::SetNZFlagsW(int32_t val) {
193 n_flag_ = (val < 0);
194 z_flag_ = (val == 0);
195 }
196
197
198 // Calculate C flag value for additions.
199 bool Simulator::CarryFromW(int32_t left, int32_t right) {
200 uint32_t uleft = static_cast<uint32_t>(left);
201 uint32_t uright = static_cast<uint32_t>(right);
202 uint32_t urest = 0xffffffffU - uleft;
203
204 return (uright > urest);
205 }
206
207
208 // Calculate C flag value for subtractions.
209 bool Simulator::BorrowFromW(int32_t left, int32_t right) {
210 uint32_t uleft = static_cast<uint32_t>(left);
211 uint32_t uright = static_cast<uint32_t>(right);
212
213 return (uright > uleft);
214 }
215
216
217 // Calculate V flag value for additions and subtractions.
218 bool Simulator::OverflowFromW(int32_t alu_out,
219 int32_t left, int32_t right, bool addition) {
220 bool overflow;
221 if (addition) {
222 // operands have the same sign
223 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
224 // and operands and result have different sign
225 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
226 } else {
227 // operands have different signs
228 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
229 // and first operand and result have different signs
230 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
231 }
232 return overflow;
233 }
234
235
236 // Calculate and set the Negative and Zero flags.
237 void Simulator::SetNZFlagsX(int64_t val) {
238 n_flag_ = (val < 0);
239 z_flag_ = (val == 0);
240 }
241
242
243 // Calculate C flag value for additions.
244 bool Simulator::CarryFromX(int64_t left, int64_t right) {
245 uint64_t uleft = static_cast<uint64_t>(left);
246 uint64_t uright = static_cast<uint64_t>(right);
247 uint64_t urest = 0xffffffffffffffffULL - uleft;
248
249 return (uright > urest);
250 }
251
252
253 // Calculate C flag value for subtractions.
254 bool Simulator::BorrowFromX(int64_t left, int64_t right) {
255 uint64_t uleft = static_cast<uint64_t>(left);
256 uint64_t uright = static_cast<uint64_t>(right);
257
258 return (uright > uleft);
259 }
260
261
262 // Calculate V flag value for additions and subtractions.
263 bool Simulator::OverflowFromX(int64_t alu_out,
264 int64_t left, int64_t right, bool addition) {
265 bool overflow;
266 if (addition) {
267 // operands have the same sign
268 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
269 // and operands and result have different sign
270 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
271 } else {
272 // operands have different signs
273 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
274 // and first operand and result have different signs
275 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
276 }
277 return overflow;
278 }
279
280
281 // Set the Carry flag.
282 void Simulator::SetCFlag(bool val) {
283 c_flag_ = val;
284 }
285
286
287 // Set the oVerflow flag.
288 void Simulator::SetVFlag(bool val) {
289 v_flag_ = val;
290 }
291
292
293 void Simulator::DecodeMoveWide(Instr* instr) {
294 UnimplementedInstruction(instr);
295 }
296
297
298 void Simulator::DecodeAddSubImm(Instr* instr) {
299 switch (instr->Bit(30)) {
300 case 0: {
301 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s");
302 const Register rd = instr->RdField();
303 const Register rn = instr->RnField();
304 const uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
305 : (instr->Imm12Field());
306 if (instr->SFField()) {
307 // 64-bit add.
308 const int64_t rn_val = get_register(rn, instr->RnMode());
309 const int64_t alu_out = rn_val + imm;
310 set_register(rd, alu_out, instr->RdMode());
311 if (instr->HasS()) {
312 SetNZFlagsX(alu_out);
313 SetCFlag(CarryFromX(rn_val, imm));
314 SetVFlag(OverflowFromX(alu_out, rn_val, imm, true));
315 }
316 } else {
317 // 32-bit add.
318 const int32_t rn_val = get_wregister(rn, instr->RnMode());
319 const int32_t alu_out = rn_val + imm;
320 set_wregister(rd, alu_out, instr->RdMode());
321 if (instr->HasS()) {
322 SetNZFlagsW(alu_out);
323 SetCFlag(CarryFromW(rn_val, imm));
324 SetVFlag(OverflowFromW(alu_out, rn_val, imm, true));
325 }
326 }
327 break;
328 }
329 default:
330 UnimplementedInstruction(instr);
331 break;
332 }
333 }
334
335 void Simulator::DecodeDPImmediate(Instr* instr) {
336 if (instr->IsMoveWideOp()) {
337 DecodeMoveWide(instr);
338 } else if (instr->IsAddSubImmOp()) {
339 DecodeAddSubImm(instr);
340 } else {
341 UnimplementedInstruction(instr);
342 }
343 }
344
345
346 void Simulator::DecodeExceptionGen(Instr* instr) {
347 UnimplementedInstruction(instr);
348 }
349
350
351 void Simulator::DecodeSystem(Instr* instr) {
352 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) &&
353 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
354 (instr->Bit(21) == 0)) {
355 if (instr->Bits(8, 4) == 0) {
356 // Format(instr, "nop");
357 } else {
358 UnimplementedInstruction(instr);
359 }
360 } else {
361 UnimplementedInstruction(instr);
362 }
363 }
364
365
366 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
367 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) &&
368 (instr->Bits(16, 5) == 0x1f)) {
369 switch (instr->Bits(21, 4)) {
370 case 2: {
371 // Format(instr, "ret 'rn");
372 const Register rn = instr->RnField();
373 const int64_t rn_val = get_register(rn, instr->RnMode());
374 set_pc(rn_val);
375 break;
376 }
377 default:
378 UnimplementedInstruction(instr);
379 break;
380 }
381 } else {
382 UnimplementedInstruction(instr);
383 }
384 }
385
386
387 void Simulator::DecodeCompareBranch(Instr* instr) {
388 if (instr->IsExceptionGenOp()) {
389 DecodeExceptionGen(instr);
390 } else if (instr->IsSystemOp()) {
391 DecodeSystem(instr);
392 } else if (instr->IsUnconditionalBranchRegOp()) {
393 DecodeUnconditionalBranchReg(instr);
394 } else {
395 UnimplementedInstruction(instr);
396 }
397 }
398
399
400 void Simulator::DecodeLoadStore(Instr* instr) {
401 UnimplementedInstruction(instr);
402 }
403
404
405 int64_t Simulator::ShiftOperand(uint8_t reg_size,
406 int64_t value,
407 Shift shift_type,
408 uint8_t amount) {
409 if (amount == 0) {
410 return value;
411 }
412 int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask;
413 switch (shift_type) {
414 case LSL:
415 return (value << amount) & mask;
416 case LSR:
417 return static_cast<uint64_t>(value) >> amount;
418 case ASR: {
419 // Shift used to restore the sign.
420 uint8_t s_shift = kXRegSizeInBits - reg_size;
421 // Value with its sign restored.
422 int64_t s_value = (value << s_shift) >> s_shift;
423 return (s_value >> amount) & mask;
424 }
425 case ROR: {
426 if (reg_size == kWRegSizeInBits) {
427 value &= kWRegMask;
428 }
429 return (static_cast<uint64_t>(value) >> amount) |
430 ((value & ((1L << amount) - 1L)) << (reg_size - amount));
431 }
432 default:
433 UNIMPLEMENTED();
434 return 0;
435 }
436 }
437
438
439 int64_t Simulator::ExtendOperand(uint8_t reg_size,
440 int64_t value,
441 Extend extend_type,
442 uint8_t amount) {
443 switch (extend_type) {
444 case UXTB:
445 value &= 0xff;
446 break;
447 case UXTH:
448 value &= 0xffff;
449 break;
450 case UXTW:
451 value &= 0xffffffff;
452 break;
453 case SXTB:
454 value = (value << 56) >> 56;
455 break;
456 case SXTH:
457 value = (value << 48) >> 48;
458 break;
459 case SXTW:
460 value = (value << 32) >> 32;
461 break;
462 case UXTX:
463 case SXTX:
464 break;
465 default:
466 UNREACHABLE();
467 }
468 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask;
469 return (value << amount) & mask;
470 }
471
472
473 int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) {
474 const Register rm = instr->RmField();
475 const int64_t rm_val = get_register(rm, R31IsZR);
476 const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits;
477 if (instr->IsShift()) {
478 const Shift shift_type = instr->ShiftTypeField();
479 const uint8_t shift_amount = instr->Imm6Field();
480 return ShiftOperand(size, rm_val, shift_type, shift_amount);
481 } else {
482 ASSERT(instr->IsExtend());
483 const Extend extend_type = instr->ExtendTypeField();
484 const uint8_t shift_amount = instr->Imm3Field();
485 return ExtendOperand(size, rm_val, extend_type, shift_amount);
486 }
487 UNREACHABLE();
488 return -1;
489 }
490
491
492 void Simulator::DecodeAddSubShiftExt(Instr* instr) {
493 switch (instr->Bit(30)) {
494 case 0: {
495 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op");
496 const Register rd = instr->RdField();
497 const Register rn = instr->RnField();
498 const int64_t rm_val = DecodeShiftExtendOperand(instr);
499 if (instr->SFField()) {
500 // 64-bit add.
501 const int64_t rn_val = get_register(rn, instr->RnMode());
502 const int64_t alu_out = rn_val + rm_val;
503 set_register(rd, alu_out, instr->RdMode());
504 if (instr->HasS()) {
505 SetNZFlagsX(alu_out);
506 SetCFlag(CarryFromX(rn_val, rm_val));
507 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, true));
508 }
509 } else {
510 // 32-bit add.
511 const int32_t rn_val = get_wregister(rn, instr->RnMode());
512 const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask);
513 const int32_t alu_out = rn_val + rm_val32;
514 set_wregister(rd, alu_out, instr->RdMode());
515 if (instr->HasS()) {
516 SetNZFlagsW(alu_out);
517 SetCFlag(CarryFromW(rn_val, rm_val32));
518 SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, true));
519 }
520 }
521 break;
522 }
523 default:
524 UnimplementedInstruction(instr);
525 break;
526 }
527 }
528
529
530 void Simulator::DecodeDPRegister(Instr* instr) {
531 if (instr->IsAddSubShiftExtOp()) {
532 DecodeAddSubShiftExt(instr);
533 } else {
534 UnimplementedInstruction(instr);
535 }
536 }
537
538
539 void Simulator::DecodeDPSimd1(Instr* instr) {
540 UnimplementedInstruction(instr);
541 }
542
543
544 void Simulator::DecodeDPSimd2(Instr* instr) {
545 UnimplementedInstruction(instr);
546 }
547
548
549 // Executes the current instruction.
550 void Simulator::InstructionDecode(Instr* instr) {
551 pc_modified_ = false;
552 if (FLAG_trace_sim) {
553 const uword start = reinterpret_cast<uword>(instr);
554 const uword end = start + Instr::kInstrSize;
555 Disassembler::Disassemble(start, end);
556 }
557
558 if (instr->IsDPImmediateOp()) {
559 DecodeDPImmediate(instr);
560 } else if (instr->IsCompareBranchOp()) {
561 DecodeCompareBranch(instr);
562 } else if (instr->IsLoadStoreOp()) {
563 DecodeLoadStore(instr);
564 } else if (instr->IsDPRegisterOp()) {
565 DecodeDPRegister(instr);
566 } else if (instr->IsDPSimd1Op()) {
567 DecodeDPSimd1(instr);
568 } else {
569 ASSERT(instr->IsDPSimd2Op());
570 DecodeDPSimd2(instr);
571 }
572
573 if (!pc_modified_) {
574 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize);
575 }
576 }
577
578
579 void Simulator::Execute() {
580 // Get the PC to simulate. Cannot use the accessor here as we need the
581 // raw PC value and not the one used as input to arithmetic instructions.
582 uword program_counter = get_pc();
583
584 if (FLAG_stop_sim_at == 0) {
585 // Fast version of the dispatch loop without checking whether the simulator
586 // should be stopping at a particular executed instruction.
587 while (program_counter != kEndSimulatingPC) {
588 Instr* instr = reinterpret_cast<Instr*>(program_counter);
589 icount_++;
590 if (IsIllegalAddress(program_counter)) {
591 HandleIllegalAccess(program_counter, instr);
592 } else {
593 InstructionDecode(instr);
594 }
595 program_counter = get_pc();
596 }
597 } else {
598 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
599 // we reach the particular instruction count.
600 while (program_counter != kEndSimulatingPC) {
601 Instr* instr = reinterpret_cast<Instr*>(program_counter);
602 icount_++;
603 if (icount_ == FLAG_stop_sim_at) {
604 // TODO(zra): Add a debugger.
605 UNIMPLEMENTED();
606 } else if (IsIllegalAddress(program_counter)) {
607 HandleIllegalAccess(program_counter, instr);
608 } else {
609 InstructionDecode(instr);
610 }
611 program_counter = get_pc();
612 }
613 }
614 }
615
616
617 int64_t Simulator::Call(int64_t entry,
618 int64_t parameter0,
619 int64_t parameter1,
620 int64_t parameter2,
621 int64_t parameter3) {
622 // Save the SP register before the call so we can restore it.
623 int32_t sp_before_call = get_register(SP, R31IsSP);
624
625 // Setup parameters.
626 set_register(R0, parameter0);
627 set_register(R1, parameter1);
628 set_register(R2, parameter2);
629 set_register(R3, parameter3);
630
631 // Make sure the activation frames are properly aligned.
632 int32_t stack_pointer = sp_before_call;
633 if (OS::ActivationFrameAlignment() > 1) {
634 stack_pointer =
635 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
636 }
637 set_register(SP, stack_pointer, R31IsSP);
638
639 // Prepare to execute the code at entry.
640 set_pc(entry);
641 // Put down marker for end of simulation. The simulator will stop simulation
642 // when the PC reaches this value. By saving the "end simulation" value into
643 // the LR the simulation stops when returning to this call point.
644 set_register(LR, kEndSimulatingPC);
645
646 // Remember the values of callee-saved registers.
647 int64_t r19_val = get_register(R19);
648 int64_t r20_val = get_register(R20);
649 int64_t r21_val = get_register(R21);
650 int64_t r22_val = get_register(R22);
651 int64_t r23_val = get_register(R23);
652 int64_t r24_val = get_register(R24);
653 int64_t r25_val = get_register(R25);
654 int64_t r26_val = get_register(R26);
655 int64_t r27_val = get_register(R27);
656 int64_t r28_val = get_register(R28);
657 int64_t r29_val = get_register(R29);
658
659 // Setup the callee-saved registers with a known value. To be able to check
660 // that they are preserved properly across dart execution.
661 int64_t callee_saved_value = icount_;
662 set_register(R19, callee_saved_value);
663 set_register(R20, callee_saved_value);
664 set_register(R21, callee_saved_value);
665 set_register(R22, callee_saved_value);
666 set_register(R23, callee_saved_value);
667 set_register(R24, callee_saved_value);
668 set_register(R25, callee_saved_value);
669 set_register(R26, callee_saved_value);
670 set_register(R27, callee_saved_value);
671 set_register(R28, callee_saved_value);
672 set_register(R29, callee_saved_value);
673
674 // Start the simulation
675 Execute();
676
677 // Check that the callee-saved registers have been preserved.
678 ASSERT(callee_saved_value == get_register(R19));
679 ASSERT(callee_saved_value == get_register(R20));
680 ASSERT(callee_saved_value == get_register(R21));
681 ASSERT(callee_saved_value == get_register(R22));
682 ASSERT(callee_saved_value == get_register(R23));
683 ASSERT(callee_saved_value == get_register(R24));
684 ASSERT(callee_saved_value == get_register(R25));
685 ASSERT(callee_saved_value == get_register(R26));
686 ASSERT(callee_saved_value == get_register(R27));
687 ASSERT(callee_saved_value == get_register(R28));
688 ASSERT(callee_saved_value == get_register(R29));
689
690 // Restore callee-saved registers with the original value.
691 set_register(R19, r19_val);
692 set_register(R20, r20_val);
693 set_register(R21, r21_val);
694 set_register(R22, r22_val);
695 set_register(R23, r23_val);
696 set_register(R24, r24_val);
697 set_register(R25, r25_val);
698 set_register(R26, r26_val);
699 set_register(R27, r27_val);
700 set_register(R28, r28_val);
701 set_register(R29, r29_val);
702
703 // Restore the SP register and return R1:R0.
704 set_register(SP, sp_before_call, R31IsSP);
705 int64_t return_value;
706 return_value = get_register(R0);
707 return return_value;
708 }
709
710 } // namespace dart
711
712 #endif // !defined(HOST_ARCH_ARM64)
713
714 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/snapshot_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698