Begins work on ARM64, first assembler test.

Most new code is in constants_arm64.h and
{assembler,disassembler,simulator}_arm64.{h,cc}

The rest of the CL just #def's out tests, modifies status files,
and adds UNIMPLEMENTED functions, etc.

R=regis@google.com

Review URL: https://codereview.chromium.org//221133002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@34654 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
zra@google.com 2014-04-02 17:39:32 +00:00
parent 7a0660513f
commit 2fe51715e5
81 changed files with 5644 additions and 16 deletions

View file

@ -264,6 +264,9 @@ matcher/test/*_minified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS
[ $arch == simarm && $checked ]
watcher/test/directory_watcher/linux_test: Skip # Issue 16118
[ $arch == simarm64 ]
*: Skip
# Skip serialization test that explicitly has no library declaration in the
# test on Dartium, which requires all tests to have a library.
[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]

View file

@ -67,6 +67,14 @@
]}],
],
},
# Added by Dart.
'Dart_simarm64_Base': {
'defines': [
'NSS_X86_OR_X64',
'NSS_X64',
'NSS_USE_64',
],
},
},
'conditions': [
['OS=="win"', {

View file

@ -196,6 +196,7 @@ typedef double fpu_register_t;
#if !defined(TARGET_ARCH_ARM)
#if !defined(TARGET_ARCH_X64)
#if !defined(TARGET_ARCH_IA32)
#if !defined(TARGET_ARCH_ARM64)
// No target architecture specified pick the one matching the host architecture.
#if defined(HOST_ARCH_MIPS)
#define TARGET_ARCH_MIPS 1
@ -205,6 +206,8 @@ typedef double fpu_register_t;
#define TARGET_ARCH_X64 1
#elif defined(HOST_ARCH_IA32)
#define TARGET_ARCH_IA32 1
#elif defined(HOST_ARCH_ARM64)
#define TARGET_ARCH_ARM64 1
#else
#error Automatic target architecture detection failed.
#endif
@ -212,10 +215,12 @@ typedef double fpu_register_t;
#endif
#endif
#endif
#endif
// Verify that host and target architectures match, we cannot
// have a 64 bit Dart VM generating 32 bit code or vice-versa.
#if defined(TARGET_ARCH_X64)
#if defined(TARGET_ARCH_X64) || \
defined(TARGET_ARCH_ARM64)
#if !defined(ARCH_IS_64_BIT)
#error Mismatched Host/Target architectures.
#endif

View file

@ -75,6 +75,9 @@ cc/StaticNonNullSumCallCodegen: Crash, Pass # dartbug.com/17440
[ $arch == mips && $mode == debug ]
cc/FindCodeObject: Skip # Takes more than 8 minutes. dartbug.com/17440.
[ $arch == simarm64 ]
dart/*: Skip
[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
dart/mirrored_compilation_error_test: Skip # Can't pass needed VM flag

View file

@ -13,7 +13,9 @@
namespace dart {
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
#if defined(TARGET_ARCH_ARM) || \
defined(TARGET_ARCH_ARM64) || \
defined(TARGET_ARCH_MIPS)
DECLARE_FLAG(bool, use_far_branches);
#endif
@ -217,6 +219,8 @@ class AssemblerBuffer : public ValueObject {
#include "vm/assembler_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/assembler_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/assembler_arm64.h"
#elif defined(TARGET_ARCH_MIPS)
#include "vm/assembler_mips.h"
#else

View file

@ -0,0 +1,78 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/longjump.h"
#include "vm/runtime_entry.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
// An extra check since we are assuming the existence of /proc/cpuinfo below.
#if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID)
#error ARM64 cross-compile only supported on Linux
#endif
namespace dart {
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
ASSERT(Utils::IsAligned(data, 4));
ASSERT(Utils::IsAligned(length, 4));
const uword end = data + length;
while (data < end) {
*reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction;
data += 4;
}
}
void Assembler::Stop(const char* message) {
UNIMPLEMENTED();
}
void Assembler::Emit(int32_t value) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
buffer_.Emit<int32_t>(value);
}
static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31",
};
const char* Assembler::RegisterName(Register reg) {
ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
return cpu_reg_names[reg];
}
static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
};
const char* Assembler::FpuRegisterName(FpuRegister reg) {
ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
return fpu_reg_names[reg];
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -0,0 +1,357 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_ASSEMBLER_ARM64_H_
#define VM_ASSEMBLER_ARM64_H_
#ifndef VM_ASSEMBLER_H_
#error Do not include assembler_arm64.h directly; use assembler.h instead.
#endif
#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/constants_arm64.h"
#include "vm/object.h"
#include "vm/simulator.h"
namespace dart {
// Forward declarations.
class RuntimeEntry;
// TODO(zra): Label, Address, and FieldAddress are copied from ARM,
// they must be adapted to ARM64.
class Label : public ValueObject {
public:
Label() : position_(0) { }
~Label() {
// Assert if label is being destroyed with unresolved branches pending.
ASSERT(!IsLinked());
}
// Returns the position for bound and linked labels. Cannot be used
// for unused labels.
intptr_t Position() const {
ASSERT(!IsUnused());
return IsBound() ? -position_ - kWordSize : position_ - kWordSize;
}
bool IsBound() const { return position_ < 0; }
bool IsUnused() const { return position_ == 0; }
bool IsLinked() const { return position_ > 0; }
private:
intptr_t position_;
void Reinitialize() {
position_ = 0;
}
void BindTo(intptr_t position) {
ASSERT(!IsBound());
position_ = -position - kWordSize;
ASSERT(IsBound());
}
void LinkTo(intptr_t position) {
ASSERT(!IsBound());
position_ = position + kWordSize;
ASSERT(IsLinked());
}
friend class Assembler;
DISALLOW_COPY_AND_ASSIGN(Label);
};
class Address : public ValueObject {
public:
Address(const Address& other)
: ValueObject(), encoding_(other.encoding_) {
}
Address& operator=(const Address& other) {
encoding_ = other.encoding_;
return *this;
}
Address(Register rn, int32_t offset = 0) {
ASSERT(Utils::IsAbsoluteUint(12, offset));
encoding_ = -1;
}
private:
uint32_t encoding() const { return encoding_; }
uint32_t encoding_;
friend class Assembler;
};
class FieldAddress : public Address {
public:
FieldAddress(Register base, int32_t disp)
: Address(base, disp - kHeapObjectTag) { }
FieldAddress(const FieldAddress& other) : Address(other) { }
FieldAddress& operator=(const FieldAddress& other) {
Address::operator=(other);
return *this;
}
};
class Operand : public ValueObject {
public:
// Data-processing operand - Uninitialized.
Operand() : encoding_(-1), type_(Unknown) { }
// Data-processing operands - Copy constructor.
Operand(const Operand& other)
: ValueObject(), encoding_(other.encoding_), type_(other.type_) { }
explicit Operand(Register rm) {
ASSERT((rm != R31) && (rm != SP));
const Register crm = ConcreteRegister(rm);
encoding_ = (static_cast<int32_t>(crm) << kRmShift);
}
Operand(Register rm, Shift shift, int32_t imm) {
ASSERT(Utils::IsUint(6, imm));
ASSERT((rm != R31) && (rm != SP));
const Register crm = ConcreteRegister(rm);
encoding_ =
(imm << kImm6Shift) |
(static_cast<int32_t>(crm) << kRmShift) |
(static_cast<int32_t>(shift) << kShiftTypeShift);
type_ = Shifted;
}
Operand(Register rm, Extend extend, int32_t imm) {
ASSERT(Utils::IsUint(3, imm));
ASSERT((rm != R31) && (rm != SP));
const Register crm = ConcreteRegister(rm);
encoding_ =
B21 |
(static_cast<int32_t>(crm) << kRmShift) |
(static_cast<int32_t>(extend) << kExtendTypeShift) |
((imm & 0x7) << kImm3Shift);
type_ = Extended;
}
explicit Operand(int32_t imm) {
if (Utils::IsUint(12, imm)) {
encoding_ = imm << kImm12Shift;
} else {
// imm only has bits in [12, 24) set.
ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12)));
encoding_ = B22 | ((imm >> 12) << kImm12Shift);
}
type_ = Immediate;
}
// TODO(zra): Add bitfield immediate operand
// Operand(int32_t n, int32_t imms, int32_t immr);
enum OperandType {
Shifted,
Extended,
Immediate,
BitfieldImm,
Unknown,
};
private:
uint32_t encoding() const {
return encoding_;
}
OperandType type() const {
return type_;
}
uint32_t encoding_;
OperandType type_;
friend class Assembler;
};
class Assembler : public ValueObject {
public:
explicit Assembler(bool use_far_branches = false)
: buffer_(),
object_pool_(GrowableObjectArray::Handle()),
prologue_offset_(-1),
use_far_branches_(use_far_branches),
comments_() { }
~Assembler() { }
void PopRegister(Register r) {
UNIMPLEMENTED();
}
void Drop(intptr_t stack_elements) {
UNIMPLEMENTED();
}
void Bind(Label* label) {
UNIMPLEMENTED();
}
// Misc. functionality
intptr_t CodeSize() const { return buffer_.Size(); }
intptr_t prologue_offset() const { return prologue_offset_; }
// Count the fixups that produce a pointer offset, without processing
// the fixups. On ARM64 there are no pointers in code.
intptr_t CountPointerOffsets() const { return 0; }
const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
ASSERT(buffer_.pointer_offsets().length() == 0); // No pointers in code.
return buffer_.pointer_offsets();
}
const GrowableObjectArray& object_pool() const { return object_pool_; }
bool use_far_branches() const {
return FLAG_use_far_branches || use_far_branches_;
}
void set_use_far_branches(bool b) {
ASSERT(buffer_.Size() == 0);
use_far_branches_ = b;
}
void FinalizeInstructions(const MemoryRegion& region) {
buffer_.FinalizeInstructions(region);
}
// Debugging and bringup support.
void Stop(const char* message);
void Unimplemented(const char* message);
void Untested(const char* message);
void Unreachable(const char* message);
static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
const Code::Comments& GetCodeComments() const;
static const char* RegisterName(Register reg);
static const char* FpuRegisterName(FpuRegister reg);
// TODO(zra): Make sure this is right.
// Instruction pattern from entrypoint is used in Dart frame prologs
// to set up the frame and save a PC which can be used to figure out the
// RawInstruction object corresponding to the code running in the frame.
static const intptr_t kEntryPointToPcMarkerOffset = 0;
// Emit data (e.g encoded instruction or immediate) in instruction stream.
void Emit(int32_t value);
// On some other platforms, we draw a distinction between safe and unsafe
// smis.
static bool IsSafe(const Object& object) { return true; }
static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
void add(Register rd, Register rn, Operand o) {
AddSubHelper(kDoubleWord, false, false, rd, rn, o);
}
void addw(Register rd, Register rn, Operand o) {
AddSubHelper(kWord, false, false, rd, rn, o);
}
// Function return.
void ret(Register rn = R30) {
EmitUnconditionalBranchRegOp(RET, rn);
}
private:
AssemblerBuffer buffer_; // Contains position independent code.
GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
int32_t prologue_offset_;
bool use_far_branches_;
class CodeComment : public ZoneAllocated {
public:
CodeComment(intptr_t pc_offset, const String& comment)
: pc_offset_(pc_offset), comment_(comment) { }
intptr_t pc_offset() const { return pc_offset_; }
const String& comment() const { return comment_; }
private:
intptr_t pc_offset_;
const String& comment_;
DISALLOW_COPY_AND_ASSIGN(CodeComment);
};
GrowableArray<CodeComment*> comments_;
void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
Register rd, Register rn, Operand o) {
ASSERT((rd != R31) && (rn != R31));
const Register crd = ConcreteRegister(rd);
const Register crn = ConcreteRegister(rn);
if (o.type() == Operand::Immediate) {
ASSERT((rd != ZR) && (rn != ZR));
EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
} else {
if (o.type() == Operand::Shifted) {
ASSERT((rd != SP) && (rn != SP));
EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
} else {
ASSERT(o.type() == Operand::Extended);
ASSERT((rd != SP) && (rn != ZR));
EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
}
}
}
void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn,
Operand o, OperandSize os, bool set_flags) {
ASSERT((os == kDoubleWord) || (os == kWord));
const int32_t size = (os == kDoubleWord) ? B31 : 0;
const int32_t s = set_flags ? B29 : 0;
const int32_t encoding =
op | size | s |
(static_cast<int32_t>(rd) << kRdShift) |
(static_cast<int32_t>(rn) << kRnShift) |
o.encoding();
Emit(encoding);
}
void EmitAddSubShiftExtOp(AddSubShiftExtOp op,
Register rd, Register rn, Operand o,
OperandSize os, bool set_flags) {
ASSERT((os == kDoubleWord) || (os == kWord));
const int32_t size = (os == kDoubleWord) ? B31 : 0;
const int32_t s = set_flags ? B29 : 0;
const int32_t encoding =
op | size | s |
(static_cast<int32_t>(rd) << kRdShift) |
(static_cast<int32_t>(rn) << kRnShift) |
o.encoding();
Emit(encoding);
}
void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) {
const int32_t encoding =
op | (static_cast<int32_t>(rn) << kRnShift);
Emit(encoding);
}
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(Assembler);
};
} // namespace dart
#endif // VM_ASSEMBLER_ARM64_H_

View file

@ -0,0 +1,32 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/unit_test.h"
#include "vm/virtual_memory.h"
namespace dart {
#define __ assembler->
ASSEMBLER_TEST_GENERATE(Simple, assembler) {
__ add(R0, ZR, Operand(ZR));
__ add(R0, R0, Operand(42));
__ ret();
}
ASSEMBLER_TEST_RUN(Simple, test) {
typedef int (*SimpleCode)();
EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
}
} // namespace dart
#endif // defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when test is ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/globals.h"
#include "vm/os.h"
@ -73,3 +77,5 @@ ASSEMBLER_TEST_RUN(StoreIntoObject, test) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -8,6 +8,7 @@
#include "bin/file.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/dart_api_impl.h"
#include "vm/stack_frame.h"
@ -30,6 +31,8 @@ void Benchmark::RunAll(const char* executable) {
}
}
// TODO(zra): Remove when tests are ready to enable.
#if !defined(TARGET_ARCH_ARM64)
//
// Measure compile of all functions in dart core lib classes.
@ -578,4 +581,6 @@ BENCHMARK(SimpleMessage) {
benchmark->set_score(elapsed_time);
}
#endif // !defined(TARGET_ARCH_ARM64)
} // namespace dart

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/cha.h"
#include "vm/class_finalizer.h"
@ -127,3 +131,5 @@ TEST_CASE(ClassHierarchyAnalysis) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/globals.h"
@ -280,3 +284,5 @@ TEST_CASE(StackmapGC) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/ast.h"
@ -566,3 +570,5 @@ CODEGEN_TEST_RAW_RUN(AllocateNewObjectCodegen, function) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,88 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
#if defined(TARGET_ARCH_ARM64)
#include "vm/code_patcher.h"
#include "vm/instructions.h"
#include "vm/object.h"
namespace dart {
RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
const Code& code) {
UNIMPLEMENTED();
return NULL;
}
uword CodePatcher::GetStaticCallTargetAt(uword return_address,
const Code& code) {
UNIMPLEMENTED();
return 0;
}
void CodePatcher::PatchStaticCallAt(uword return_address,
const Code& code,
uword new_target) {
UNIMPLEMENTED();
}
void CodePatcher::PatchInstanceCallAt(uword return_address,
const Code& code,
uword new_target) {
UNIMPLEMENTED();
}
int32_t CodePatcher::GetPoolOffsetAt(uword return_address) {
UNIMPLEMENTED();
return 0;
}
void CodePatcher::SetPoolOffsetAt(uword return_address, int32_t offset) {
UNIMPLEMENTED();
}
void CodePatcher::InsertCallAt(uword start, uword target) {
UNIMPLEMENTED();
}
uword CodePatcher::GetInstanceCallAt(uword return_address,
const Code& code,
ICData* ic_data) {
UNIMPLEMENTED();
return 0;
}
intptr_t CodePatcher::InstanceCallSizeInBytes() {
// The instance call instruction sequence has a variable size on ARM.
UNREACHABLE();
return 0;
}
RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
uword return_address, const Code& code, ICData* ic_data_result) {
UNIMPLEMENTED();
return NULL;
}
RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
UNIMPLEMENTED();
return NULL;
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -0,0 +1,10 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
// TODO(zra): Port these tests.
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
@ -98,3 +102,5 @@ TEST_CASE(EvalExpression) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,519 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CONSTANTS_ARM64_H_
#define VM_CONSTANTS_ARM64_H_
#include "platform/assert.h"
namespace dart {
enum Register {
kFirstFreeCpuRegister = 0,
R0 = 0,
R1 = 1,
R2 = 2,
R3 = 3,
R4 = 4,
R5 = 5,
R6 = 6,
R7 = 7,
R8 = 8,
R9 = 9,
R10 = 10,
R11 = 11,
R12 = 12,
R13 = 13,
R14 = 14,
R15 = 15,
R16 = 16,
R17 = 17,
R18 = 18,
R19 = 19,
R20 = 20,
R21 = 21,
R22 = 22,
R23 = 23,
R24 = 24,
kLastFreeCpuRegister = 24,
R25 = 25, // IP0
R26 = 26, // IP1
R27 = 27, // PP
R28 = 28, // CTX
R29 = 29, // FP
R30 = 30, // LR
R31 = 31, // ZR, SP
kNumberOfCpuRegisters = 32,
kNoRegister = -1,
// Aliases.
IP0 = R25,
IP1 = R26,
FP = R29,
LR = R30,
// Left abstract so we can avoid misuse.
SP,
ZR,
};
enum VRegister {
V0 = 0,
V1 = 1,
V2 = 2,
V3 = 3,
V4 = 4,
V5 = 5,
V6 = 6,
V7 = 7,
V8 = 8,
V9 = 9,
V10 = 10,
V11 = 11,
V12 = 12,
V13 = 13,
V14 = 14,
V15 = 15,
V16 = 16,
V17 = 17,
V18 = 18,
V19 = 19,
V20 = 20,
V21 = 21,
V22 = 22,
V23 = 24,
V24 = 24,
V25 = 25,
V26 = 26,
V27 = 27,
V28 = 28,
V29 = 29,
V30 = 30,
V31 = 31,
kNumberOfVRegisters = 32,
kNoVRegister = -1,
};
// Register alias for floating point scratch register.
const VRegister VTMP0 = V30;
const VRegister VTMP1 = V31;
// Architecture independent aliases.
typedef VRegister FpuRegister;
const FpuRegister FpuTMP = VTMP0;
const int kNumberOfFpuRegisters = kNumberOfVRegisters;
const FpuRegister kNoFpuRegister = kNoVRegister;
// Register aliases.
const Register TMP = R25; // Used as scratch register by assembler.
const Register TMP0 = R25;
const Register TMP1 = R26;
const Register CTX = R27; // Caches current context in generated code.
const Register PP = R26; // Caches object pool pointer in generated code.
const Register SPREG = R31; // Stack pointer register.
const Register FPREG = FP; // Frame pointer register.
const Register ICREG = R5; // IC data register.
// Exception object is passed in this register to the catch handlers when an
// exception is thrown.
const Register kExceptionObjectReg = R0;
// Stack trace object is passed in this register to the catch handlers when
// an exception is thrown.
const Register kStackTraceObjectReg = R1;
// Masks, sizes, etc.
const int kXRegSizeInBits = 64;
const int kWRegSizeInBits = 32;
const int64_t kXRegMask = 0xffffffffffffffffL;
const int64_t kWRegMask = 0x00000000ffffffffL;
// List of registers used in load/store multiple.
typedef uint32_t RegList;
const RegList kAllCpuRegistersList = 0xFFFF;
// C++ ABI call registers.
const RegList kAbiArgumentCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R7);
const RegList kAbiPreservedCpuRegs =
(1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) |
(1 << R23) | (1 << R24) | (1 << R25) | (1 << R26) |
(1 << R27) | (1 << R28) | (1 << R29);
const int kAbiPreservedCpuRegCount = 11;
const VRegister kAbiFirstPreservedFpuReg = V8;
const VRegister kAbiLastPreservedFpuReg = V15;
const int kAbiPreservedFpuRegCount = 8;
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
(1 << R8) | (1 << R9) | (1 << R10) | (1 << R11) |
(1 << R12) | (1 << R13) | (1 << R14) | (1 << R15) |
(1 << R16) | (1 << R17) | (1 << R18) | (1 << R19) |
(1 << R20) | (1 << R21) | (1 << R22) | (1 << R23) |
(1 << R24);
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
const int kDartVolatileCpuRegCount = 19;
const VRegister kDartFirstVolatileFpuReg = V0;
const VRegister kDartLastVolatileFpuReg = V7;
const int kDartVolatileFpuRegCount = 8;
static inline Register ConcreteRegister(Register r) {
return ((r == ZR) || (r == SP)) ? R31 : r;
}
// Values for the condition field as defined in section A3.2.
enum Condition {
kNoCondition = -1,
EQ = 0, // equal
NE = 1, // not equal
CS = 2, // carry set/unsigned higher or same
CC = 3, // carry clear/unsigned lower
MI = 4, // minus/negative
PL = 5, // plus/positive or zero
VS = 6, // overflow
VC = 7, // no overflow
HI = 8, // unsigned higher
LS = 9, // unsigned lower or same
GE = 10, // signed greater than or equal
LT = 11, // signed less than
GT = 12, // signed greater than
LE = 13, // signed less than or equal
AL = 14, // always (unconditional)
NV = 15, // special condition (refer to section C1.2.3)
kMaxCondition = 16,
};
enum Bits {
B0 = (1 << 0), B1 = (1 << 1), B2 = (1 << 2), B3 = (1 << 3),
B4 = (1 << 4), B5 = (1 << 5), B6 = (1 << 6), B7 = (1 << 7),
B8 = (1 << 8), B9 = (1 << 9), B10 = (1 << 10), B11 = (1 << 11),
B12 = (1 << 12), B13 = (1 << 13), B14 = (1 << 14), B15 = (1 << 15),
B16 = (1 << 16), B17 = (1 << 17), B18 = (1 << 18), B19 = (1 << 19),
B20 = (1 << 20), B21 = (1 << 21), B22 = (1 << 22), B23 = (1 << 23),
B24 = (1 << 24), B25 = (1 << 25), B26 = (1 << 26), B27 = (1 << 27),
B28 = (1 << 28), B29 = (1 << 29), B30 = (1 << 30), B31 = (1 << 31),
};
enum OperandSize {
kByte,
kUnsignedByte,
kHalfword,
kUnsignedHalfword,
kWord,
kUnsignedWord,
kDoubleWord,
kSWord,
kDWord,
};
// Opcodes from C3
// C3.1.
enum MainOp {
DPImmediateMask = 0x1c000000,
DPImmediateFixed = B28,
CompareBranchMask = 0x1c000000,
CompareBranchFixed = B28 | B26,
LoadStoreMask = B27 | B25,
LoadStoreFixed = B27,
DPRegisterMask = 0x0e000000,
DPRegisterFixed = B27 | B25,
DPSimd1Mask = 0x1e000000,
DPSimd1Fixed = B27 | B26 | B25,
DPSimd2Mask = 0x1e000000,
DPSimd2Fixed = B28 | DPSimd1Fixed,
};
// C3.2.3
enum ExceptionGenOp {
ExceptionGenMask = 0xff000000,
ExceptionGenFixed = CompareBranchFixed | B31 | B30,
SVC = ExceptionGenFixed | B0,
BRK = ExceptionGenFixed | B21,
HLT = ExceptionGenFixed | B22,
};
// C3.2.4
enum SystemOp {
SystemMask = 0xffc00000,
SystemFixed = CompareBranchFixed | B31 | B30 | B24,
HINT = SystemFixed | B17 | B16 | B13 | B4 | B3 | B2 | B1 | B0,
};
// C3.2.7
enum UnconditionalBranchRegOp {
UnconditionalBranchRegMask = 0xfe000000,
UnconditionalBranchRegFixed = CompareBranchFixed | B31 | B30 | B25,
BR = UnconditionalBranchRegFixed | B20 | B19 | B18 | B17 | B16,
BLR = BR | B21,
RET = BR | B22,
};
// C3.4.1
enum AddSubImmOp {
AddSubImmMask = 0x1f000000,
AddSubImmFixed = DPImmediateFixed | B24,
ADDI = AddSubImmFixed,
SUBI = AddSubImmFixed | B30,
};
// C3.4.5
enum MoveWideOp {
MoveWideMask = 0x1f800000,
MoveWideFixed = DPImmediateFixed | B25 | B23,
MOVN = MoveWideFixed,
MOVZ = MoveWideFixed | B30,
MOVK = MoveWideFixed | B30 | B29,
};
// C3.5.1
enum AddSubShiftExtOp {
AddSubShiftExtMask = 0x1f200000,
AddSubShiftExtFixed = DPRegisterFixed | B24,
ADD = AddSubShiftExtFixed,
SUB = AddSubShiftExtFixed | B30,
};
#define APPLY_OP_LIST(_V) \
_V(DPImmediate) \
_V(CompareBranch) \
_V(LoadStore) \
_V(DPRegister) \
_V(DPSimd1) \
_V(DPSimd2) \
_V(ExceptionGen) \
_V(System) \
_V(UnconditionalBranchReg) \
_V(AddSubImm) \
_V(MoveWide) \
_V(AddSubShiftExt) \
enum Shift {
kNoShift = -1,
LSL = 0, // Logical shift left
LSR = 1, // Logical shift right
ASR = 2, // Arithmetic shift right
ROR = 3, // Rotate right
kMaxShift = 4,
};
enum Extend {
kNoExtend = -1,
UXTB = 0,
UXTH = 1,
UXTW = 2,
UXTX = 3,
SXTB = 4,
SXTH = 5,
SXTW = 6,
SXTX = 7,
kMaxExtend = 8,
};
enum R31Type {
R31IsSP,
R31IsZR,
R31IsUndef,
};
// Constants used for the decoding or encoding of the individual fields of
// instructions. Based on the "Figure 3-1 ARM instruction set summary".
enum InstructionFields {
// S-bit (modify condition register)
kSShift = 29,
kSBits = 1,
// sf field.
kSFShift = 31,
kSFBits = 1,
// Registers.
kRdShift = 0,
kRdBits = 5,
kRnShift = 5,
kRnBits = 5,
kRaShift = 10,
kRaBits = 5,
kRmShift = 16,
kRmBits = 5,
// Immediates.
kImm3Shift = 10,
kImm3Bits = 3,
kImm6Shift = 10,
kImm6Bits = 6,
kImm12Shift = 10,
kImm12Bits = 12,
kImm12ShiftShift = 22,
kImm12ShiftBits = 2,
kImm16Shift = 5,
kImm16Bits = 16,
// Shift and Extend.
kShiftExtendShift = 21,
kShiftExtendBits = 1,
kShiftTypeShift = 22,
kShiftTypeBits = 2,
kExtendTypeShift = 13,
kExtendTypeBits = 3,
// Hint Fields.
kHintCRmShift = 8,
kHintCRmBits = 4,
kHintOp2Shift = 5,
kHintOp2Bits = 3,
};
const uint32_t kImmExceptionIsRedirectedCall = 0xca11;
const uint32_t kImmExceptionIsUnreachable = 0xdebf;
const uint32_t kImmExceptionIsPrintf = 0xdeb1;
const uint32_t kImmExceptionIsDebug = 0xdeb0;
// The class Instr enables access to individual fields defined in the ARM
// architecture instruction set encoding as described in figure A3-1.
//
// Example: Test whether the instruction at ptr sets the condition code bits.
//
// bool InstructionSetsConditionCodes(byte* ptr) {
// Instr* instr = Instr::At(ptr);
// int type = instr->TypeField();
// return ((type == 0) || (type == 1)) && instr->HasS();
// }
//
class Instr {
public:
enum {
kInstrSize = 4,
kInstrSizeLog2 = 2,
kPCReadOffset = 8
};
static const int32_t kNopInstruction = HINT; // hint #0 === nop.
static const int32_t kBreakPointInstruction = // hlt #kImmExceptionIsDebug.
HLT | (kImmExceptionIsDebug << kImm16Shift);
static const int kBreakPointInstructionSize = kInstrSize;
// Get the raw instruction bits.
inline int32_t InstructionBits() const {
return *reinterpret_cast<const int32_t*>(this);
}
// Set the raw instruction bits to value.
inline void SetInstructionBits(int32_t value) {
*reinterpret_cast<int32_t*>(this) = value;
}
// Read one particular bit out of the instruction bits.
inline int Bit(int nr) const {
return (InstructionBits() >> nr) & 1;
}
// Read a bit field out of the instruction bits.
inline int Bits(int shift, int count) const {
return (InstructionBits() >> shift) & ((1 << count) - 1);
}
inline int SField() const { return Bit(kSShift); }
inline int SFField() const { return Bit(kSFShift); }
inline Register RdField() const { return static_cast<Register>(
Bits(kRdShift, kRdBits)); }
inline Register RnField() const { return static_cast<Register>(
Bits(kRnShift, kRnBits)); }
inline Register RaField() const { return static_cast<Register>(
Bits(kRaShift, kRaBits)); }
inline Register RmField() const { return static_cast<Register>(
Bits(kRmShift, kRmBits)); }
// Immediates
inline int Imm3Field() const { return Bits(kImm3Shift, kImm3Bits); }
inline int Imm6Field() const { return Bits(kImm6Shift, kImm6Bits); }
inline int Imm12Field() const { return Bits(kImm12Shift, kImm12Bits); }
inline int Imm16Field() const { return Bits(kImm16Shift, kImm16Bits); }
inline int Imm12ShiftField() const {
return Bits(kImm12ShiftShift, kImm12ShiftBits); }
// Shift and Extend.
inline bool IsShift() const { return (Bit(kShiftExtendShift) == 0); }
inline bool IsExtend() const { return (Bit(kShiftExtendShift) == 1); }
inline Shift ShiftTypeField() const {
return static_cast<Shift>(Bits(kShiftTypeShift, kShiftTypeBits)); }
inline Extend ExtendTypeField() const {
return static_cast<Extend>(Bits(kExtendTypeShift, kExtendTypeBits)); }
inline int ShiftAmountField() const { return Imm6Field(); }
inline int ExtShiftAmountField() const { return Imm3Field(); }
// Instruction identification.
#define IS_OP(op) \
inline bool Is##op##Op() const { \
return ((InstructionBits() & op##Mask) == (op##Fixed & op##Mask)); }
APPLY_OP_LIST(IS_OP)
#undef IS_OP
inline bool HasS() const { return (SField() == 1); }
// Indicate whether Rd can be the SP or ZR. This does not check that the
// instruction actually has an Rd field.
R31Type RdMode() const {
// The following instructions use SP as Rd:
// Add/sub (immediate) when not setting the flags.
// Add/sub (extended) when not setting the flags.
// Logical (immediate) when not setting the flags.
// Otherwise, R31 is the ZR.
if (IsAddSubImmOp() || (IsAddSubShiftExtOp() && IsExtend())) {
if (HasS()) {
return R31IsZR;
} else {
return R31IsSP;
}
}
// TODO(zra): Handle for logical immediate operations.
return R31IsZR;
}
// Indicate whether Rn can be SP or ZR. This does not check that the
// instruction actually has an Rn field.
R31Type RnMode() const {
// The following instructions use SP as Rn:
// All loads and stores.
// Add/sub (immediate).
// Add/sub (extended).
// Otherwise, r31 is ZR.
if (IsLoadStoreOp() ||
IsAddSubImmOp() ||
(IsAddSubShiftExtOp() && IsExtend())) {
return R31IsSP;
}
return R31IsZR;
}
// Instructions are read out of a code stream. The only way to get a
// reference to an instruction is to convert a pointer. There is no way
// to allocate or create instances of class Instr.
// Use the At(pc) function to create references to Instr.
static Instr* At(uword pc) { return reinterpret_cast<Instr*>(pc); }
private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
};
} // namespace dart
#endif // VM_CONSTANTS_ARM64_H_

View file

@ -29,6 +29,8 @@ class CPU : public AllStatic {
#include "vm/cpu_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/cpu_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/cpu_arm64.h"
#elif defined(TARGET_ARCH_MIPS)
#include "vm/cpu_mips.h"
#else

90
runtime/vm/cpu_arm64.cc Normal file
View file

@ -0,0 +1,90 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/cpu.h"
#include "vm/cpuinfo.h"
#include "vm/simulator.h"
#if defined(HOST_ARCH_ARM64)
#include <sys/syscall.h> /* NOLINT */
#include <unistd.h> /* NOLINT */
#endif
namespace dart {
void CPU::FlushICache(uword start, uword size) {
#if defined(USING_SIMULATOR)
// Nothing to do.
#else
UNIMPLEMENTED();
#endif
}
const char* CPU::Id() {
return
#if !defined(HOST_ARCH_ARM64)
"sim"
#endif // !defined(HOST_ARCH_ARM64)
"arm64";
}
const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif
#if defined(HOST_ARCH_ARM64)
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
free(const_cast<char*>(hardware_));
hardware_ = NULL;
CpuInfo::Cleanup();
}
#else
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
free(const_cast<char*>(hardware_));
hardware_ = NULL;
CpuInfo::Cleanup();
}
#endif // defined(HOST_ARCH_ARM64)
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

