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

Unified Diff: runtime/vm/assembler_arm64.h

Issue 221133002: Begins work on ARM64, first assembler test. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: adds files Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/assembler.h ('k') | runtime/vm/assembler_arm64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/assembler_arm64.h
===================================================================
--- runtime/vm/assembler_arm64.h (revision 0)
+++ runtime/vm/assembler_arm64.h (revision 0)
@@ -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_
« no previous file with comments | « runtime/vm/assembler.h ('k') | runtime/vm/assembler_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698