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 "vm/globals.h"
6#if defined(TARGET_ARCH_ARM64)
7
8#include "vm/runtime_entry.h"
9
10#include "vm/simulator.h"
11#include "vm/stub_code.h"
12
13#if !defined(DART_PRECOMPILED_RUNTIME)
14#include "vm/compiler/assembler/assembler.h"
15#endif // !defined(DART_PRECOMPILED_RUNTIME)
16
17namespace dart {
18
19#define __ assembler->
20
21uword RuntimeEntry::GetEntryPoint() const {
22 // Compute the effective address. When running under the simulator,
23 // this is a redirection address that forces the simulator to call
24 // into the runtime system.
25 uword entry = reinterpret_cast<uword>(function());
26#if defined(USING_SIMULATOR)
27 // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
28 // in registers (maximum 2 double arguments for leaf float runtime calls).
29 ASSERT(argument_count() >= 0);
30 ASSERT(!is_leaf() || (!is_float() && (argument_count() <= 4)) ||
31 (argument_count() <= 2));
32 Simulator::CallKind call_kind =
33 is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
34 : Simulator::kLeafRuntimeCall)
35 : Simulator::kRuntimeCall;
36 entry =
37 Simulator::RedirectExternalReference(entry, call_kind, argument_count());
38#endif
39 return entry;
40}
41
42#if !defined(DART_PRECOMPILED_RUNTIME)
43// Generate code to call into the stub which will call the runtime
44// function. Input for the stub is as follows:
45// SP : points to the arguments and return value array.
46// R5 : address of the runtime function to call.
47// R4 : number of arguments to the call.
48void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
49 compiler::Assembler* assembler,
50 intptr_t argument_count) {
51 if (runtime_entry->is_leaf()) {
52 ASSERT(argument_count == runtime_entry->argument_count());
53 // Since we are entering C++ code, we must restore the C stack pointer from
54 // the stack limit to an aligned value nearer to the top of the stack.
55 // We cache the Dart stack pointer and the stack limit in callee-saved
56 // registers, then align and call, restoring CSP and SP on return from the
57 // call.
58 // This sequence may occur in an intrinsic, so don't use registers an
59 // intrinsic must preserve.
60 COMPILE_ASSERT(R23 != CODE_REG);
61 COMPILE_ASSERT(R25 != CODE_REG);
62 COMPILE_ASSERT(R23 != ARGS_DESC_REG);
63 COMPILE_ASSERT(R25 != ARGS_DESC_REG);
64 __ mov(R23, CSP);
65 __ mov(R25, SP);
66 __ ReserveAlignedFrameSpace(0);
67 __ mov(CSP, SP);
68 __ ldr(TMP,
69 compiler::Address(THR, Thread::OffsetFromThread(runtime_entry)));
70 __ str(TMP, compiler::Address(THR, Thread::vm_tag_offset()));
71 __ blr(TMP);
72 __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
73 __ str(TMP, compiler::Address(THR, Thread::vm_tag_offset()));
74 __ mov(SP, R25);
75 __ mov(CSP, R23);
76 ASSERT((kAbiPreservedCpuRegs & (1 << THR)) != 0);
77 ASSERT((kAbiPreservedCpuRegs & (1 << PP)) != 0);
78 } else {
79 // Argument count is not checked here, but in the runtime entry for a more
80 // informative error message.
81 __ ldr(R5, compiler::Address(THR, Thread::OffsetFromThread(runtime_entry)));
82 __ LoadImmediate(R4, argument_count);
83 __ BranchLinkToRuntime();
84 }
85}
86#endif // !defined(DART_PRECOMPILED_RUNTIME)
87
88} // namespace dart
89
90#endif // defined TARGET_ARCH_ARM64
91