55
runtime/vm/cpu_arm64.h Normal file
View file

@ -0,0 +1,55 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPU_ARM64_H_
#define VM_CPU_ARM64_H_
#include "vm/allocation.h"
#include "vm/simulator.h"
namespace dart {
// TargetCPUFeatures gives CPU features for the architecture that we are
// generating code for. HostCPUFeatures gives the CPU features for the
// architecture that we are actually running on. When the architectures
// are the same, TargetCPUFeatures will query HostCPUFeatures. When they are
// different (i.e. we are running in a simulator), HostCPUFeatures will
// additionally mock the options needed for the target architecture so that
// they may be altered for testing.
class HostCPUFeatures: public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* hardware() {
DEBUG_ASSERT(initialized_);
return hardware_;
}
private:
static const char* hardware_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
class TargetCPUFeatures : public AllStatic {
public:
static void InitOnce() {
HostCPUFeatures::InitOnce();
}
static void Cleanup() {
HostCPUFeatures::Cleanup();
}
static const char* hardware() {
return HostCPUFeatures::hardware();
}
static bool double_truncate_round_supported() {
return false;
}
};
} // namespace dart
#endif // VM_CPU_ARM64_H_

View file

@ -20,6 +20,12 @@ UNIT_TEST_CASE(Id) {
#else // defined(HOST_ARCH_ARM)
EXPECT_STREQ("simarm", CPU::Id());
#endif // defined(HOST_ARCH_ARM)
#elif defined(TARGET_ARCH_ARM64)
#if defined(HOST_ARCH_ARM64)
EXPECT_STREQ("arm64", CPU::Id());
#else // defined(HOST_ARCH_ARM64)
EXPECT_STREQ("simarm64", CPU::Id());
#endif // defined(HOST_ARCH_ARM64)
#elif defined(TARGET_ARCH_MIPS)
#if defined(HOST_ARCH_MIPS)
EXPECT_STREQ("mips", CPU::Id());

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_api.h"
#include "include/dart_native_api.h"
@ -350,3 +354,5 @@ UNIT_TEST_CASE(CustomIsolates) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -233,12 +233,15 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer, void* data) {
Object::VerifyBuiltinVtables();
StubCode::Init(isolate);
// TODO(zra): ifndef to be removed when ARM64 port is ready.
#if !defined(TARGET_ARCH_ARM64)
if (snapshot_buffer == NULL) {
if (!isolate->object_store()->PreallocateObjects()) {
return isolate->object_store()->sticky_error();
}
}
isolate->megamorphic_cache_table()->InitMissHandler();
#endif
isolate->heap()->EnableGrowthControl();
isolate->set_init_callback_data(data);

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "bin/builtin.h"
#include "include/dart_api.h"
#include "include/dart_debugger_api.h"
@ -8094,3 +8098,5 @@ TEST_CASE(ExternalStringIndexOf) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -58,12 +58,22 @@ RawObject* DartEntry::InvokeFunction(const Function& function,
ASSERT(!code.IsNull());
ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
#if defined(USING_SIMULATOR)
#if defined(ARCH_IS_64_BIT)
// TODO(zra): Change to intptr_t so we have only one case.
return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
reinterpret_cast<int64_t>(entrypoint),
static_cast<int64_t>(code.EntryPoint()),
reinterpret_cast<int64_t>(&arguments_descriptor),
reinterpret_cast<int64_t>(&arguments),
reinterpret_cast<int64_t>(&context)));
#else
return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
reinterpret_cast<int32_t>(entrypoint),
static_cast<int32_t>(code.EntryPoint()),
reinterpret_cast<int32_t>(&arguments_descriptor),
reinterpret_cast<int32_t>(&arguments),
reinterpret_cast<int32_t>(&context)));
#endif
#else
return entrypoint(code.EntryPoint(),
arguments_descriptor,

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/assembler.h"
#include "vm/class_finalizer.h"
@ -111,3 +115,5 @@ TEST_CASE(InvokeDynamic_CompileError) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_debugger_api.h"
#include "include/dart_mirrors_api.h"
#include "platform/assert.h"
@ -2139,3 +2143,5 @@ TEST_CASE(Debug_ScriptGetTokenInfo_MultiLineInterpolation) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,46 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/code_patcher.h"
#include "vm/cpu.h"
#include "vm/debugger.h"
#include "vm/instructions.h"
#include "vm/stub_code.h"
namespace dart {
RawInstance* ActivationFrame::GetInstanceCallReceiver(
intptr_t num_actual_args) {
UNIMPLEMENTED();
return NULL;
}
RawObject* ActivationFrame::GetClosureObject(intptr_t num_actual_args) {
UNIMPLEMENTED();
return NULL;
}
uword CodeBreakpoint::OrigStubAddress() const {
UNIMPLEMENTED();
return 0;
}
void CodeBreakpoint::PatchCode() {
UNIMPLEMENTED();
}
void CodeBreakpoint::RestoreCode() {
UNIMPLEMENTED();
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/debugger.h"
#include "vm/unit_test.h"
@ -104,6 +108,6 @@ TEST_CASE(Debugger_PauseEvent) {
EXPECT(saw_paused_event);
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,486 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/disassembler.h"
#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
#if defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
namespace dart {
class ARM64Decoder : public ValueObject {
public:
ARM64Decoder(char* buffer, size_t buffer_size)
: buffer_(buffer),
buffer_size_(buffer_size),
buffer_pos_(0) {
buffer_[buffer_pos_] = '\0';
}
~ARM64Decoder() {}
// Writes one disassembled instruction into 'buffer' (0-terminated).
// Returns true if the instruction was successfully decoded, false otherwise.
void InstructionDecode(uword pc);
private:
// Bottleneck functions to print into the out_buffer.
void Print(const char* str);
// Printing of common values.
void PrintRegister(int reg);
void PrintShiftExtendRm(Instr* instr);
void PrintS(Instr* instr);
// Handle formatting of instructions and their options.
int FormatRegister(Instr* instr, const char* option);
int FormatOption(Instr* instr, const char* format);
void Format(Instr* instr, const char* format);
void Unknown(Instr* instr);
// Decode instructions.
#define DECODE_OP(op) \
void Decode##op(Instr* instr);
APPLY_OP_LIST(DECODE_OP)
#undef DECODE_OP
// Convenience functions.
char* get_buffer() const { return buffer_; }
char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
char* buffer_; // Decode instructions into this buffer.
size_t buffer_size_; // The size of the character buffer.
size_t buffer_pos_; // Current character position in buffer.
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ARM64Decoder);
};
// Support for assertions in the ARM64Decoder formatting functions.
#define STRING_STARTS_WITH(string, compare_string) \
(strncmp(string, compare_string, strlen(compare_string)) == 0)
// Append the str to the output buffer.
void ARM64Decoder::Print(const char* str) {
char cur = *str++;
while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
buffer_[buffer_pos_++] = cur;
cur = *str++;
}
buffer_[buffer_pos_] = '\0';
}
// These register names are defined in a way to match the native disassembler
// formatting, except for register aliases ctx (r9) and pp (r10).
// See for example the command "objdump -d <binary file>".
static const char* reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31",
};
// Print the register name according to the active name converter.
void ARM64Decoder::PrintRegister(int reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfCpuRegisters);
Print(reg_names[reg]);
}
// These shift names are defined in a way to match the native disassembler
// formatting. See for example the command "objdump -d <binary file>".
static const char* shift_names[kMaxShift] = {
"lsl", "lsr", "asr", "ror"
};
static const char* extend_names[kMaxExtend] = {
"uxtb", "uxth", "uxtw", "uxtx",
"sxtb", "sxth", "sxtw", "sxtx",
};
// Print the register shift operands for the instruction. Generally used for
// data processing instructions.
void ARM64Decoder::PrintShiftExtendRm(Instr* instr) {
int rm = instr->RmField();
Shift shift = instr->ShiftTypeField();
int shift_amount = instr->ShiftAmountField();
Extend extend = instr->ExtendTypeField();
int extend_shift_amount = instr->ExtShiftAmountField();
PrintRegister(rm);
if (instr->IsShift() && (shift == LSL) && (shift_amount == 0)) {
// Special case for using rm only.
return;
}
if (instr->IsShift()) {
// by immediate
if ((shift == ROR) && (shift_amount == 0)) {
Print(", RRX");
return;
} else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
shift_amount = 32;
}
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
", %s #%d",
shift_names[shift],
shift_amount);
} else {
ASSERT(instr->IsExtend());
// by register
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
", %s",
extend_names[extend]);
if (((instr->SFField() == 1) && (extend == UXTX)) ||
((instr->SFField() == 0) && (extend == UXTW))) {
// Shift amount.
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
" %d",
extend_shift_amount);
}
}
}
// Handle all register based formatting in these functions to reduce the
// complexity of FormatOption.
int ARM64Decoder::FormatRegister(Instr* instr, const char* format) {
ASSERT(format[0] == 'r');
if (format[1] == 'n') { // 'rn: Rn register
int reg = instr->RnField();
PrintRegister(reg);
return 2;
} else if (format[1] == 'd') { // 'rd: Rd register
int reg = instr->RdField();
PrintRegister(reg);
return 2;
} else if (format[1] == 'm') { // 'rm: Rm register
int reg = instr->RmField();
PrintRegister(reg);
return 2;
}
UNREACHABLE();
return -1;
}
// FormatOption takes a formatting string and interprets it based on
// the current instructions. The format string points to the first
// character of the option string (the option escape has already been
// consumed by the caller.) FormatOption returns the number of
// characters that were consumed from the formatting string.
int ARM64Decoder::FormatOption(Instr* instr, const char* format) {
switch (format[0]) {
case 'i': { // 'imm12, imm16
uint64_t imm;
int ret = 5;
if (format[4] == '2') {
ASSERT(STRING_STARTS_WITH(format, "imm12"));
imm = instr->Imm12Field();
if (format[5] == 's') {
// shifted immediate.
if (instr->Imm12ShiftField() == 1) {
imm = imm << 12;
} else if ((instr->Imm12ShiftField() & 0x2) != 0) {
Print("Unknown Shift");
}
ret = 6;
}
} else {
ASSERT(STRING_STARTS_WITH(format, "imm16"));
imm = instr->Imm16Field();
}
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
"0x%"Px64,
imm);
return ret;
}
case 's': { // 's: S flag.
if (format[1] == 'h') {
ASSERT(STRING_STARTS_WITH(format, "shift_op"));
PrintShiftExtendRm(instr);
return 8;
} else if (format[1] == 'f') {
ASSERT(STRING_STARTS_WITH(format, "sf"));
if (instr->SFField() == 1) {
// TODO(zra): If we don't use the w form much, we can omit printing
// this x.
Print("x");
} else {
Print("w");
}
return 2;
} else if (format[1] == ' ') {
if (instr->HasS()) {
Print("s");
}
return 1;
} else {
UNREACHABLE();
}
}
case 'r': {
return FormatRegister(instr, format);
}
default: {
UNREACHABLE();
break;
}
}
UNREACHABLE();
return -1;
}
// Format takes a formatting string for a whole instruction and prints it into
// the output buffer. All escaped options are handed to FormatOption to be
// parsed further.
void ARM64Decoder::Format(Instr* instr, const char* format) {
char cur = *format++;
while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
if (cur == '\'') { // Single quote is used as the formatting escape.
format += FormatOption(instr, format);
} else {
buffer_[buffer_pos_++] = cur;
}
cur = *format++;
}
buffer_[buffer_pos_] = '\0';
}
// For currently unimplemented decodings the disassembler calls Unknown(instr)
// which will just print "unknown" of the instruction bits.
void ARM64Decoder::Unknown(Instr* instr) {
Format(instr, "unknown");
}
void ARM64Decoder::DecodeMoveWide(Instr* instr) {
switch (instr->Bits(29, 2)) {
case 0:
Format(instr, "movn'sf 'rd, 'imm16");
break;
case 2:
Format(instr, "movz'sf 'rd, 'imm16");
break;
case 3:
Format(instr, "movk'sf 'rd, 'imm16");
break;
default:
Unknown(instr);
break;
}
}
void ARM64Decoder::DecodeAddSubImm(Instr* instr) {
switch (instr->Bit(30)) {
case 0:
Format(instr, "addi'sf's 'rd, 'rn, 'imm12s");
break;
case 1:
Format(instr, "subi'sf's 'rd, 'rn, 'imm12s");
break;
default:
Unknown(instr);
break;
}
}
void ARM64Decoder::DecodeDPImmediate(Instr* instr) {
if (instr->IsMoveWideOp()) {
DecodeMoveWide(instr);
} else if (instr->IsAddSubImmOp()) {
DecodeAddSubImm(instr);
} else {
Unknown(instr);
}
}
void ARM64Decoder::DecodeExceptionGen(Instr* instr) {
if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
(instr->Bits(21, 3) == 0)) {
Format(instr, "svc 'imm16");
} else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
(instr->Bits(21, 3) == 1)) {
Format(instr, "brk 'imm16");
} else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
(instr->Bits(21, 3) == 2)) {
Format(instr, "hlt 'imm16");
}
}
void ARM64Decoder::DecodeSystem(Instr* instr) {
if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) &&
(instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
(instr->Bit(21) == 0)) {
if (instr->Bits(8, 4) == 0) {
Format(instr, "nop");
} else {
Unknown(instr);
}
} else {
Unknown(instr);
}
}
void ARM64Decoder::DecodeUnconditionalBranchReg(Instr* instr) {
if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 5) == 0) &&
(instr->Bits(16, 5) == 0x1f)) {
switch (instr->Bits(21, 4)) {
case 0:
Format(instr, "br 'rn");
break;
case 1:
Format(instr, "blr 'rn");
break;
case 2:
Format(instr, "ret 'rn");
break;
default:
Unknown(instr);
break;
}
}
}
void ARM64Decoder::DecodeCompareBranch(Instr* instr) {
if (instr->IsExceptionGenOp()) {
DecodeExceptionGen(instr);
} else if (instr->IsSystemOp()) {
DecodeSystem(instr);
} else if (instr->IsUnconditionalBranchRegOp()) {
DecodeUnconditionalBranchReg(instr);
} else {
Unknown(instr);
}
}
void ARM64Decoder::DecodeLoadStore(Instr* instr) {
Unknown(instr);
}
void ARM64Decoder::DecodeAddSubShiftExt(Instr* instr) {
switch (instr->Bit(30)) {
case 0:
Format(instr, "add'sf's 'rd, 'rn, 'shift_op");
break;
case 1:
Format(instr, "sub'sf's 'rd, 'rn, 'shift_op");
break;
default:
UNREACHABLE();
break;
}
}
void ARM64Decoder::DecodeDPRegister(Instr* instr) {
if (instr->IsAddSubShiftExtOp()) {
DecodeAddSubShiftExt(instr);
} else {
Unknown(instr);
}
}
void ARM64Decoder::DecodeDPSimd1(Instr* instr) {
Unknown(instr);
}
void ARM64Decoder::DecodeDPSimd2(Instr* instr) {
Unknown(instr);
}
void ARM64Decoder::InstructionDecode(uword pc) {
Instr* instr = Instr::At(pc);
if (instr->IsDPImmediateOp()) {
DecodeDPImmediate(instr);
} else if (instr->IsCompareBranchOp()) {
DecodeCompareBranch(instr);
} else if (instr->IsLoadStoreOp()) {
DecodeLoadStore(instr);
} else if (instr->IsDPRegisterOp()) {
DecodeDPRegister(instr);
} else if (instr->IsDPSimd1Op()) {
DecodeDPSimd1(instr);
} else {
ASSERT(instr->IsDPSimd2Op());
DecodeDPSimd2(instr);
}
}
void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
char* human_buffer, intptr_t human_size,
int* out_instr_size, uword pc) {
ARM64Decoder decoder(human_buffer, human_size);
decoder.InstructionDecode(pc);
int32_t instruction_bits = Instr::At(pc)->InstructionBits();
OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
if (out_instr_size) {
*out_instr_size = Instr::kInstrSize;
}
}
void Disassembler::Disassemble(uword start,
uword end,
DisassemblyFormatter* formatter,
const Code::Comments& comments) {
ASSERT(formatter != NULL);
char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
uword pc = start;
intptr_t comment_finger = 0;
while (pc < end) {
const intptr_t offset = pc - start;
while (comment_finger < comments.Length() &&
comments.PCOffsetAt(comment_finger) <= offset) {
formatter->Print(
" ;; %s\n",
String::Handle(comments.CommentAt(comment_finger)).ToCString());
comment_finger++;
}
int instruction_length;
DecodeInstruction(hex_buffer, sizeof(hex_buffer),
human_buffer, sizeof(human_buffer),
&instruction_length, pc);
formatter->ConsumeInstruction(hex_buffer,
sizeof(hex_buffer),
human_buffer,
sizeof(human_buffer),
pc);
pc += instruction_length;
}
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/disassembler.h"
#include "vm/unit_test.h"
@ -23,3 +27,5 @@ TEST_CASE(Disassembler) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -403,6 +403,9 @@ void ElfGen::AddELFHeader(int shoff) {
WriteShort(&header_, kEM_X86_64); // e_machine
#elif defined(TARGET_ARCH_ARM)
WriteShort(&header_, kEM_ARM); // e_machine
#elif defined(TARGET_ARCH_ARM64)
// TODO(zra): Find the right ARM64 constant.
WriteShort(&header_, kEM_ARM); // e_machine
#elif defined(TARGET_ARCH_MIPS)
WriteShort(&header_, kEM_MIPS); // e_machine
#else

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_api.h"
#include "platform/assert.h"
#include "vm/dart_api_impl.h"
@ -133,3 +137,5 @@ TEST_CASE(UnhandledExceptions) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
@ -156,3 +160,5 @@ TEST_CASE(FindCodeObject) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,429 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
#if defined(TARGET_ARCH_ARM64)
#include "vm/flow_graph_compiler.h"
#include "vm/ast_printer.h"
#include "vm/compiler.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/deopt_instructions.h"
#include "vm/il_printer.h"
#include "vm/locations.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
namespace dart {
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
// Verify the labels explicitly here.
for (int i = 0; i < block_info_.length(); ++i) {
ASSERT(!block_info_[i]->jump_label()->IsLinked());
}
}
bool FlowGraphCompiler::SupportsUnboxedMints() {
return false;
}
bool FlowGraphCompiler::SupportsUnboxedSimd128() {
return false;
}
bool FlowGraphCompiler::SupportsSinCos() {
return false;
}
RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
DeoptInfoBuilder* builder,
const Array& deopt_table) {
UNIMPLEMENTED();
return NULL;
}
void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
intptr_t stub_ix) {
UNIMPLEMENTED();
}
#define __ assembler()->
// Fall through if bool_register contains null.
void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
Label* is_true,
Label* is_false) {
UNIMPLEMENTED();
}
RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
TypeTestStubKind test_kind,
Register instance_reg,
Register type_arguments_reg,
Register temp_reg,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return NULL;
}
RawSubtypeTestCache*
FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
intptr_t token_pos,
const AbstractType& type,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return NULL;
}
void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
const GrowableArray<intptr_t>& class_ids,
Label* is_equal_lbl,
Label* is_not_equal_lbl) {
UNIMPLEMENTED();
}
bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
intptr_t token_pos,
const AbstractType& type,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return false;
}
RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
intptr_t token_pos,
const Class& type_class,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return NULL;
}
RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
intptr_t token_pos,
const AbstractType& type,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return NULL;
}
RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
intptr_t token_pos,
const AbstractType& type,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
UNIMPLEMENTED();
return NULL;
}
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
intptr_t deopt_id,
const AbstractType& type,
bool negate_result,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::CopyParameters() {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitFrameEntry() {
UNIMPLEMENTED();
}
void FlowGraphCompiler::CompileGraph() {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
const ExternalLabel* label,
PcDescriptors::Kind kind,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
intptr_t token_pos,
const ExternalLabel* label,
PcDescriptors::Kind kind,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos,
intptr_t deopt_id,
const RuntimeEntry& entry,
intptr_t argument_count,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitEdgeCounter() {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitOptimizedInstanceCall(
ExternalLabel* target_label,
const ICData& ic_data,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
const ICData& ic_data,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitUnoptimizedStaticCall(
const Function& target_function,
const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitOptimizedStaticCall(
const Function& function,
const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
const Object& obj,
bool needs_number_check,
intptr_t token_pos) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
Register right,
bool needs_number_check,
intptr_t token_pos) {
UNIMPLEMENTED();
}
// This function must be in sync with FlowGraphCompiler::RecordSafepoint and
// FlowGraphCompiler::SlowPathEnvironmentFor.
void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
UNIMPLEMENTED();
}
void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
Register class_id_reg,
intptr_t argument_count,
const Array& argument_names,
Label* deopt,
intptr_t deopt_id,
intptr_t token_index,
LocationSummary* locs) {
UNIMPLEMENTED();
}
// Do not implement or use this function.
FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
intptr_t index_scale,
Register array,
intptr_t index) {
UNREACHABLE();
return FieldAddress(array, index);
}
// Do not implement or use this function.
FieldAddress FlowGraphCompiler::ElementAddressForRegIndex(intptr_t cid,
intptr_t index_scale,
Register array,
Register index) {
UNREACHABLE(); // No register indexed with offset addressing mode on ARM.
return FieldAddress(array, index);
}
Address FlowGraphCompiler::ExternalElementAddressForIntIndex(
intptr_t index_scale,
Register array,
intptr_t index) {
UNREACHABLE();
return FieldAddress(array, index);
}
Address FlowGraphCompiler::ExternalElementAddressForRegIndex(
intptr_t index_scale,
Register array,
Register index) {
UNREACHABLE();
return FieldAddress(array, index);
}
#undef __
#define __ compiler_->assembler()->
void ParallelMoveResolver::EmitMove(int index) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::EmitSwap(int index) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
const Address& src) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
UNIMPLEMENTED();
}
// Do not call or implement this function. Instead, use the form below that
// uses an offset from the frame pointer instead of an Address.
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
UNREACHABLE();
}
// Do not call or implement this function. Instead, use the form below that
// uses offsets from the frame pointer instead of Addresses.
void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
UNREACHABLE();
}
void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
intptr_t stack_offset2) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::SpillScratch(Register reg) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::RestoreScratch(Register reg) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
UNIMPLEMENTED();
}
void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
UNIMPLEMENTED();
}
#undef __
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/dart_api_impl.h"
#include "vm/dart_api_state.h"
#include "vm/intermediate_language.h"
@ -270,3 +274,5 @@ TEST_CASE(GuardFieldConstructor2Test) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/dart_api_impl.h"
#include "vm/globals.h"
@ -206,3 +209,5 @@ TEST_CASE(FindObject) {
}
} // namespace dart.
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -13,6 +13,8 @@
#include "vm/instructions_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/instructions_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/instructions_arm64.h"
#elif defined(TARGET_ARCH_MIPS)
#include "vm/instructions_mips.h"
#else

