| 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 |