OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_ASSEMBLER_ARM64_H_ | 5 #ifndef VM_ASSEMBLER_ARM64_H_ |
6 #define VM_ASSEMBLER_ARM64_H_ | 6 #define VM_ASSEMBLER_ARM64_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_arm64.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 Operand() : encoding_(-1), type_(Unknown) { } | 111 Operand() : encoding_(-1), type_(Unknown) { } |
112 | 112 |
113 // Data-processing operands - Copy constructor. | 113 // Data-processing operands - Copy constructor. |
114 Operand(const Operand& other) | 114 Operand(const Operand& other) |
115 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } | 115 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } |
116 | 116 |
117 explicit Operand(Register rm) { | 117 explicit Operand(Register rm) { |
118 ASSERT((rm != R31) && (rm != SP)); | 118 ASSERT((rm != R31) && (rm != SP)); |
119 const Register crm = ConcreteRegister(rm); | 119 const Register crm = ConcreteRegister(rm); |
120 encoding_ = (static_cast<int32_t>(crm) << kRmShift); | 120 encoding_ = (static_cast<int32_t>(crm) << kRmShift); |
| 121 type_ = Shifted; |
121 } | 122 } |
122 | 123 |
123 Operand(Register rm, Shift shift, int32_t imm) { | 124 Operand(Register rm, Shift shift, int32_t imm) { |
124 ASSERT(Utils::IsUint(6, imm)); | 125 ASSERT(Utils::IsUint(6, imm)); |
125 ASSERT((rm != R31) && (rm != SP)); | 126 ASSERT((rm != R31) && (rm != SP)); |
126 const Register crm = ConcreteRegister(rm); | 127 const Register crm = ConcreteRegister(rm); |
127 encoding_ = | 128 encoding_ = |
128 (imm << kImm6Shift) | | 129 (imm << kImm6Shift) | |
129 (static_cast<int32_t>(crm) << kRmShift) | | 130 (static_cast<int32_t>(crm) << kRmShift) | |
130 (static_cast<int32_t>(shift) << kShiftTypeShift); | 131 (static_cast<int32_t>(shift) << kShiftTypeShift); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 static const intptr_t kEntryPointToPcMarkerOffset = 0; | 253 static const intptr_t kEntryPointToPcMarkerOffset = 0; |
253 | 254 |
254 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 255 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
255 void Emit(int32_t value); | 256 void Emit(int32_t value); |
256 | 257 |
257 // On some other platforms, we draw a distinction between safe and unsafe | 258 // On some other platforms, we draw a distinction between safe and unsafe |
258 // smis. | 259 // smis. |
259 static bool IsSafe(const Object& object) { return true; } | 260 static bool IsSafe(const Object& object) { return true; } |
260 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } | 261 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } |
261 | 262 |
| 263 // Addition and subtraction. |
262 void add(Register rd, Register rn, Operand o) { | 264 void add(Register rd, Register rn, Operand o) { |
263 AddSubHelper(kDoubleWord, false, false, rd, rn, o); | 265 AddSubHelper(kDoubleWord, false, false, rd, rn, o); |
264 } | 266 } |
265 void addw(Register rd, Register rn, Operand o) { | 267 void addw(Register rd, Register rn, Operand o) { |
266 AddSubHelper(kWord, false, false, rd, rn, o); | 268 AddSubHelper(kWord, false, false, rd, rn, o); |
267 } | 269 } |
| 270 void sub(Register rd, Register rn, Operand o) { |
| 271 AddSubHelper(kDoubleWord, false, true, rd, rn, o); |
| 272 } |
| 273 |
| 274 // Move wide immediate. |
| 275 void movk(Register rd, int32_t imm, int32_t hw_idx) { |
| 276 ASSERT(rd != SP); |
| 277 const Register crd = ConcreteRegister(rd); |
| 278 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 279 } |
| 280 void movn(Register rd, int32_t imm, int32_t hw_idx) { |
| 281 ASSERT(rd != SP); |
| 282 const Register crd = ConcreteRegister(rd); |
| 283 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); |
| 284 } |
| 285 void movz(Register rd, int32_t imm, int32_t hw_idx) { |
| 286 ASSERT(rd != SP); |
| 287 const Register crd = ConcreteRegister(rd); |
| 288 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| 289 } |
| 290 |
268 | 291 |
269 // Function return. | 292 // Function return. |
270 void ret(Register rn = R30) { | 293 void ret(Register rn = R30) { |
271 EmitUnconditionalBranchRegOp(RET, rn); | 294 EmitUnconditionalBranchRegOp(RET, rn); |
272 } | 295 } |
273 | 296 |
274 private: | 297 private: |
275 AssemblerBuffer buffer_; // Contains position independent code. | 298 AssemblerBuffer buffer_; // Contains position independent code. |
276 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. | 299 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
277 int32_t prologue_offset_; | 300 int32_t prologue_offset_; |
(...skipping 18 matching lines...) Expand all Loading... |
296 GrowableArray<CodeComment*> comments_; | 319 GrowableArray<CodeComment*> comments_; |
297 | 320 |
298 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, | 321 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, |
299 Register rd, Register rn, Operand o) { | 322 Register rd, Register rn, Operand o) { |
300 ASSERT((rd != R31) && (rn != R31)); | 323 ASSERT((rd != R31) && (rn != R31)); |
301 const Register crd = ConcreteRegister(rd); | 324 const Register crd = ConcreteRegister(rd); |
302 const Register crn = ConcreteRegister(rn); | 325 const Register crn = ConcreteRegister(rn); |
303 if (o.type() == Operand::Immediate) { | 326 if (o.type() == Operand::Immediate) { |
304 ASSERT((rd != ZR) && (rn != ZR)); | 327 ASSERT((rd != ZR) && (rn != ZR)); |
305 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); | 328 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); |
| 329 } else if (o.type() == Operand::Shifted) { |
| 330 ASSERT((rd != SP) && (rn != SP)); |
| 331 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
306 } else { | 332 } else { |
307 if (o.type() == Operand::Shifted) { | 333 ASSERT(o.type() == Operand::Extended); |
308 ASSERT((rd != SP) && (rn != SP)); | 334 ASSERT((rd != SP) && (rn != ZR)); |
309 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | 335 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
310 } else { | |
311 ASSERT(o.type() == Operand::Extended); | |
312 ASSERT((rd != SP) && (rn != ZR)); | |
313 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | |
314 } | |
315 } | 336 } |
316 } | 337 } |
317 | 338 |
318 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, | 339 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, |
319 Operand o, OperandSize os, bool set_flags) { | 340 Operand o, OperandSize os, bool set_flags) { |
320 ASSERT((os == kDoubleWord) || (os == kWord)); | 341 ASSERT((os == kDoubleWord) || (os == kWord)); |
321 const int32_t size = (os == kDoubleWord) ? B31 : 0; | 342 const int32_t size = (os == kDoubleWord) ? B31 : 0; |
322 const int32_t s = set_flags ? B29 : 0; | 343 const int32_t s = set_flags ? B29 : 0; |
323 const int32_t encoding = | 344 const int32_t encoding = |
324 op | size | s | | 345 op | size | s | |
325 (static_cast<int32_t>(rd) << kRdShift) | | 346 (static_cast<int32_t>(rd) << kRdShift) | |
326 (static_cast<int32_t>(rn) << kRnShift) | | 347 (static_cast<int32_t>(rn) << kRnShift) | |
327 o.encoding(); | 348 o.encoding(); |
328 Emit(encoding); | 349 Emit(encoding); |
329 } | 350 } |
330 | 351 |
331 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, | 352 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, |
332 Register rd, Register rn, Operand o, | 353 Register rd, Register rn, Operand o, |
333 OperandSize os, bool set_flags) { | 354 OperandSize sz, bool set_flags) { |
334 ASSERT((os == kDoubleWord) || (os == kWord)); | 355 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
335 const int32_t size = (os == kDoubleWord) ? B31 : 0; | 356 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
336 const int32_t s = set_flags ? B29 : 0; | 357 const int32_t s = set_flags ? B29 : 0; |
337 const int32_t encoding = | 358 const int32_t encoding = |
338 op | size | s | | 359 op | size | s | |
339 (static_cast<int32_t>(rd) << kRdShift) | | 360 (static_cast<int32_t>(rd) << kRdShift) | |
340 (static_cast<int32_t>(rn) << kRnShift) | | 361 (static_cast<int32_t>(rn) << kRnShift) | |
341 o.encoding(); | 362 o.encoding(); |
342 Emit(encoding); | 363 Emit(encoding); |
343 } | 364 } |
344 | 365 |
345 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { | 366 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { |
346 const int32_t encoding = | 367 const int32_t encoding = |
347 op | (static_cast<int32_t>(rn) << kRnShift); | 368 op | (static_cast<int32_t>(rn) << kRnShift); |
348 Emit(encoding); | 369 Emit(encoding); |
349 } | 370 } |
350 | 371 |
| 372 void EmitMoveWideOp(MoveWideOp op, Register rd, int32_t imm, int32_t hw_idx, |
| 373 OperandSize sz) { |
| 374 ASSERT(Utils::IsUint(16, imm)); |
| 375 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); |
| 376 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 377 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 378 const int32_t encoding = |
| 379 op | size | |
| 380 (static_cast<int32_t>(rd) << kRdShift) | |
| 381 (hw_idx << kHWShift) | |
| 382 (imm << kImm16Shift); |
| 383 Emit(encoding); |
| 384 } |
| 385 |
351 DISALLOW_ALLOCATION(); | 386 DISALLOW_ALLOCATION(); |
352 DISALLOW_COPY_AND_ASSIGN(Assembler); | 387 DISALLOW_COPY_AND_ASSIGN(Assembler); |
353 }; | 388 }; |
354 | 389 |
355 } // namespace dart | 390 } // namespace dart |
356 | 391 |
357 #endif // VM_ASSEMBLER_ARM64_H_ | 392 #endif // VM_ASSEMBLER_ARM64_H_ |
OLD | NEW |