View file

@ -0,0 +1,129 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
#if defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/constants_arm64.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
#include "vm/object.h"
namespace dart {
CallPattern::CallPattern(uword pc, const Code& code)
: object_pool_(Array::Handle(code.ObjectPool())),
end_(pc),
args_desc_load_end_(0),
ic_data_load_end_(0),
target_address_pool_index_(-1),
args_desc_(Array::Handle()),
ic_data_(ICData::Handle()) {
UNIMPLEMENTED();
}
int CallPattern::LengthInBytes() {
UNIMPLEMENTED();
return 0;
}
// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end). Returns a pointer to
// the first instruction in the sequence. Returns the register being loaded
// and the loaded object in the output parameters 'reg' and 'obj'
// respectively.
uword InstructionPattern::DecodeLoadObject(uword end,
const Array& object_pool,
Register* reg,
Object* obj) {
UNIMPLEMENTED();
return 0;
}
// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end). Returns a pointer to
// the first instruction in the sequence. Returns the register being loaded
// and the loaded immediate value in the output parameters 'reg' and 'value'
// respectively.
uword InstructionPattern::DecodeLoadWordImmediate(uword end,
Register* reg,
intptr_t* value) {
UNIMPLEMENTED();
return 0;
}
// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end). Returns a pointer to
// the first instruction in the sequence. Returns the register being loaded
// and the index in the pool being read from in the output parameters 'reg'
// and 'index' respectively.
uword InstructionPattern::DecodeLoadWordFromPool(uword end,
Register* reg,
intptr_t* index) {
UNIMPLEMENTED();
return 0;
}
RawICData* CallPattern::IcData() {
UNIMPLEMENTED();
return NULL;
}
RawArray* CallPattern::ClosureArgumentsDescriptor() {
UNIMPLEMENTED();
return NULL;
}
uword CallPattern::TargetAddress() const {
UNIMPLEMENTED();
return 0;
}
void CallPattern::SetTargetAddress(uword target_address) const {
UNIMPLEMENTED();
}
void CallPattern::InsertAt(uword pc, uword target_address) {
UNIMPLEMENTED();
}
JumpPattern::JumpPattern(uword pc, const Code& code) : pc_(pc) { }
int JumpPattern::pattern_length_in_bytes() {
UNIMPLEMENTED();
return 0;
}
bool JumpPattern::IsValid() const {
UNIMPLEMENTED();
return false;
}
uword JumpPattern::TargetAddress() const {
UNIMPLEMENTED();
return 0;
}
void JumpPattern::SetTargetAddress(uword target_address) const {
UNIMPLEMENTED();
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -0,0 +1,101 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Classes that describe assembly patterns as used by inline caches.
#ifndef VM_INSTRUCTIONS_ARM64_H_
#define VM_INSTRUCTIONS_ARM64_H_
#ifndef VM_INSTRUCTIONS_H_
#error Do not include instructions_arm64.h directly; use instructions.h instead.
#endif
#include "vm/constants_arm64.h"
#include "vm/object.h"
namespace dart {
class InstructionPattern : public AllStatic {
public:
// Decodes a load sequence ending at 'end' (the last instruction of the
// load sequence is the instruction before the one at end). Returns the
// address of the first instruction in the sequence. Returns the register
// being loaded and the loaded object in the output parameters 'reg' and
// 'obj' respectively.
static uword DecodeLoadObject(uword end,
const Array& object_pool,
Register* reg,
Object* obj);
// Decodes a load sequence ending at 'end' (the last instruction of the
// load sequence is the instruction before the one at end). Returns the
// address of the first instruction in the sequence. Returns the register
// being loaded and the loaded immediate value in the output parameters
// 'reg' and 'value' respectively.
static uword DecodeLoadWordImmediate(uword end,
Register* reg,
intptr_t* value);
// Decodes a load sequence ending at 'end' (the last instruction of the
// load sequence is the instruction before the one at end). Returns the
// address of the first instruction in the sequence. Returns the register
// being loaded and the index in the pool being read from in the output
// parameters 'reg' and 'index' respectively.
static uword DecodeLoadWordFromPool(uword end,
Register* reg,
intptr_t* index);
};
class CallPattern : public ValueObject {
public:
CallPattern(uword pc, const Code& code);
RawICData* IcData();
RawArray* ClosureArgumentsDescriptor();
uword TargetAddress() const;
void SetTargetAddress(uword target_address) const;
// This constant length is only valid for inserted call patterns used for
// lazy deoptimization. Regular call pattern may vary in length.
static int LengthInBytes();
static void InsertAt(uword pc, uword target_address);
private:
const Array& object_pool_;
uword end_;
uword args_desc_load_end_;
uword ic_data_load_end_;
intptr_t target_address_pool_index_;
Array& args_desc_;
ICData& ic_data_;
DISALLOW_COPY_AND_ASSIGN(CallPattern);
};
class JumpPattern : public ValueObject {
public:
JumpPattern(uword pc, const Code& code);
static const int kLengthInBytes = 3 * Instr::kInstrSize;
static int pattern_length_in_bytes();
bool IsValid() const;
uword TargetAddress() const;
void SetTargetAddress(uword target_address) const;
private:
const uword pc_;
DISALLOW_COPY_AND_ASSIGN(JumpPattern);
};
} // namespace dart
#endif // VM_INSTRUCTIONS_ARM64_H_

View file

@ -0,0 +1,10 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
// TODO(zra): Port these tests.
#endif // defined TARGET_ARCH_ARM64

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,408 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
#if defined(TARGET_ARCH_ARM64)
#include "vm/intrinsifier.h"
#include "vm/assembler.h"
#include "vm/flow_graph_compiler.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/symbols.h"
namespace dart {
#define __ assembler->
void Intrinsifier::List_Allocate(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Array_getLength(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::ImmutableList_getLength(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Array_getIndexed(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Array_setIndexed(Assembler* assembler) {
UNIMPLEMENTED();
}
// Allocate a GrowableObjectArray using the backing array specified.
// On stack: type argument (+1), data (+0).
void Intrinsifier::GrowableList_Allocate(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::GrowableList_getLength(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) {
UNIMPLEMENTED();
}
// Set value into growable object array at specified index.
// On stack: growable array (+2), index (+1), value (+0).
void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) {
UNIMPLEMENTED();
}
// Set length of growable object array. The length cannot
// be greater than the length of the data container.
// On stack: growable array (+1), length (+0).
void Intrinsifier::GrowableList_setLength(Assembler* assembler) {
UNIMPLEMENTED();
}
// Set data of growable object array.
// On stack: growable array (+1), data (+0).
void Intrinsifier::GrowableList_setData(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::GrowableList_add(Assembler* assembler) {
UNIMPLEMENTED();
}
// Gets the length of a TypedData.
void Intrinsifier::TypedData_getLength(Assembler* assembler) {
UNIMPLEMENTED();
}
#define TYPED_DATA_ALLOCATOR(clazz) \
void Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) { \
UNIMPLEMENTED(); \
} \
void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \
UNIMPLEMENTED(); \
}
CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
#undef TYPED_DATA_ALLOCATOR
void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_add(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_sub(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_mul(Assembler* assembler) {
UNIMPLEMENTED();
}
// Implementation:
// res = left % right;
// if (res < 0) {
// if (right < 0) {
// res = res - right;
// } else {
// res = res + right;
// }
// }
void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_truncDivide(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_negate(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitAnd(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitOr(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_bitXor(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_shl(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_lessThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_greaterThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
UNIMPLEMENTED();
}
// This is called for Smi, Mint and Bigint receivers. The right argument
// can be Smi, Mint, Bigint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_equal(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Integer_sar(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Smi_bitLength(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_greaterThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_lessThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_equal(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_add(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_mul(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_sub(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_div(Assembler* assembler) {
UNIMPLEMENTED();
}
// Left is double right is integer (Bigint, Mint or Smi)
void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_fromInteger(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_getIsNegative(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Double_toInt(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Math_sqrt(Assembler* assembler) {
UNIMPLEMENTED();
}
// var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
// _state[kSTATE_LO] = state & _MASK_32;
// _state[kSTATE_HI] = state >> 32;
void Intrinsifier::Random_nextState(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::Object_equal(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::String_getHashCode(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::String_getLength(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::String_codeUnitAt(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::String_getIsEmpty(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
UNIMPLEMENTED();
}
// Arg0: OneByteString (receiver).
// Arg1: Start index as Smi.
// Arg2: End index as Smi.
// The indexes must be valid.
void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::OneByteString_setAt(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::OneByteString_allocate(Assembler* assembler) {
UNIMPLEMENTED();
}
// TODO(srdjan): Add combinations (one-byte/two-byte/external strings).
void StringEquality(Assembler* assembler, intptr_t string_cid) {
UNIMPLEMENTED();
}
void Intrinsifier::OneByteString_equality(Assembler* assembler) {
UNIMPLEMENTED();
}
void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
UNIMPLEMENTED();
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/isolate.h"
@ -80,3 +84,5 @@ TEST_CASE(IsolateSpawn) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "platform/json.h"
#include "vm/json_stream.h"
@ -334,3 +338,5 @@ TEST_CASE(JSON_JSONStream_Options) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -5863,7 +5863,13 @@ RawFunction* Function::New(const String& name,
const ClosureData& data = ClosureData::Handle(ClosureData::New());
result.set_data(data);
}
// TODO(zra): Remove when arm64 is ready.
#if !defined(TARGET_ARCH_ARM64)
result.set_code(Code::Handle(StubCode::LazyCompile_entry()->code()));
#else
result.set_code(Code::Handle());
#endif
return result.raw();
}

View file

@ -0,0 +1,11 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
// TODO(zra): Port these tests.
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/object_id_ring.h"
@ -190,3 +194,5 @@ TEST_CASE(ObjectIdRingOldGCTest) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/bigint_operations.h"
#include "vm/class_finalizer.h"
@ -4009,3 +4013,5 @@ TEST_CASE(PrintToJSONStream) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -59,6 +59,8 @@ class LowLevelProfileCodeObserver : public CodeObserver {
const char arch[] = "x64";
#elif defined(TARGET_ARCH_ARM)
const char arch[] = "arm";
#elif defined(TARGET_ARCH_ARM64)
const char arch[] = "arm64";
#elif defined(TARGET_ARCH_MIPS)
const char arch[] = "mips";
#else
@ -355,6 +357,8 @@ class JitdumpCodeObserver : public CodeObserver {
static const uint32_t kElfMachIA32 = 3;
static const uint32_t kElfMachX64 = 62;
static const uint32_t kElfMachARM = 40;
// TODO(zra): Find the right ARM64 constant.
static const uint32_t kElfMachARM64 = 40;
static const uint32_t kElfMachMIPS = 10;
static const int kInvalidClockId = -1;
@ -405,6 +409,8 @@ class JitdumpCodeObserver : public CodeObserver {
return kElfMachX64;
#elif defined(TARGET_ARCH_ARM)
return kElfMachARM;
#elif defined(TARGET_ARCH_ARM64)
return kElfMachARM64;
#elif defined(TARGET_ARCH_MIPS)
return kElfMachMIPS;
#else
@ -570,7 +576,9 @@ void OS::AlignedFree(void* ptr) {
// TODO(5411554): May need to hoist these architecture dependent code
// into a architecture specific file e.g: os_ia32_linux.cc
word OS::ActivationFrameAlignment() {
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
#if defined(TARGET_ARCH_IA32) || \
defined(TARGET_ARCH_X64) || \
defined(TARGET_ARCH_ARM64)
const int kMinimumAlignment = 16;
#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
const int kMinimumAlignment = 8;
@ -588,7 +596,9 @@ word OS::ActivationFrameAlignment() {
word OS::PreferredCodeAlignment() {
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
#if defined(TARGET_ARCH_IA32) || \
defined(TARGET_ARCH_X64) || \
defined(TARGET_ARCH_ARM64)
const int kMinimumAlignment = 32;
#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
const int kMinimumAlignment = 16;

View file

@ -710,8 +710,13 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader,
*(func.raw()->from() + i) = reader->ReadObjectRef();
}
// TODO(zra): Remove when arm64 is ready.
#if !defined(TARGET_ARCH_ARM64)
// Set up code pointer with the lazy-compile-stub.
func.set_code(Code::Handle(StubCode::LazyCompile_entry()->code()));
#else
func.set_code(Code::Handle());
#endif
return func.raw();
}

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "platform/assert.h"
#include "vm/assembler.h"
#include "vm/class_finalizer.h"
@ -213,3 +217,5 @@ TEST_CASE(DartDynamicResolve) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -0,0 +1,24 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/runtime_entry.h"
#include "vm/assembler.h"
#include "vm/simulator.h"
#include "vm/stub_code.h"
namespace dart {
#define __ assembler->
void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
UNIMPLEMENTED();
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "vm/runtime_entry.h"
#include "vm/object.h"
@ -59,3 +63,5 @@ DEFINE_LEAF_RUNTIME_ENTRY(RawObject*, TestLeafSmiAdd, 2,
END_LEAF_RUNTIME_ENTRY
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_debugger_api.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
@ -1376,3 +1380,5 @@ TEST_CASE(Service_Profile) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -21,6 +21,14 @@
#include "vm/simulator_arm.h"
#endif
#elif defined(TARGET_ARCH_ARM64)
#if defined(HOST_ARCH_ARM64)
// No simulator used.
#else
#define USING_SIMULATOR 1
#include "vm/simulator_arm64.h"
#endif
#elif defined(TARGET_ARCH_MIPS)
#if defined(HOST_ARCH_MIPS)
// No simulator used.

View file

@ -0,0 +1,714 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <math.h> // for isnan.
#include <setjmp.h>
#include <stdlib.h>
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
// Only build the simulator if not compiling for real ARM hardware.
#if !defined(HOST_ARCH_ARM64)
#include "vm/simulator.h"
#include "vm/assembler.h"
#include "vm/constants_arm64.h"
#include "vm/cpu.h"
#include "vm/disassembler.h"
#include "vm/native_arguments.h"
#include "vm/stack_frame.h"
#include "vm/thread.h"
namespace dart {
DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution.");
DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
// This macro provides a platform independent use of sscanf. The reason for
// SScanF not being implemented in a platform independent way through
// OS in the same way as SNPrint is that the Windows C Run-Time
// Library does not provide vsscanf.
#define SScanF sscanf // NOLINT
Simulator::Simulator() {
// Setup simulator support first. Some of this information is needed to
// setup the architecture state.
// We allocate the stack here, the size is computed as the sum of
// the size specified by the user and the buffer space needed for
// handling stack overflow exceptions. To be safe in potential
// stack underflows we also add some underflow buffer space.
stack_ = new char[(Isolate::GetSpecifiedStackSize() +
Isolate::kStackSizeBuffer +
kSimulatorStackUnderflowSize)];
pc_modified_ = false;
icount_ = 0;
break_pc_ = NULL;
break_instr_ = 0;
top_exit_frame_info_ = 0;
// Setup architecture state.
// All registers are initialized to zero to start with.
for (int i = 0; i < kNumberOfCpuRegisters; i++) {
registers_[i] = 0;
}
n_flag_ = false;
z_flag_ = false;
c_flag_ = false;
v_flag_ = false;
// The sp is initialized to point to the bottom (high address) of the
// allocated stack area.
registers_[SP] = StackTop();
// The lr and pc are initialized to a known bad value that will cause an
// access violation if the simulator ever tries to execute it.
registers_[LR] = kBadLR;
pc_ = kBadLR;
}
Simulator::~Simulator() {
delete[] stack_;
Isolate* isolate = Isolate::Current();
if (isolate != NULL) {
isolate->set_simulator(NULL);
}
}
// Get the active Simulator for the current isolate.
Simulator* Simulator::Current() {
Simulator* simulator = Isolate::Current()->simulator();
if (simulator == NULL) {
simulator = new Simulator();
Isolate::Current()->set_simulator(simulator);
}
return simulator;
}
// Sets the register in the architecture state.
void Simulator::set_register(Register reg, int64_t value, R31Type r31t) {
// register is in range, and if it is R31, a mode is specified.
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
ASSERT((reg != R31) || (r31t != R31IsUndef));
if ((reg != R31) || (r31t != R31IsZR)) {
registers_[reg] = value;
}
}
// Get the register from the architecture state.
int64_t Simulator::get_register(Register reg, R31Type r31t) const {
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
ASSERT((reg != R31) || (r31t != R31IsUndef));
if ((reg == R31) && (r31t == R31IsZR)) {
return 0;
} else {
return registers_[reg];
}
}
void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) {
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
ASSERT((reg != R31) || (r31t != R31IsUndef));
// When setting in W mode, clear the high bits.
if ((reg != R31) || (r31t != R31IsZR)) {
registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0);
}
}
// Get the register from the architecture state.
int32_t Simulator::get_wregister(Register reg, R31Type r31t) const {
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
ASSERT((reg != R31) || (r31t != R31IsUndef));
if ((reg == R31) && (r31t == R31IsZR)) {
return 0;
} else {
return registers_[reg];
}
}
// Raw access to the PC register.
void Simulator::set_pc(int64_t value) {
pc_modified_ = true;
pc_ = value;
}
// Raw access to the PC register without the special adjustment when reading.
int64_t Simulator::get_pc() const {
return pc_;
}
void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
uword fault_pc = get_pc();
// TODO(zra): drop into debugger.
char buffer[128];
snprintf(buffer, sizeof(buffer),
"illegal memory access at 0x%" Px ", pc=0x%" Px "\n",
addr, fault_pc);
// The debugger will return control in non-interactive mode.
FATAL("Cannot continue execution after illegal memory access.");
}
void Simulator::UnimplementedInstruction(Instr* instr) {
char buffer[64];
snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
// TODO(zra): drop into debugger.
FATAL("Cannot continue execution after unimplemented instruction.");
}
// Returns the top of the stack area to enable checking for stack pointer
// validity.
uword Simulator::StackTop() const {
// To be safe in potential stack underflows we leave some buffer above and
// set the stack top.
return reinterpret_cast<uword>(stack_) +
(Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
}
// Unsupported instructions use Format to print an error and stop execution.
void Simulator::Format(Instr* instr, const char* format) {
OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n",
instr,
format);
UNIMPLEMENTED();
}
// Calculate and set the Negative and Zero flags.
void Simulator::SetNZFlagsW(int32_t val) {
n_flag_ = (val < 0);
z_flag_ = (val == 0);
}
// Calculate C flag value for additions.
bool Simulator::CarryFromW(int32_t left, int32_t right) {
uint32_t uleft = static_cast<uint32_t>(left);
uint32_t uright = static_cast<uint32_t>(right);
uint32_t urest = 0xffffffffU - uleft;
return (uright > urest);
}
// Calculate C flag value for subtractions.
bool Simulator::BorrowFromW(int32_t left, int32_t right) {
uint32_t uleft = static_cast<uint32_t>(left);
uint32_t uright = static_cast<uint32_t>(right);
return (uright > uleft);
}
// Calculate V flag value for additions and subtractions.
bool Simulator::OverflowFromW(int32_t alu_out,
int32_t left, int32_t right, bool addition) {
bool overflow;
if (addition) {
// operands have the same sign
overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
// and operands and result have different sign
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
} else {
// operands have different signs
overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
// and first operand and result have different signs
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
}
return overflow;
}
// Calculate and set the Negative and Zero flags.
void Simulator::SetNZFlagsX(int64_t val) {
n_flag_ = (val < 0);
z_flag_ = (val == 0);
}
// Calculate C flag value for additions.
bool Simulator::CarryFromX(int64_t left, int64_t right) {
uint64_t uleft = static_cast<uint64_t>(left);
uint64_t uright = static_cast<uint64_t>(right);
uint64_t urest = 0xffffffffffffffffULL - uleft;
return (uright > urest);
}
// Calculate C flag value for subtractions.
bool Simulator::BorrowFromX(int64_t left, int64_t right) {
uint64_t uleft = static_cast<uint64_t>(left);
uint64_t uright = static_cast<uint64_t>(right);
return (uright > uleft);
}
// Calculate V flag value for additions and subtractions.
bool Simulator::OverflowFromX(int64_t alu_out,
int64_t left, int64_t right, bool addition) {
bool overflow;
if (addition) {
// operands have the same sign
overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
// and operands and result have different sign
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
} else {
// operands have different signs
overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
// and first operand and result have different signs
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
}
return overflow;
}
// Set the Carry flag.
void Simulator::SetCFlag(bool val) {
c_flag_ = val;
}
// Set the oVerflow flag.
void Simulator::SetVFlag(bool val) {
v_flag_ = val;
}
void Simulator::DecodeMoveWide(Instr* instr) {
UnimplementedInstruction(instr);
}
void Simulator::DecodeAddSubImm(Instr* instr) {
switch (instr->Bit(30)) {
case 0: {
// Format(instr, "addi'sf's 'rd, 'rn, 'imm12s");
const Register rd = instr->RdField();
const Register rn = instr->RnField();
const uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
: (instr->Imm12Field());
if (instr->SFField()) {
// 64-bit add.
const int64_t rn_val = get_register(rn, instr->RnMode());
const int64_t alu_out = rn_val + imm;
set_register(rd, alu_out, instr->RdMode());
if (instr->HasS()) {
SetNZFlagsX(alu_out);
SetCFlag(CarryFromX(rn_val, imm));
SetVFlag(OverflowFromX(alu_out, rn_val, imm, true));
}
} else {
// 32-bit add.
const int32_t rn_val = get_wregister(rn, instr->RnMode());
const int32_t alu_out = rn_val + imm;
set_wregister(rd, alu_out, instr->RdMode());
if (instr->HasS()) {
SetNZFlagsW(alu_out);
SetCFlag(CarryFromW(rn_val, imm));
SetVFlag(OverflowFromW(alu_out, rn_val, imm, true));
}
}
break;
}
default:
UnimplementedInstruction(instr);
break;
}
}
void Simulator::DecodeDPImmediate(Instr* instr) {
if (instr->IsMoveWideOp()) {
DecodeMoveWide(instr);
} else if (instr->IsAddSubImmOp()) {
DecodeAddSubImm(instr);
} else {
UnimplementedInstruction(instr);
}
}
void Simulator::DecodeExceptionGen(Instr* instr) {
UnimplementedInstruction(instr);
}
void Simulator::DecodeSystem(Instr* instr) {
if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) &&
(instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
(instr->Bit(21) == 0)) {
if (instr->Bits(8, 4) == 0) {
// Format(instr, "nop");
} else {
UnimplementedInstruction(instr);
}
} else {
UnimplementedInstruction(instr);
}
}
void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) &&
(instr->Bits(16, 5) == 0x1f)) {
switch (instr->Bits(21, 4)) {
case 2: {
// Format(instr, "ret 'rn");
const Register rn = instr->RnField();
const int64_t rn_val = get_register(rn, instr->RnMode());
set_pc(rn_val);
break;
}
default:
UnimplementedInstruction(instr);
break;
}
} else {
UnimplementedInstruction(instr);
}
}
void Simulator::DecodeCompareBranch(Instr* instr) {
if (instr->IsExceptionGenOp()) {
DecodeExceptionGen(instr);
} else if (instr->IsSystemOp()) {
DecodeSystem(instr);
} else if (instr->IsUnconditionalBranchRegOp()) {
DecodeUnconditionalBranchReg(instr);
} else {
UnimplementedInstruction(instr);
}
}
void Simulator::DecodeLoadStore(Instr* instr) {
UnimplementedInstruction(instr);
}
int64_t Simulator::ShiftOperand(uint8_t reg_size,
int64_t value,
Shift shift_type,
uint8_t amount) {
if (amount == 0) {
return value;
}
int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask;
switch (shift_type) {
case LSL:
return (value << amount) & mask;
case LSR:
return static_cast<uint64_t>(value) >> amount;
case ASR: {
// Shift used to restore the sign.
uint8_t s_shift = kXRegSizeInBits - reg_size;
// Value with its sign restored.
int64_t s_value = (value << s_shift) >> s_shift;
return (s_value >> amount) & mask;
}
case ROR: {
if (reg_size == kWRegSizeInBits) {
value &= kWRegMask;
}
return (static_cast<uint64_t>(value) >> amount) |
((value & ((1L << amount) - 1L)) << (reg_size - amount));
}
default:
UNIMPLEMENTED();
return 0;
}
}
int64_t Simulator::ExtendOperand(uint8_t reg_size,
int64_t value,
Extend extend_type,
uint8_t amount) {
switch (extend_type) {
case UXTB:
value &= 0xff;
break;
case UXTH:
value &= 0xffff;
break;
case UXTW:
value &= 0xffffffff;
break;
case SXTB:
value = (value << 56) >> 56;
break;
case SXTH:
value = (value << 48) >> 48;
break;
case SXTW:
value = (value << 32) >> 32;
break;
case UXTX:
case SXTX:
break;
default:
UNREACHABLE();
}
int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask;
return (value << amount) & mask;
}
int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) {
const Register rm = instr->RmField();
const int64_t rm_val = get_register(rm, R31IsZR);
const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits;
if (instr->IsShift()) {
const Shift shift_type = instr->ShiftTypeField();
const uint8_t shift_amount = instr->Imm6Field();
return ShiftOperand(size, rm_val, shift_type, shift_amount);
} else {
ASSERT(instr->IsExtend());
const Extend extend_type = instr->ExtendTypeField();
const uint8_t shift_amount = instr->Imm3Field();
return ExtendOperand(size, rm_val, extend_type, shift_amount);
}
UNREACHABLE();
return -1;
}
void Simulator::DecodeAddSubShiftExt(Instr* instr) {
switch (instr->Bit(30)) {
case 0: {
// Format(instr, "add'sf's 'rd, 'rn, 'shift_op");
const Register rd = instr->RdField();
const Register rn = instr->RnField();
const int64_t rm_val = DecodeShiftExtendOperand(instr);
if (instr->SFField()) {
// 64-bit add.
const int64_t rn_val = get_register(rn, instr->RnMode());
const int64_t alu_out = rn_val + rm_val;
set_register(rd, alu_out, instr->RdMode());
if (instr->HasS()) {
SetNZFlagsX(alu_out);
SetCFlag(CarryFromX(rn_val, rm_val));
SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, true));
}
} else {
// 32-bit add.
const int32_t rn_val = get_wregister(rn, instr->RnMode());
const int32_t rm_val32 = static_cast<int32_t>(rm_val & kWRegMask);
const int32_t alu_out = rn_val + rm_val32;
set_wregister(rd, alu_out, instr->RdMode());
if (instr->HasS()) {
SetNZFlagsW(alu_out);
SetCFlag(CarryFromW(rn_val, rm_val32));
SetVFlag(OverflowFromW(alu_out, rn_val, rm_val32, true));
}
}
break;
}
default:
UnimplementedInstruction(instr);
break;
}
}
void Simulator::DecodeDPRegister(Instr* instr) {
if (instr->IsAddSubShiftExtOp()) {
DecodeAddSubShiftExt(instr);
} else {
UnimplementedInstruction(instr);
}
}
void Simulator::DecodeDPSimd1(Instr* instr) {
UnimplementedInstruction(instr);
}
void Simulator::DecodeDPSimd2(Instr* instr) {
UnimplementedInstruction(instr);
}
// Executes the current instruction.
void Simulator::InstructionDecode(Instr* instr) {
pc_modified_ = false;
if (FLAG_trace_sim) {
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
Disassembler::Disassemble(start, end);
}
if (instr->IsDPImmediateOp()) {
DecodeDPImmediate(instr);
} else if (instr->IsCompareBranchOp()) {
DecodeCompareBranch(instr);
} else if (instr->IsLoadStoreOp()) {
DecodeLoadStore(instr);
} else if (instr->IsDPRegisterOp()) {
DecodeDPRegister(instr);
} else if (instr->IsDPSimd1Op()) {
DecodeDPSimd1(instr);
} else {
ASSERT(instr->IsDPSimd2Op());
DecodeDPSimd2(instr);
}
if (!pc_modified_) {
set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize);
}
}
void Simulator::Execute() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
uword program_counter = get_pc();
if (FLAG_stop_sim_at == 0) {
// Fast version of the dispatch loop without checking whether the simulator
// should be stopping at a particular executed instruction.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
}
} else {
// FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
// we reach the particular instruction count.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (icount_ == FLAG_stop_sim_at) {
// TODO(zra): Add a debugger.
UNIMPLEMENTED();
} else if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
}
}
}
int64_t Simulator::Call(int64_t entry,
int64_t parameter0,
int64_t parameter1,
int64_t parameter2,
int64_t parameter3) {
// Save the SP register before the call so we can restore it.
int32_t sp_before_call = get_register(SP, R31IsSP);
// Setup parameters.
set_register(R0, parameter0);
set_register(R1, parameter1);
set_register(R2, parameter2);
set_register(R3, parameter3);
// Make sure the activation frames are properly aligned.
int32_t stack_pointer = sp_before_call;
if (OS::ActivationFrameAlignment() > 1) {
stack_pointer =
Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
}
set_register(SP, stack_pointer, R31IsSP);
// Prepare to execute the code at entry.
set_pc(entry);
// Put down marker for end of simulation. The simulator will stop simulation
// when the PC reaches this value. By saving the "end simulation" value into
// the LR the simulation stops when returning to this call point.
set_register(LR, kEndSimulatingPC);
// Remember the values of callee-saved registers.
int64_t r19_val = get_register(R19);
int64_t r20_val = get_register(R20);
int64_t r21_val = get_register(R21);
int64_t r22_val = get_register(R22);
int64_t r23_val = get_register(R23);
int64_t r24_val = get_register(R24);
int64_t r25_val = get_register(R25);
int64_t r26_val = get_register(R26);
int64_t r27_val = get_register(R27);
int64_t r28_val = get_register(R28);
int64_t r29_val = get_register(R29);
// Setup the callee-saved registers with a known value. To be able to check
// that they are preserved properly across dart execution.
int64_t callee_saved_value = icount_;
set_register(R19, callee_saved_value);
set_register(R20, callee_saved_value);
set_register(R21, callee_saved_value);
set_register(R22, callee_saved_value);
set_register(R23, callee_saved_value);
set_register(R24, callee_saved_value);
set_register(R25, callee_saved_value);
set_register(R26, callee_saved_value);
set_register(R27, callee_saved_value);
set_register(R28, callee_saved_value);
set_register(R29, callee_saved_value);
// Start the simulation
Execute();
// Check that the callee-saved registers have been preserved.
ASSERT(callee_saved_value == get_register(R19));
ASSERT(callee_saved_value == get_register(R20));
ASSERT(callee_saved_value == get_register(R21));
ASSERT(callee_saved_value == get_register(R22));
ASSERT(callee_saved_value == get_register(R23));
ASSERT(callee_saved_value == get_register(R24));
ASSERT(callee_saved_value == get_register(R25));
ASSERT(callee_saved_value == get_register(R26));
ASSERT(callee_saved_value == get_register(R27));
ASSERT(callee_saved_value == get_register(R28));
ASSERT(callee_saved_value == get_register(R29));
// Restore callee-saved registers with the original value.
set_register(R19, r19_val);
set_register(R20, r20_val);
set_register(R21, r21_val);
set_register(R22, r22_val);
set_register(R23, r23_val);
set_register(R24, r24_val);
set_register(R25, r25_val);
set_register(R26, r26_val);
set_register(R27, r27_val);
set_register(R28, r28_val);
set_register(R29, r29_val);
// Restore the SP register and return R1:R0.
set_register(SP, sp_before_call, R31IsSP);
int64_t return_value;
return_value = get_register(R0);
return return_value;
}
} // namespace dart
#endif // !defined(HOST_ARCH_ARM64)
#endif // defined TARGET_ARCH_ARM64

View file

@ -0,0 +1,160 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Declares a Simulator for ARM64 instructions if we are not generating a native
// ARM64 binary. This Simulator allows us to run and debug ARM64 code generation
// on regular desktop machines.
// Dart calls into generated code by "calling" the InvokeDartCode stub,
// which will start execution in the Simulator or forwards to the real entry
// on a ARM64 HW platform.
#ifndef VM_SIMULATOR_ARM64_H_
#define VM_SIMULATOR_ARM64_H_
#ifndef VM_SIMULATOR_H_
#error Do not include simulator_arm64.h directly; use simulator.h.
#endif
#include "vm/constants_arm64.h"
#include "vm/object.h"
namespace dart {
class Isolate;
class Simulator {
public:
static const uword kSimulatorStackUnderflowSize = 64;
Simulator();
~Simulator();
// The currently executing Simulator instance, which is associated to the
// current isolate
static Simulator* Current();
// Accessors for register state.
void set_register(Register reg, int64_t value, R31Type r31t = R31IsUndef);
int64_t get_register(Register reg, R31Type r31t = R31IsUndef) const;
void set_wregister(Register reg, int32_t value, R31Type r31t = R31IsUndef);
int32_t get_wregister(Register reg, R31Type r31t = R31IsUndef) const;
int64_t get_pc() const;
void set_pc(int64_t pc);
// Accessor to the internal simulator stack top.
uword StackTop() const;
// The isolate's top_exit_frame_info refers to a Dart frame in the simulator
// stack. The simulator's top_exit_frame_info refers to a C++ frame in the
// native stack.
uword top_exit_frame_info() const { return top_exit_frame_info_; }
void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
// Call on program start.
static void InitOnce() {}
// Dart generally calls into generated code with 5 parameters. This is a
// convenience function, which sets up the simulator state and grabs the
// result on return. The return value is R0. The parameters are placed in
// R0-3.
int64_t Call(int64_t entry,
int64_t parameter0,
int64_t parameter1,
int64_t parameter2,
int64_t parameter3);
void Longjmp(uword pc,
uword sp,
uword fp,
RawObject* raw_exception,
RawObject* raw_stacktrace) {
UNIMPLEMENTED();
}
private:
// Known bad pc value to ensure that the simulator does not execute
// without being properly setup.
static const uword kBadLR = -1;
// A pc value used to signal the simulator to stop execution. Generally
// the lr is set to this value on transition from native C code to
// simulated execution, so that the simulator can "return" to the native
// C code.
static const uword kEndSimulatingPC = -2;
// CPU state.
int64_t registers_[kNumberOfCpuRegisters];
bool n_flag_;
bool z_flag_;
bool c_flag_;
bool v_flag_;
// Simulator support.
int64_t pc_;
char* stack_;
bool pc_modified_;
intptr_t icount_;
static int64_t flag_stop_sim_at_;
uword top_exit_frame_info_;
// Registered breakpoints.
Instr* break_pc_;
int64_t break_instr_;
// Illegal memory access support.
static bool IsIllegalAddress(uword addr) {
return addr < 64*1024;
}
void HandleIllegalAccess(uword addr, Instr* instr);
// Handles a legal instruction that the simulator does not implement.
void UnimplementedInstruction(Instr* instr);
// Unsupported instructions use Format to print an error and stop execution.
void Format(Instr* instr, const char* format);
// Helper functions to set the conditional flags in the architecture state.
void SetNZFlagsW(int32_t val);
bool CarryFromW(int32_t left, int32_t right);
bool BorrowFromW(int32_t left, int32_t right);
bool OverflowFromW(
int32_t alu_out, int32_t left, int32_t right, bool addition);
void SetNZFlagsX(int64_t val);
bool CarryFromX(int64_t left, int64_t right);
bool BorrowFromX(int64_t left, int64_t right);
bool OverflowFromX(
int64_t alu_out, int64_t left, int64_t right, bool addition);
void SetCFlag(bool val);
void SetVFlag(bool val);
int64_t ShiftOperand(uint8_t reg_size,
int64_t value,
Shift shift_type,
uint8_t amount);
int64_t ExtendOperand(uint8_t reg_size,
int64_t value,
Extend extend_type,
uint8_t amount);
int64_t DecodeShiftExtendOperand(Instr* instr);
// Decode instructions.
void InstructionDecode(Instr* instr);
#define DECODE_OP(op) \
void Decode##op(Instr* instr);
APPLY_OP_LIST(DECODE_OP)
#undef DECODE_OP
// Executes ARM64 instructions until the PC reaches kEndSimulatingPC.
void Execute();
DISALLOW_COPY_AND_ASSIGN(Simulator);
};
} // namespace dart
#endif // VM_SIMULATOR_ARM64_H_

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_debugger_api.h"
#include "platform/assert.h"
#include "vm/bigint_operations.h"
@ -2692,3 +2696,5 @@ UNIT_TEST_CASE(PostCObject) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -15,6 +15,8 @@
#include "vm/stack_frame_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/stack_frame_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/stack_frame_arm64.h"
#elif defined(TARGET_ARCH_MIPS)
#include "vm/stack_frame_mips.h"
#else

View file

@ -0,0 +1,34 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_STACK_FRAME_ARM64_H_
#define VM_STACK_FRAME_ARM64_H_
namespace dart {
// TODO(zra):
// These are the values for ARM. Fill in the values for ARM64 as they are
// needed.
static const int kDartFrameFixedSize = 4; // PP, FP, LR, PC marker.
static const int kSavedPcSlotFromSp = -2;
static const int kFirstObjectSlotFromFp = -1; // Used by GC to traverse stack.
static const int kFirstLocalSlotFromFp = -2;
static const int kSavedCallerPpSlotFromFp = -1;
static const int kSavedCallerFpSlotFromFp = 0;
static const int kSavedCallerPcSlotFromFp = 1;
static const int kPcMarkerSlotFromFp = 2;
static const int kParamEndSlotFromFp = 2; // One slot past last parameter.
static const int kCallerSpSlotFromFp = 3;
// Entry and exit frame layout.
static const int kSavedContextSlotFromEntryFp = -27;
static const int kExitLinkSlotFromEntryFp = -26;
static const int kSavedVMTagSlotFromEntryFp = -25;
} // namespace dart
#endif // VM_STACK_FRAME_ARM64_H_

View file

@ -2,6 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(zra): Remove when tests are ready to enable.
#include "platform/globals.h"
#if !defined(TARGET_ARCH_ARM64)
#include "include/dart_api.h"
#include "platform/assert.h"
#include "vm/class_finalizer.h"
@ -288,3 +292,5 @@ TEST_CASE(ValidateNoSuchMethodStackFrameIteration) {
}
} // namespace dart
#endif // !defined(TARGET_ARCH_ARM64)

View file

@ -5,6 +5,7 @@
#include "vm/stub_code.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/assembler.h"
#include "vm/disassembler.h"
#include "vm/flags.h"
@ -50,9 +51,12 @@ StubCode::~StubCode() {
void StubCode::InitOnce() {
// TODO(zra): ifndef to be removed when ARM64 port is ready.
#if !defined(TARGET_ARCH_ARM64)
// Generate all the stubs.
Code& code = Code::Handle();
VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
#endif
}
@ -66,9 +70,12 @@ void StubCode::GenerateFor(Isolate* init) {
void StubCode::Init(Isolate* isolate) {
// TODO(zra): ifndef to be removed when ARM64 port is ready.
#if !defined(TARGET_ARCH_ARM64)
StubCode* stubs = new StubCode();
isolate->set_stub_code(stubs);
stubs->GenerateFor(isolate);
#endif
}

View file

@ -0,0 +1,249 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
#include "vm/assembler.h"
#include "vm/code_generator.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/flow_graph_compiler.h"
#include "vm/heap.h"
#include "vm/instructions.h"
#include "vm/object_store.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/tags.h"
#define __ assembler->
namespace dart {
void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
const Class& cls) {
UNIMPLEMENTED();
}
void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
Register temp_reg) {
UNIMPLEMENTED();
}
void StubCode::GenerateNArgsCheckInlineCacheStub(
Assembler* assembler,
intptr_t num_args,
const RuntimeEntry& handle_ic_miss) {
UNIMPLEMENTED();
}
void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
const Register left,
const Register right,
const Register temp,
const Register unused) {
UNIMPLEMENTED();
}
void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
Assembler* assembler) {
UNIMPLEMENTED();
}
void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
Assembler* assembler) {
UNIMPLEMENTED();
}
} // namespace dart
#endif // defined TARGET_ARCH_ARM64

View file

@ -0,0 +1,10 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_ARM64)
// TODO(zra): Port these tests.
#endif // defined TARGET_ARCH_ARM64

View file

@ -2,13 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <stdio.h>
#include "vm/unit_test.h"
#include <stdio.h>
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "platform/globals.h"
#include "vm/assembler.h"
#include "vm/ast_printer.h"
#include "vm/compiler.h"
@ -25,7 +26,6 @@ namespace dart {
DECLARE_FLAG(bool, disassemble);
TestCaseBase* TestCaseBase::first_ = NULL;
TestCaseBase* TestCaseBase::tail_ = NULL;
@ -48,6 +48,8 @@ void TestCaseBase::RunAll() {
}
}
// TODO(zra): Remove when tests that need these functions are ready to enable.
#if !defined(TARGET_ARCH_ARM64)
static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
@ -142,6 +144,7 @@ Dart_Handle TestCase::library_handler(Dart_LibraryTag tag,
return Api::Success();
}
#endif
void AssemblerTest::Assemble() {
const String& function_name = String::ZoneHandle(Symbols::New(name_));
@ -166,6 +169,9 @@ void AssemblerTest::Assemble() {
}
// TODO(zra): Remove once supported.
#if !defined(TARGET_ARCH_ARM64)
CodeGenTest::CodeGenTest(const char* name)
: function_(Function::ZoneHandle()),
node_sequence_(new SequenceNode(Scanner::kNoSourcePos,
@ -233,4 +239,6 @@ bool CompilerTest::TestCompileFunction(const Function& function) {
return error.IsNull();
}
#endif // !defined(TARGET_ARCH_ARM64)
} // namespace dart

View file

@ -7,6 +7,8 @@
#include "include/dart_api.h"
#include "platform/globals.h"
#include "vm/ast.h"
#include "vm/dart.h"
#include "vm/globals.h"
@ -130,8 +132,12 @@
}
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_MIPS)
#if defined(TARGET_ARCH_ARM) || \
defined(TARGET_ARCH_MIPS) || \
defined(TARGET_ARCH_ARM64)
#if defined(HOST_ARCH_ARM) || \
defined(HOST_ARCH_MIPS) || \
defined(HOST_ARCH_ARM64)
// Running on actual ARM or MIPS hardware, execute code natively.
#define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
@ -144,9 +150,16 @@
reinterpret_cast<name>(entry)(double_arg)
#else
// Not running on ARM or MIPS hardware, call simulator to execute code.
#if defined(ARCH_IS_64_BIT)
// TODO(zra): Supply more macros for 64-bit as tests are added for ARM64.
#define EXECUTE_TEST_CODE_INT32(name, entry) \
static_cast<int32_t>(Simulator::Current()->Call( \
bit_cast<int64_t, uword>(entry), 0, 0, 0, 0))
#else
#define EXECUTE_TEST_CODE_INT32(name, entry) \
static_cast<int32_t>(Simulator::Current()->Call( \
bit_cast<int32_t, uword>(entry), 0, 0, 0, 0))
#endif
#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
static_cast<int64_t>(Simulator::Current()->Call( \
bit_cast<int32_t, uword>(entry), \

View file

@ -14,6 +14,9 @@
'assembler_arm.cc',
'assembler_arm.h',
'assembler_arm_test.cc',
'assembler_arm64.cc',
'assembler_arm64.h',
'assembler_arm64_test.cc',
'assembler_ia32.cc',
'assembler_ia32.h',
'assembler_ia32_test.cc',
@ -77,6 +80,8 @@
'code_patcher.h',
'code_patcher_arm.cc',
'code_patcher_arm_test.cc',
'code_patcher_arm64.cc',
'code_patcher_arm64_test.cc',
'code_patcher_ia32.cc',
'code_patcher_ia32_test.cc',
'code_patcher_mips.cc',
@ -89,6 +94,7 @@
'compiler_stats.h',
'compiler_test.cc',
'constants_arm.h',
'constants_arm64.h',
'constants_ia32.h',
'constants_mips.h',
'constants_x64.h',
@ -96,6 +102,7 @@
'coverage.h',
'cpu.h',
'cpu_arm.cc',
'cpu_arm64.cc',
'cpu_ia32.cc',
'cpu_mips.cc',
'cpu_test.cc',
@ -124,6 +131,7 @@
'debugger.h',
'debugger_api_impl_test.cc',
'debugger_arm.cc',
'debugger_arm64.cc',
'debugger_ia32.cc',
'debugger_mips.cc',
'debugger_x64.cc',
@ -137,6 +145,7 @@
'disassembler.cc',
'disassembler.h',
'disassembler_arm.cc',
'disassembler_arm64.cc',
'disassembler_ia32.cc',
'disassembler_mips.cc',
'disassembler_test.cc',
@ -160,6 +169,7 @@
'flow_graph_compiler.cc',
'flow_graph_compiler.h',
'flow_graph_compiler_arm.cc',
'flow_graph_compiler_arm64.cc',
'flow_graph_compiler_ia32.cc',
'flow_graph_compiler_mips.cc',
'flow_graph_compiler_x64.cc',
@ -199,6 +209,9 @@
'instructions_arm.cc',
'instructions_arm.h',
'instructions_arm_test.cc',
'instructions_arm64.cc',
'instructions_arm64.h',
'instructions_arm64_test.cc',
'instructions_ia32.cc',
'instructions_ia32.h',
'instructions_ia32_test.cc',
@ -211,6 +224,7 @@
'intermediate_language.cc',
'intermediate_language.h',
'intermediate_language_arm.cc',
'intermediate_language_arm64.cc',
'intermediate_language_ia32.cc',
'intermediate_language_mips.cc',
'intermediate_language_test.cc',
@ -218,6 +232,7 @@
'intrinsifier.cc',
'intrinsifier.h',
'intrinsifier_arm.cc',
'intrinsifier_arm64.cc',
'intrinsifier_ia32.cc',
'intrinsifier_mips.cc',
'intrinsifier_x64.cc',
@ -258,6 +273,7 @@
'object.cc',
'object.h',
'object_arm_test.cc',
'object_arm64_test.cc',
'object_ia32_test.cc',
'object_id_ring.cc',
'object_id_ring.h',
@ -300,6 +316,7 @@
'reusable_handles.h',
'runtime_entry.h',
'runtime_entry_arm.cc',
'runtime_entry_arm64.cc',
'runtime_entry_ia32.cc',
'runtime_entry_mips.cc',
'runtime_entry_test.cc',
@ -323,6 +340,8 @@
'simulator.h',
'simulator_arm.cc',
'simulator_arm.h',
'simulator_arm64.cc',
'simulator_arm64.h',
'simulator_mips.cc',
'simulator_mips.h',
'snapshot.cc',
@ -332,6 +351,7 @@
'stack_frame.cc',
'stack_frame.h',
'stack_frame_arm.h',
'stack_frame_arm64.h',
'stack_frame_ia32.h',
'stack_frame_mips.h',
'stack_frame_test.cc',
@ -342,6 +362,8 @@
'stub_code.h',
'stub_code_arm.cc',
'stub_code_arm_test.cc',
'stub_code_arm64.cc',
'stub_code_arm64_test.cc',
'stub_code_ia32.cc',
'stub_code_ia32_test.cc',
'stub_code_mips.cc',

View file

@ -79,3 +79,6 @@ LibTest/collection/ListBase/ListBase_class_A01_t01: Skip # Timeouts
[ $runtime == vm ]
LibTest/isolate/Isolate/spawn_A02_t01: Skip # co19 issue 667
[ $compiler == none && $runtime == vm && $arch == simarm64 ]
*: Skip

View file

@ -143,6 +143,9 @@ int_parse_radix_test: Skip # Timeout
[ $arch == simarm && $checked ]
num_parse_test: Pass, Timeout
[ $arch == simarm64 ]
*: Skip
[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
error_stack_trace_test: StaticWarning, OK # Test generates errors on purpose.
iterable_element_at_test: StaticWarning, OK # Test generates errors on purpose.

View file

@ -9,6 +9,9 @@ isolate_stress_test: Fail # Issue 12588: This should be able to pass when we hav
[ $runtime == vm && $arch == mips && $mode == debug ]
mandel_isolate_test: Skip # Uses 600 MB Ram on our 1 GB test device.
[ $runtime == vm && $arch == simarm64 ]
*: Skip
[ $compiler == none || $compiler == dart2dart ]
serialization_test: SkipByDesign # Tests dart2js-specific serialization code
isolate_throws_test/01: Skip # Issue 12587

View file

@ -134,3 +134,6 @@ generic_instanceof3_test: Pass, Crash # Issue 17440.
[ $compiler == none && $runtime == vm && $arch == mips && $mode == debug ]
stack_overflow_test: Skip # Crashes. Issue 17440.
stack_overflow_stacktrace_test: Skip # Crashes. Issue 17440.
[ $compiler == none && $runtime == vm && $arch == simarm64 ]
*: Skip

View file

@ -283,6 +283,9 @@ convert/streamed_conversion_json_utf8_decode_test: Pass, Slow
convert/chunked_conversion_utf88_test: Pass, Slow # Issue 12644.
convert/utf85_test: Pass, Slow # Issue 12644.
[ $arch == simarm64 ]
*: Skip
[ $compiler == none && $runtime == dartium ]
async/schedule_microtask5_test: Pass, Timeout # Issue 13719: Please triage this failure.
async/timer_cancel2_test: Pass, Timeout # Issue 13719: Please triage this failure.

View file

@ -119,6 +119,9 @@ io/signals_test: Skip # Starts 10 dart subprocesses, uses too much memory
[ $arch == mips && $mode == debug ]
io/file_read_special_device_test: Fail # dartbug.com/17440
[ $arch == simarm64 ]
*: Skip
[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
assert_test: Fail # Issue 13719: Please triage this failure.

View file

@ -18,3 +18,6 @@ dart2js_test: Skip # Uses dart:io.
[ $compiler == dart2js && $mode == debug ]
source_mirrors_test: Slow, Pass
[ $compiler == none && $runtime == vm && $arch == simarm64 ]
*: Skip

View file

@ -44,7 +44,7 @@ def BuildOptions():
default=False, action="store_true")
result.add_option("-a", "--arch",
help='Target architectures (comma-separated).',
metavar='[all,ia32,x64,simarm,arm,simmips,mips]',
metavar='[all,ia32,x64,simarm,arm,simmips,mips,simarm64]',
default=utils.GuessArchitecture())
result.add_option("--os",
help='Target OSs (comma-separated).',
@ -76,7 +76,7 @@ def ProcessOsOption(os):
def ProcessOptions(options, args):
if options.arch == 'all':
options.arch = 'ia32,x64,simarm,simmips'
options.arch = 'ia32,x64,simarm,simmips,simarm64'
if options.mode == 'all':
options.mode = 'release,debug'
if options.os == 'all':
@ -89,7 +89,8 @@ def ProcessOptions(options, args):
print "Unknown mode %s" % mode
return False
for arch in options.arch:
if not arch in ['ia32', 'x64', 'simarm', 'arm', 'simmips', 'mips']:
archs = ['ia32', 'x64', 'simarm', 'arm', 'simmips', 'mips', 'simarm64']
if not arch in archs:
print "Unknown arch %s" % arch
return False
options.os = [ProcessOsOption(os) for os in options.os]

View file

@ -18,6 +18,7 @@
['"<(target_arch)"=="x64"', { 'dart_target_arch': 'X64', }],
['"<(target_arch)"=="arm"', { 'dart_target_arch': 'ARM', }],
['"<(target_arch)"=="simarm"', { 'dart_target_arch': 'SIMARM', }],
['"<(target_arch)"=="simarm64"', { 'dart_target_arch': 'SIMARM64', }],
['"<(target_arch)"=="mips"', { 'dart_target_arch': 'MIPS', }],
['"<(target_arch)"=="simmips"', { 'dart_target_arch': 'SIMMIPS', }],
[ 'OS=="linux"', { 'dart_target_os': 'Linux', } ],
@ -59,6 +60,13 @@
]
},
'Dart_simarm64_Base': {
'abstract': 1,
'defines': [
'TARGET_ARCH_ARM64',
]
},
'Dart_arm_Base': {
'abstract': 1,
'defines': [
@ -150,6 +158,27 @@
],
},
'DebugSIMARM64': {
'inherit_from': [
'Dart_Base', 'Dart_simarm64_Base', 'Dart_Debug',
'Dart_<(dart_target_os)_Base',
'Dart_<(dart_target_os)_simarm64_Base',
'Dart_<(dart_target_os)_Debug',
],
'defines': [
'DEBUG',
],
},
'ReleaseSIMARM64': {
'inherit_from': [
'Dart_Base', 'Dart_simarm64_Base', 'Dart_Release',
'Dart_<(dart_target_os)_Base',
'Dart_<(dart_target_os)_simarm64_Base',
'Dart_<(dart_target_os)_Release',
],
},
'DebugSIMMIPS': {
'inherit_from': [
'Dart_Base', 'Dart_simmips_Base', 'Dart_Debug',

View file

@ -49,6 +49,15 @@
],
},
'Dart_Linux_simarm64_Base': {
'abstract': 1,
'cflags': [ '-O3', '-m64', '-msse2' ],
'ldflags': [ '-m64', ],
'defines': [
'ARM64_FLOAT_ABI_HARD',
],
},
# ARM cross-build
'Dart_Linux_xarm_Base': {
'abstract': 1,

View file

@ -107,7 +107,8 @@ class TestOptionsParser {
'arch',
'The architecture to run tests for',
['-a', '--arch'],
['all', 'ia32', 'x64', 'simarm', 'simmips', 'arm', 'mips'],
['all', 'ia32', 'x64', 'arm', 'mips',
'simarm', 'simarm64', 'simmips'],
'ia32'),
new _TestOptionSpecification(
'system',
@ -634,7 +635,7 @@ Note: currently only implemented for dart2js.''',
List<Map> _expandConfigurations(Map configuration) {
// Expand the pseudo-values such as 'all'.
if (configuration['arch'] == 'all') {
configuration['arch'] = 'ia32,x64,simarm,simmips';
configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips';
}
if (configuration['mode'] == 'all') {
configuration['mode'] = 'debug,release';

View file

@ -220,6 +220,7 @@ ARCH_FAMILY = {
'mips': 'mips',
'simarm': 'ia32',
'simmips': 'ia32',
'simarm64': 'ia32',
}
ARCH_GUESS = GuessArchitecture()

View file

@ -14,6 +14,9 @@ peg_test: Skip
[ $arch == simarm ]
*: Skip
[ $arch == simarm64 ]
*: Skip
[ $arch == mips ]
*: Skip