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

Side by Side 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 TODOs Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #ifndef VM_ASSEMBLER_ARM64_H_
6 #define VM_ASSEMBLER_ARM64_H_
7
8 #ifndef VM_ASSEMBLER_H_
9 #error Do not include assembler_arm64.h directly; use assembler.h instead.
10 #endif
11
12 #include "platform/assert.h"
13 #include "platform/utils.h"
14 #include "vm/constants_arm64.h"
15 #include "vm/object.h"
16 #include "vm/simulator.h"
17
18 namespace dart {
19
20 // Forward declarations.
21 class RuntimeEntry;
22
23 // TODO(zra): Label, Address, and FieldAddress are copied from ARM,
24 // they must be adapted to ARM64.
25 class Label : public ValueObject {
26 public:
27 Label() : position_(0) { }
28
29 ~Label() {
30 // Assert if label is being destroyed with unresolved branches pending.
31 ASSERT(!IsLinked());
32 }
33
34 // Returns the position for bound and linked labels. Cannot be used
35 // for unused labels.
36 intptr_t Position() const {
37 ASSERT(!IsUnused());
38 return IsBound() ? -position_ - kWordSize : position_ - kWordSize;
39 }
40
41 bool IsBound() const { return position_ < 0; }
42 bool IsUnused() const { return position_ == 0; }
43 bool IsLinked() const { return position_ > 0; }
44
45 private:
46 intptr_t position_;
47
48 void Reinitialize() {
49 position_ = 0;
50 }
51
52 void BindTo(intptr_t position) {
53 ASSERT(!IsBound());
54 position_ = -position - kWordSize;
55 ASSERT(IsBound());
56 }
57
58 void LinkTo(intptr_t position) {
59 ASSERT(!IsBound());
60 position_ = position + kWordSize;
61 ASSERT(IsLinked());
62 }
63
64 friend class Assembler;
65 DISALLOW_COPY_AND_ASSIGN(Label);
66 };
67
68
69 class Address : public ValueObject {
70 public:
71 Address(const Address& other)
72 : ValueObject(), encoding_(other.encoding_) {
73 }
74
75 Address& operator=(const Address& other) {
76 encoding_ = other.encoding_;
77 return *this;
78 }
79
80 Address(Register rn, int32_t offset = 0) {
81 ASSERT(Utils::IsAbsoluteUint(12, offset));
82 encoding_ = -1;
83 }
84
85 private:
86 uint32_t encoding() const { return encoding_; }
87
88 uint32_t encoding_;
89
90 friend class Assembler;
91 };
92
93
94 class FieldAddress : public Address {
95 public:
96 FieldAddress(Register base, int32_t disp)
97 : Address(base, disp - kHeapObjectTag) { }
98
99 FieldAddress(const FieldAddress& other) : Address(other) { }
100
101 FieldAddress& operator=(const FieldAddress& other) {
102 Address::operator=(other);
103 return *this;
104 }
105 };
106
107
108 // Shift or Extend operand for ADD and SUB.
109 class AddSubOperand : public ValueObject {
regis 2014/04/01 22:25:15 Is AddSubOperand a good name? There are more instr
zra 2014/04/02 00:04:25 I had anticipated the bitfield immediate operand t
110 public:
111 // Data-processing operand - Uninitialized.
112 AddSubOperand() : encoding_(-1) { }
113
114 // Data-processing operands - Copy constructor.
115 AddSubOperand(const AddSubOperand& other)
116 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { }
117
118 explicit AddSubOperand(Register rm) {
119 encoding_ = (static_cast<int32_t>(rm) << kRmShift);
120 }
121
122 AddSubOperand(Register rm, Shift shift, int32_t imm) {
123 ASSERT(Utils::IsUint(6, imm));
124 encoding_ =
125 (imm << kImm6Shift) |
126 (static_cast<int32_t>(rm) << kRmShift) |
127 (static_cast<int32_t>(shift) << kShiftTypeShift);
128 type_ = ASShifted;
129 }
130
131 AddSubOperand(Register rm, Extend extend, int32_t imm) {
132 ASSERT(Utils::IsUint(3, imm));
133 encoding_ =
134 B21 |
135 (static_cast<int32_t>(rm) << kRmShift) |
136 (static_cast<int32_t>(extend) << kExtendTypeShift) |
137 ((imm & 0x7) << kImm3Shift);
138 type_ = ASExtended;
139 }
140
141 explicit AddSubOperand(int32_t imm) {
142 if (Utils::IsUint(12, imm)) {
143 encoding_ = imm << kImm12Shift;
144 } else {
145 // imm only has bits in [12, 24) set.
146 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12)));
147 encoding_ = B22 | ((imm >> 12) << kImm12Shift);
148 }
149 type_ = ASImmediate;
150 }
151
152 enum ASOpType {
regis 2014/04/01 22:25:15 Does this mean AddSubOperandType? How about Opera
zra 2014/04/02 00:04:25 Done.
153 ASShifted,
154 ASExtended,
155 ASImmediate,
156 };
157
158 private:
159 uint32_t encoding() const {
160 return encoding_;
161 }
162 ASOpType type() const {
163 return type_;
164 }
165
166 uint32_t encoding_;
167 ASOpType type_;
168
169 friend class Assembler;
170 };
171
172
173 class Assembler : public ValueObject {
174 public:
175 explicit Assembler(bool use_far_branches = false)
176 : buffer_(),
177 object_pool_(GrowableObjectArray::Handle()),
178 prologue_offset_(-1),
179 use_far_branches_(use_far_branches),
180 comments_() { }
181 ~Assembler() { }
182
183 void PopRegister(Register r) {
184 UNIMPLEMENTED();
185 }
186
187 void Drop(intptr_t stack_elements) {
188 UNIMPLEMENTED();
189 }
190
191 void Bind(Label* label) {
192 UNIMPLEMENTED();
193 }
194
195 // Misc. functionality
196 intptr_t CodeSize() const { return buffer_.Size(); }
197 intptr_t prologue_offset() const { return prologue_offset_; }
198
199 // Count the fixups that produce a pointer offset, without processing
200 // the fixups. On ARM64 there are no pointers in code.
201 intptr_t CountPointerOffsets() const { return 0; }
202
203 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
204 ASSERT(buffer_.pointer_offsets().length() == 0); // No pointers in code.
205 return buffer_.pointer_offsets();
206 }
207 const GrowableObjectArray& object_pool() const { return object_pool_; }
208
209 bool use_far_branches() const {
210 return FLAG_use_far_branches || use_far_branches_;
211 }
212
213 void set_use_far_branches(bool b) {
214 ASSERT(buffer_.Size() == 0);
215 use_far_branches_ = b;
216 }
217
218 void FinalizeInstructions(const MemoryRegion& region) {
219 buffer_.FinalizeInstructions(region);
220 }
221
222 // Debugging and bringup support.
223 void Stop(const char* message);
224 void Unimplemented(const char* message);
225 void Untested(const char* message);
226 void Unreachable(const char* message);
227
228 static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
229
230 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
231
232 const Code::Comments& GetCodeComments() const;
233
234 static const char* RegisterName(Register reg);
235
236 static const char* FpuRegisterName(FpuRegister reg);
237
238 // TODO(zra): Make sure this is right.
239 // Instruction pattern from entrypoint is used in Dart frame prologs
240 // to set up the frame and save a PC which can be used to figure out the
241 // RawInstruction object corresponding to the code running in the frame.
242 static const intptr_t kEntryPointToPcMarkerOffset = 0;
243
244 // Emit data (e.g encoded instruction or immediate) in instruction stream.
245 void Emit(int32_t value);
246
247 // On some other platforms, we draw a distinction between safe and unsafe
248 // smis.
249 static bool IsSafe(const Object& object) { return true; }
250 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
251
252 // Add unsigned immediate.
253 // shifted = true => imm left-shifted by 12 then added.
254 void addi(OperandSize os, Register rd, Register rn, AddSubOperand aso) {
regis 2014/04/01 22:25:15 Passing OperandSize explicitly seems strange to me
zra 2014/04/02 00:04:25 Since add() become more complicated, I added a hel
255 ASSERT(aso.type() == AddSubOperand::ASImmediate);
regis 2014/04/01 22:25:15 We will probably have a "macro" instruction AddImm
zra 2014/04/02 00:04:25 Done.
256 EmitAddSubImmOp(ADDI, rd, rn, aso, os, false);
257 }
258
259 // Add register.
260 void add(OperandSize os, Register rd, Register rn, AddSubOperand aso) {
261 ASSERT(aso.type() != AddSubOperand::ASImmediate);
262 EmitAddSubShiftExtOp(ADD, rd, rn, aso, os, false);
263 }
264
265 // Function return.
266 void ret(Register rn = R30) {
267 EmitUnconditionalBranchRegOp(RET, rn);
268 }
269
270 private:
271 AssemblerBuffer buffer_; // Contains position independent code.
272 GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
273 int32_t prologue_offset_;
274
275 bool use_far_branches_;
276
277 class CodeComment : public ZoneAllocated {
278 public:
279 CodeComment(intptr_t pc_offset, const String& comment)
280 : pc_offset_(pc_offset), comment_(comment) { }
281
282 intptr_t pc_offset() const { return pc_offset_; }
283 const String& comment() const { return comment_; }
284
285 private:
286 intptr_t pc_offset_;
287 const String& comment_;
288
289 DISALLOW_COPY_AND_ASSIGN(CodeComment);
290 };
291
292 GrowableArray<CodeComment*> comments_;
293
294 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn,
295 AddSubOperand aso, OperandSize os, bool set_flags) {
296 ASSERT((os == kDoubleWord) || (os == kWord));
297 const int32_t size = (os == kDoubleWord) ? B31 : 0;
298 const int32_t s = set_flags ? B29 : 0;
299 const int32_t encoding =
300 op | size | s |
301 (static_cast<int32_t>(rd) << kRdShift) |
302 (static_cast<int32_t>(rn) << kRnShift) |
303 aso.encoding();
304 Emit(encoding);
305 }
306
307 void EmitAddSubShiftExtOp(AddSubShiftExtOp op,
308 Register rd, Register rn, AddSubOperand aso,
309 OperandSize os, bool set_flags) {
310 ASSERT((os == kDoubleWord) || (os == kWord));
311 const int32_t size = (os == kDoubleWord) ? B31 : 0;
312 const int32_t s = set_flags ? B29 : 0;
313 const int32_t encoding =
314 op | size | s |
315 (static_cast<int32_t>(rd) << kRdShift) |
316 (static_cast<int32_t>(rn) << kRnShift) |
317 aso.encoding();
318 Emit(encoding);
319 }
320
321 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) {
322 const int32_t encoding =
323 op | (static_cast<int32_t>(rn) << kRnShift);
324 Emit(encoding);
325 }
326
327 DISALLOW_ALLOCATION();
328 DISALLOW_COPY_AND_ASSIGN(Assembler);
329 };
330
331 } // namespace dart
332
333 #endif // VM_ASSEMBLER_ARM64_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698