Chromium Code Reviews| 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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 if (Utils::IsUint(12, imm)) { | 210 if (Utils::IsUint(12, imm)) { |
| 211 encoding_ = imm << kImm12Shift; | 211 encoding_ = imm << kImm12Shift; |
| 212 } else { | 212 } else { |
| 213 // imm only has bits in [12, 24) set. | 213 // imm only has bits in [12, 24) set. |
| 214 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); | 214 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); |
| 215 encoding_ = B22 | ((imm >> 12) << kImm12Shift); | 215 encoding_ = B22 | ((imm >> 12) << kImm12Shift); |
| 216 } | 216 } |
| 217 type_ = Immediate; | 217 type_ = Immediate; |
| 218 } | 218 } |
| 219 | 219 |
| 220 // TODO(zra): Add bitfield immediate operand | 220 // Call Assembler::IsImmLogical to find values for these arguments. |
|
regis
2014/04/09 20:49:49
I do not understand this comment.
zra
2014/04/09 22:14:28
Tried to clarify.
| |
| 221 // Operand(int32_t n, int32_t imms, int32_t immr); | 221 Operand(uint8_t n, int8_t imm_s, int8_t imm_r) { |
| 222 ASSERT((n == 1) || (n == 0)); | |
| 223 ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r)); | |
| 224 type_ = BitfieldImm; | |
| 225 encoding_ = | |
| 226 (static_cast<int32_t>(n) << kNShift) | | |
| 227 (static_cast<int32_t>(imm_s) << kImmSShift) | | |
| 228 (static_cast<int32_t>(imm_r) << kImmRShift); | |
| 229 } | |
| 222 | 230 |
| 223 enum OperandType { | 231 enum OperandType { |
| 224 Shifted, | 232 Shifted, |
| 225 Extended, | 233 Extended, |
| 226 Immediate, | 234 Immediate, |
| 227 BitfieldImm, | 235 BitfieldImm, |
| 228 Unknown, | 236 Unknown, |
| 229 }; | 237 }; |
| 230 | 238 |
| 231 private: | 239 private: |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 | 327 |
| 320 // On some other platforms, we draw a distinction between safe and unsafe | 328 // On some other platforms, we draw a distinction between safe and unsafe |
| 321 // smis. | 329 // smis. |
| 322 static bool IsSafe(const Object& object) { return true; } | 330 static bool IsSafe(const Object& object) { return true; } |
| 323 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } | 331 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } |
| 324 | 332 |
| 325 // Addition and subtraction. | 333 // Addition and subtraction. |
| 326 void add(Register rd, Register rn, Operand o) { | 334 void add(Register rd, Register rn, Operand o) { |
| 327 AddSubHelper(kDoubleWord, false, false, rd, rn, o); | 335 AddSubHelper(kDoubleWord, false, false, rd, rn, o); |
| 328 } | 336 } |
| 337 void adds(Register rd, Register rn, Operand o) { | |
| 338 AddSubHelper(kDoubleWord, true, false, rd, rn, o); | |
| 339 } | |
| 329 void addw(Register rd, Register rn, Operand o) { | 340 void addw(Register rd, Register rn, Operand o) { |
| 330 AddSubHelper(kWord, false, false, rd, rn, o); | 341 AddSubHelper(kWord, false, false, rd, rn, o); |
| 331 } | 342 } |
| 332 void sub(Register rd, Register rn, Operand o) { | 343 void sub(Register rd, Register rn, Operand o) { |
| 333 AddSubHelper(kDoubleWord, false, true, rd, rn, o); | 344 AddSubHelper(kDoubleWord, false, true, rd, rn, o); |
| 334 } | 345 } |
| 346 void subs(Register rd, Register rn, Operand o) { | |
| 347 AddSubHelper(kDoubleWord, true, true, rd, rn, o); | |
| 348 } | |
| 349 | |
| 350 // Logical immediate operations. | |
| 351 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer | |
| 352 // sequence on failure. | |
| 353 void andi(Register rd, Register rn, uint64_t imm) { | |
| 354 uint8_t n = 0, imm_s = 0, imm_r = 0; | |
| 355 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); | |
|
regis
2014/04/09 20:49:49
You could also use a pattern similar to ShifterOpe
zra
2014/04/09 22:14:28
Done.
| |
| 356 ASSERT(immok); | |
| 357 EmitLogicalImmOp(ANDI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); | |
| 358 } | |
| 359 void orri(Register rd, Register rn, uint64_t imm) { | |
| 360 uint8_t n = 0, imm_s = 0, imm_r = 0; | |
| 361 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); | |
| 362 ASSERT(immok); | |
| 363 EmitLogicalImmOp(ORRI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); | |
| 364 } | |
| 365 void eori(Register rd, Register rn, uint64_t imm) { | |
| 366 uint8_t n = 0, imm_s = 0, imm_r = 0; | |
| 367 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); | |
| 368 ASSERT(immok); | |
| 369 EmitLogicalImmOp(EORI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); | |
| 370 } | |
| 371 void andis(Register rd, Register rn, uint64_t imm) { | |
| 372 uint8_t n = 0, imm_s = 0, imm_r = 0; | |
| 373 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); | |
| 374 ASSERT(immok); | |
| 375 EmitLogicalImmOp(ANDIS, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); | |
| 376 } | |
| 377 | |
| 378 // Logical (shifted) register operations. | |
| 379 void and_(Register rd, Register rn, Operand o) { | |
| 380 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); | |
| 381 } | |
| 382 void bic(Register rd, Register rn, Operand o) { | |
| 383 EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord); | |
| 384 } | |
| 385 void orr(Register rd, Register rn, Operand o) { | |
| 386 EmitLogicalShiftOp(ORR, rd, rn, o, kDoubleWord); | |
| 387 } | |
| 388 void orn(Register rd, Register rn, Operand o) { | |
| 389 EmitLogicalShiftOp(ORN, rd, rn, o, kDoubleWord); | |
| 390 } | |
| 391 void eor(Register rd, Register rn, Operand o) { | |
| 392 EmitLogicalShiftOp(EOR, rd, rn, o, kDoubleWord); | |
| 393 } | |
| 394 void eon(Register rd, Register rn, Operand o) { | |
| 395 EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord); | |
| 396 } | |
| 397 void ands(Register rd, Register rn, Operand o) { | |
| 398 EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord); | |
| 399 } | |
| 400 void bics(Register rd, Register rn, Operand o) { | |
| 401 EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord); | |
| 402 } | |
| 403 | |
| 404 // Comparison. | |
| 405 // rn cmp o. | |
| 406 void cmp(Register rn, Operand o) { | |
| 407 subs(ZR, rn, o); | |
| 408 } | |
| 409 // rn cmp -o. | |
| 410 void cmn(Register rn, Operand o) { | |
| 411 adds(ZR, rn, o); | |
| 412 } | |
| 335 | 413 |
| 336 // Move wide immediate. | 414 // Move wide immediate. |
| 337 void movk(Register rd, int32_t imm, int32_t hw_idx) { | 415 void movk(Register rd, int32_t imm, int32_t hw_idx) { |
| 338 ASSERT(rd != SP); | 416 ASSERT(rd != SP); |
| 339 const Register crd = ConcreteRegister(rd); | 417 const Register crd = ConcreteRegister(rd); |
| 340 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); | 418 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 341 } | 419 } |
| 342 void movn(Register rd, int32_t imm, int32_t hw_idx) { | 420 void movn(Register rd, int32_t imm, int32_t hw_idx) { |
| 343 ASSERT(rd != SP); | 421 ASSERT(rd != SP); |
| 344 const Register crd = ConcreteRegister(rd); | 422 const Register crd = ConcreteRegister(rd); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 | 464 |
| 387 private: | 465 private: |
| 388 intptr_t pc_offset_; | 466 intptr_t pc_offset_; |
| 389 const String& comment_; | 467 const String& comment_; |
| 390 | 468 |
| 391 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 469 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
| 392 }; | 470 }; |
| 393 | 471 |
| 394 GrowableArray<CodeComment*> comments_; | 472 GrowableArray<CodeComment*> comments_; |
| 395 | 473 |
| 474 bool IsImmLogical(uint64_t value, uint8_t width, | |
| 475 uint8_t* n, uint8_t* imm_s, uint8_t* imm_r); | |
| 476 | |
| 396 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, | 477 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, |
| 397 Register rd, Register rn, Operand o) { | 478 Register rd, Register rn, Operand o) { |
| 398 ASSERT((rd != R31) && (rn != R31)); | 479 ASSERT((rd != R31) && (rn != R31)); |
| 399 const Register crd = ConcreteRegister(rd); | 480 const Register crd = ConcreteRegister(rd); |
| 400 const Register crn = ConcreteRegister(rn); | 481 const Register crn = ConcreteRegister(rn); |
| 401 if (o.type() == Operand::Immediate) { | 482 if (o.type() == Operand::Immediate) { |
| 402 ASSERT((rd != ZR) && (rn != ZR)); | 483 ASSERT((rd != ZR) && (rn != ZR)); |
| 403 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); | 484 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); |
| 404 } else if (o.type() == Operand::Shifted) { | 485 } else if (o.type() == Operand::Shifted) { |
| 405 ASSERT((rd != SP) && (rn != SP)); | 486 ASSERT((rd != SP) && (rn != SP)); |
| 406 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | 487 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
| 407 } else { | 488 } else { |
| 408 ASSERT(o.type() == Operand::Extended); | 489 ASSERT(o.type() == Operand::Extended); |
| 409 ASSERT((rd != SP) && (rn != ZR)); | 490 ASSERT((rd != SP) && (rn != ZR)); |
| 410 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | 491 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
| 411 } | 492 } |
| 412 } | 493 } |
| 413 | 494 |
| 414 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, | 495 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, |
| 415 Operand o, OperandSize os, bool set_flags) { | 496 Operand o, OperandSize sz, bool set_flags) { |
| 416 ASSERT((os == kDoubleWord) || (os == kWord)); | 497 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 417 const int32_t size = (os == kDoubleWord) ? B31 : 0; | 498 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 418 const int32_t s = set_flags ? B29 : 0; | 499 const int32_t s = set_flags ? B29 : 0; |
| 419 const int32_t encoding = | 500 const int32_t encoding = |
| 420 op | size | s | | 501 op | size | s | |
| 421 (static_cast<int32_t>(rd) << kRdShift) | | 502 (static_cast<int32_t>(rd) << kRdShift) | |
| 422 (static_cast<int32_t>(rn) << kRnShift) | | 503 (static_cast<int32_t>(rn) << kRnShift) | |
| 423 o.encoding(); | 504 o.encoding(); |
| 424 Emit(encoding); | 505 Emit(encoding); |
| 425 } | 506 } |
| 426 | 507 |
| 508 void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn, | |
| 509 Operand o, OperandSize sz) { | |
| 510 ASSERT((sz == kDoubleWord) || (sz == kWord)); | |
| 511 ASSERT((rd != R31) && (rn != R31)); | |
| 512 ASSERT(rn != SP); | |
| 513 ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR. | |
| 514 ASSERT((op != ANDIS) || (rd != SP)); // op == ANDIS => rd != SP. | |
| 515 ASSERT(o.type() == Operand::BitfieldImm); | |
| 516 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | |
| 517 const Register crd = ConcreteRegister(rd); | |
| 518 const Register crn = ConcreteRegister(rn); | |
| 519 const int32_t encoding = | |
| 520 op | size | | |
| 521 (static_cast<int32_t>(crd) << kRdShift) | | |
| 522 (static_cast<int32_t>(crn) << kRnShift) | | |
| 523 o.encoding(); | |
| 524 Emit(encoding); | |
| 525 } | |
| 526 | |
| 527 void EmitLogicalShiftOp(LogicalShiftOp op, | |
| 528 Register rd, Register rn, Operand o, OperandSize sz) { | |
| 529 ASSERT((sz == kDoubleWord) || (sz == kWord)); | |
| 530 ASSERT((rd != R31) && (rn != R31)); | |
| 531 ASSERT((rd != SP) && (rn != SP)); | |
| 532 ASSERT(o.type() == Operand::Shifted); | |
| 533 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | |
| 534 const Register crd = ConcreteRegister(rd); | |
| 535 const Register crn = ConcreteRegister(rn); | |
| 536 const int32_t encoding = | |
| 537 op | size | | |
| 538 (static_cast<int32_t>(crd) << kRdShift) | | |
| 539 (static_cast<int32_t>(crn) << kRnShift) | | |
| 540 o.encoding(); | |
| 541 Emit(encoding); | |
| 542 } | |
| 543 | |
| 427 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, | 544 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, |
| 428 Register rd, Register rn, Operand o, | 545 Register rd, Register rn, Operand o, |
| 429 OperandSize sz, bool set_flags) { | 546 OperandSize sz, bool set_flags) { |
| 430 ASSERT((sz == kDoubleWord) || (sz == kWord)); | 547 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 431 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 548 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 432 const int32_t s = set_flags ? B29 : 0; | 549 const int32_t s = set_flags ? B29 : 0; |
| 433 const int32_t encoding = | 550 const int32_t encoding = |
| 434 op | size | s | | 551 op | size | s | |
| 435 (static_cast<int32_t>(rd) << kRdShift) | | 552 (static_cast<int32_t>(rd) << kRdShift) | |
| 436 (static_cast<int32_t>(rn) << kRnShift) | | 553 (static_cast<int32_t>(rn) << kRnShift) | |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 Emit(encoding); | 585 Emit(encoding); |
| 469 } | 586 } |
| 470 | 587 |
| 471 DISALLOW_ALLOCATION(); | 588 DISALLOW_ALLOCATION(); |
| 472 DISALLOW_COPY_AND_ASSIGN(Assembler); | 589 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 473 }; | 590 }; |
| 474 | 591 |
| 475 } // namespace dart | 592 } // namespace dart |
| 476 | 593 |
| 477 #endif // VM_ASSEMBLER_ARM64_H_ | 594 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |