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

Side by Side Diff: src/arm/assembler-arm.cc

Issue 430503007: Rename ASSERT* to DCHECK*. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE and fixes Created 6 years, 4 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
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines. 118 // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
119 if (cpu.implementer() == base::CPU::ARM && 119 if (cpu.implementer() == base::CPU::ARM &&
120 (cpu.part() == base::CPU::ARM_CORTEX_A5 || 120 (cpu.part() == base::CPU::ARM_CORTEX_A5 ||
121 cpu.part() == base::CPU::ARM_CORTEX_A9)) { 121 cpu.part() == base::CPU::ARM_CORTEX_A9)) {
122 cache_line_size_ = 32; 122 cache_line_size_ = 32;
123 } 123 }
124 124
125 if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS; 125 if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS;
126 #endif 126 #endif
127 127
128 ASSERT(!IsSupported(VFP3) || IsSupported(ARMv7)); 128 DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7));
129 } 129 }
130 130
131 131
132 void CpuFeatures::PrintTarget() { 132 void CpuFeatures::PrintTarget() {
133 const char* arm_arch = NULL; 133 const char* arm_arch = NULL;
134 const char* arm_target_type = ""; 134 const char* arm_target_type = "";
135 const char* arm_no_probe = ""; 135 const char* arm_no_probe = "";
136 const char* arm_fpu = ""; 136 const char* arm_fpu = "";
137 const char* arm_thumb = ""; 137 const char* arm_thumb = "";
138 const char* arm_float_abi = NULL; 138 const char* arm_float_abi = NULL;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 bool eabi_hardfloat = false; 200 bool eabi_hardfloat = false;
201 #endif 201 #endif
202 printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat); 202 printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
203 } 203 }
204 204
205 205
206 // ----------------------------------------------------------------------------- 206 // -----------------------------------------------------------------------------
207 // Implementation of DwVfpRegister 207 // Implementation of DwVfpRegister
208 208
209 const char* DwVfpRegister::AllocationIndexToString(int index) { 209 const char* DwVfpRegister::AllocationIndexToString(int index) {
210 ASSERT(index >= 0 && index < NumAllocatableRegisters()); 210 DCHECK(index >= 0 && index < NumAllocatableRegisters());
211 ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == 211 DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
212 kNumReservedRegisters - 1); 212 kNumReservedRegisters - 1);
213 if (index >= kDoubleRegZero.code()) index += kNumReservedRegisters; 213 if (index >= kDoubleRegZero.code()) index += kNumReservedRegisters;
214 return VFPRegisters::Name(index, true); 214 return VFPRegisters::Name(index, true);
215 } 215 }
216 216
217 217
218 // ----------------------------------------------------------------------------- 218 // -----------------------------------------------------------------------------
219 // Implementation of RelocInfo 219 // Implementation of RelocInfo
220 220
221 const int RelocInfo::kApplyMask = 0; 221 const int RelocInfo::kApplyMask = 0;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 // ----------------------------------------------------------------------------- 259 // -----------------------------------------------------------------------------
260 // Implementation of Operand and MemOperand 260 // Implementation of Operand and MemOperand
261 // See assembler-arm-inl.h for inlined constructors 261 // See assembler-arm-inl.h for inlined constructors
262 262
263 Operand::Operand(Handle<Object> handle) { 263 Operand::Operand(Handle<Object> handle) {
264 AllowDeferredHandleDereference using_raw_address; 264 AllowDeferredHandleDereference using_raw_address;
265 rm_ = no_reg; 265 rm_ = no_reg;
266 // Verify all Objects referred by code are NOT in new space. 266 // Verify all Objects referred by code are NOT in new space.
267 Object* obj = *handle; 267 Object* obj = *handle;
268 if (obj->IsHeapObject()) { 268 if (obj->IsHeapObject()) {
269 ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); 269 DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
270 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 270 imm32_ = reinterpret_cast<intptr_t>(handle.location());
271 rmode_ = RelocInfo::EMBEDDED_OBJECT; 271 rmode_ = RelocInfo::EMBEDDED_OBJECT;
272 } else { 272 } else {
273 // no relocation needed 273 // no relocation needed
274 imm32_ = reinterpret_cast<intptr_t>(obj); 274 imm32_ = reinterpret_cast<intptr_t>(obj);
275 rmode_ = RelocInfo::NONE32; 275 rmode_ = RelocInfo::NONE32;
276 } 276 }
277 } 277 }
278 278
279 279
280 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { 280 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
281 ASSERT(is_uint5(shift_imm)); 281 DCHECK(is_uint5(shift_imm));
282 282
283 rm_ = rm; 283 rm_ = rm;
284 rs_ = no_reg; 284 rs_ = no_reg;
285 shift_op_ = shift_op; 285 shift_op_ = shift_op;
286 shift_imm_ = shift_imm & 31; 286 shift_imm_ = shift_imm & 31;
287 287
288 if ((shift_op == ROR) && (shift_imm == 0)) { 288 if ((shift_op == ROR) && (shift_imm == 0)) {
289 // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode 289 // ROR #0 is functionally equivalent to LSL #0 and this allow us to encode
290 // RRX as ROR #0 (See below). 290 // RRX as ROR #0 (See below).
291 shift_op = LSL; 291 shift_op = LSL;
292 } else if (shift_op == RRX) { 292 } else if (shift_op == RRX) {
293 // encoded as ROR with shift_imm == 0 293 // encoded as ROR with shift_imm == 0
294 ASSERT(shift_imm == 0); 294 DCHECK(shift_imm == 0);
295 shift_op_ = ROR; 295 shift_op_ = ROR;
296 shift_imm_ = 0; 296 shift_imm_ = 0;
297 } 297 }
298 } 298 }
299 299
300 300
301 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) { 301 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
302 ASSERT(shift_op != RRX); 302 DCHECK(shift_op != RRX);
303 rm_ = rm; 303 rm_ = rm;
304 rs_ = no_reg; 304 rs_ = no_reg;
305 shift_op_ = shift_op; 305 shift_op_ = shift_op;
306 rs_ = rs; 306 rs_ = rs;
307 } 307 }
308 308
309 309
310 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { 310 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
311 rn_ = rn; 311 rn_ = rn;
312 rm_ = no_reg; 312 rm_ = no_reg;
313 offset_ = offset; 313 offset_ = offset;
314 am_ = am; 314 am_ = am;
315 } 315 }
316 316
317 317
318 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) { 318 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
319 rn_ = rn; 319 rn_ = rn;
320 rm_ = rm; 320 rm_ = rm;
321 shift_op_ = LSL; 321 shift_op_ = LSL;
322 shift_imm_ = 0; 322 shift_imm_ = 0;
323 am_ = am; 323 am_ = am;
324 } 324 }
325 325
326 326
327 MemOperand::MemOperand(Register rn, Register rm, 327 MemOperand::MemOperand(Register rn, Register rm,
328 ShiftOp shift_op, int shift_imm, AddrMode am) { 328 ShiftOp shift_op, int shift_imm, AddrMode am) {
329 ASSERT(is_uint5(shift_imm)); 329 DCHECK(is_uint5(shift_imm));
330 rn_ = rn; 330 rn_ = rn;
331 rm_ = rm; 331 rm_ = rm;
332 shift_op_ = shift_op; 332 shift_op_ = shift_op;
333 shift_imm_ = shift_imm & 31; 333 shift_imm_ = shift_imm & 31;
334 am_ = am; 334 am_ = am;
335 } 335 }
336 336
337 337
338 NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) { 338 NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) {
339 ASSERT((am == Offset) || (am == PostIndex)); 339 DCHECK((am == Offset) || (am == PostIndex));
340 rn_ = rn; 340 rn_ = rn;
341 rm_ = (am == Offset) ? pc : sp; 341 rm_ = (am == Offset) ? pc : sp;
342 SetAlignment(align); 342 SetAlignment(align);
343 } 343 }
344 344
345 345
346 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) { 346 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
347 rn_ = rn; 347 rn_ = rn;
348 rm_ = rm; 348 rm_ = rm;
349 SetAlignment(align); 349 SetAlignment(align);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 no_const_pool_before_ = 0; 466 no_const_pool_before_ = 0;
467 first_const_pool_32_use_ = -1; 467 first_const_pool_32_use_ = -1;
468 first_const_pool_64_use_ = -1; 468 first_const_pool_64_use_ = -1;
469 last_bound_pos_ = 0; 469 last_bound_pos_ = 0;
470 constant_pool_available_ = !FLAG_enable_ool_constant_pool; 470 constant_pool_available_ = !FLAG_enable_ool_constant_pool;
471 ClearRecordedAstId(); 471 ClearRecordedAstId();
472 } 472 }
473 473
474 474
475 Assembler::~Assembler() { 475 Assembler::~Assembler() {
476 ASSERT(const_pool_blocked_nesting_ == 0); 476 DCHECK(const_pool_blocked_nesting_ == 0);
477 } 477 }
478 478
479 479
480 void Assembler::GetCode(CodeDesc* desc) { 480 void Assembler::GetCode(CodeDesc* desc) {
481 if (!FLAG_enable_ool_constant_pool) { 481 if (!FLAG_enable_ool_constant_pool) {
482 // Emit constant pool if necessary. 482 // Emit constant pool if necessary.
483 CheckConstPool(true, false); 483 CheckConstPool(true, false);
484 ASSERT(num_pending_32_bit_reloc_info_ == 0); 484 DCHECK(num_pending_32_bit_reloc_info_ == 0);
485 ASSERT(num_pending_64_bit_reloc_info_ == 0); 485 DCHECK(num_pending_64_bit_reloc_info_ == 0);
486 } 486 }
487 // Set up code descriptor. 487 // Set up code descriptor.
488 desc->buffer = buffer_; 488 desc->buffer = buffer_;
489 desc->buffer_size = buffer_size_; 489 desc->buffer_size = buffer_size_;
490 desc->instr_size = pc_offset(); 490 desc->instr_size = pc_offset();
491 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 491 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
492 desc->origin = this; 492 desc->origin = this;
493 } 493 }
494 494
495 495
496 void Assembler::Align(int m) { 496 void Assembler::Align(int m) {
497 ASSERT(m >= 4 && IsPowerOf2(m)); 497 DCHECK(m >= 4 && IsPowerOf2(m));
498 while ((pc_offset() & (m - 1)) != 0) { 498 while ((pc_offset() & (m - 1)) != 0) {
499 nop(); 499 nop();
500 } 500 }
501 } 501 }
502 502
503 503
504 void Assembler::CodeTargetAlign() { 504 void Assembler::CodeTargetAlign() {
505 // Preferred alignment of jump targets on some ARM chips. 505 // Preferred alignment of jump targets on some ARM chips.
506 Align(8); 506 Align(8);
507 } 507 }
508 508
509 509
510 Condition Assembler::GetCondition(Instr instr) { 510 Condition Assembler::GetCondition(Instr instr) {
511 return Instruction::ConditionField(instr); 511 return Instruction::ConditionField(instr);
512 } 512 }
513 513
514 514
515 bool Assembler::IsBranch(Instr instr) { 515 bool Assembler::IsBranch(Instr instr) {
516 return (instr & (B27 | B25)) == (B27 | B25); 516 return (instr & (B27 | B25)) == (B27 | B25);
517 } 517 }
518 518
519 519
520 int Assembler::GetBranchOffset(Instr instr) { 520 int Assembler::GetBranchOffset(Instr instr) {
521 ASSERT(IsBranch(instr)); 521 DCHECK(IsBranch(instr));
522 // Take the jump offset in the lower 24 bits, sign extend it and multiply it 522 // Take the jump offset in the lower 24 bits, sign extend it and multiply it
523 // with 4 to get the offset in bytes. 523 // with 4 to get the offset in bytes.
524 return ((instr & kImm24Mask) << 8) >> 6; 524 return ((instr & kImm24Mask) << 8) >> 6;
525 } 525 }
526 526
527 527
528 bool Assembler::IsLdrRegisterImmediate(Instr instr) { 528 bool Assembler::IsLdrRegisterImmediate(Instr instr) {
529 return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20); 529 return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
530 } 530 }
531 531
532 532
533 bool Assembler::IsVldrDRegisterImmediate(Instr instr) { 533 bool Assembler::IsVldrDRegisterImmediate(Instr instr) {
534 return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8); 534 return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
535 } 535 }
536 536
537 537
538 int Assembler::GetLdrRegisterImmediateOffset(Instr instr) { 538 int Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
539 ASSERT(IsLdrRegisterImmediate(instr)); 539 DCHECK(IsLdrRegisterImmediate(instr));
540 bool positive = (instr & B23) == B23; 540 bool positive = (instr & B23) == B23;
541 int offset = instr & kOff12Mask; // Zero extended offset. 541 int offset = instr & kOff12Mask; // Zero extended offset.
542 return positive ? offset : -offset; 542 return positive ? offset : -offset;
543 } 543 }
544 544
545 545
546 int Assembler::GetVldrDRegisterImmediateOffset(Instr instr) { 546 int Assembler::GetVldrDRegisterImmediateOffset(Instr instr) {
547 ASSERT(IsVldrDRegisterImmediate(instr)); 547 DCHECK(IsVldrDRegisterImmediate(instr));
548 bool positive = (instr & B23) == B23; 548 bool positive = (instr & B23) == B23;
549 int offset = instr & kOff8Mask; // Zero extended offset. 549 int offset = instr & kOff8Mask; // Zero extended offset.
550 offset <<= 2; 550 offset <<= 2;
551 return positive ? offset : -offset; 551 return positive ? offset : -offset;
552 } 552 }
553 553
554 554
555 Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) { 555 Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
556 ASSERT(IsLdrRegisterImmediate(instr)); 556 DCHECK(IsLdrRegisterImmediate(instr));
557 bool positive = offset >= 0; 557 bool positive = offset >= 0;
558 if (!positive) offset = -offset; 558 if (!positive) offset = -offset;
559 ASSERT(is_uint12(offset)); 559 DCHECK(is_uint12(offset));
560 // Set bit indicating whether the offset should be added. 560 // Set bit indicating whether the offset should be added.
561 instr = (instr & ~B23) | (positive ? B23 : 0); 561 instr = (instr & ~B23) | (positive ? B23 : 0);
562 // Set the actual offset. 562 // Set the actual offset.
563 return (instr & ~kOff12Mask) | offset; 563 return (instr & ~kOff12Mask) | offset;
564 } 564 }
565 565
566 566
567 Instr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) { 567 Instr Assembler::SetVldrDRegisterImmediateOffset(Instr instr, int offset) {
568 ASSERT(IsVldrDRegisterImmediate(instr)); 568 DCHECK(IsVldrDRegisterImmediate(instr));
569 ASSERT((offset & ~3) == offset); // Must be 64-bit aligned. 569 DCHECK((offset & ~3) == offset); // Must be 64-bit aligned.
570 bool positive = offset >= 0; 570 bool positive = offset >= 0;
571 if (!positive) offset = -offset; 571 if (!positive) offset = -offset;
572 ASSERT(is_uint10(offset)); 572 DCHECK(is_uint10(offset));
573 // Set bit indicating whether the offset should be added. 573 // Set bit indicating whether the offset should be added.
574 instr = (instr & ~B23) | (positive ? B23 : 0); 574 instr = (instr & ~B23) | (positive ? B23 : 0);
575 // Set the actual offset. Its bottom 2 bits are zero. 575 // Set the actual offset. Its bottom 2 bits are zero.
576 return (instr & ~kOff8Mask) | (offset >> 2); 576 return (instr & ~kOff8Mask) | (offset >> 2);
577 } 577 }
578 578
579 579
580 bool Assembler::IsStrRegisterImmediate(Instr instr) { 580 bool Assembler::IsStrRegisterImmediate(Instr instr) {
581 return (instr & (B27 | B26 | B25 | B22 | B20)) == B26; 581 return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
582 } 582 }
583 583
584 584
585 Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) { 585 Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
586 ASSERT(IsStrRegisterImmediate(instr)); 586 DCHECK(IsStrRegisterImmediate(instr));
587 bool positive = offset >= 0; 587 bool positive = offset >= 0;
588 if (!positive) offset = -offset; 588 if (!positive) offset = -offset;
589 ASSERT(is_uint12(offset)); 589 DCHECK(is_uint12(offset));
590 // Set bit indicating whether the offset should be added. 590 // Set bit indicating whether the offset should be added.
591 instr = (instr & ~B23) | (positive ? B23 : 0); 591 instr = (instr & ~B23) | (positive ? B23 : 0);
592 // Set the actual offset. 592 // Set the actual offset.
593 return (instr & ~kOff12Mask) | offset; 593 return (instr & ~kOff12Mask) | offset;
594 } 594 }
595 595
596 596
597 bool Assembler::IsAddRegisterImmediate(Instr instr) { 597 bool Assembler::IsAddRegisterImmediate(Instr instr) {
598 return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23); 598 return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
599 } 599 }
600 600
601 601
602 Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) { 602 Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
603 ASSERT(IsAddRegisterImmediate(instr)); 603 DCHECK(IsAddRegisterImmediate(instr));
604 ASSERT(offset >= 0); 604 DCHECK(offset >= 0);
605 ASSERT(is_uint12(offset)); 605 DCHECK(is_uint12(offset));
606 // Set the offset. 606 // Set the offset.
607 return (instr & ~kOff12Mask) | offset; 607 return (instr & ~kOff12Mask) | offset;
608 } 608 }
609 609
610 610
611 Register Assembler::GetRd(Instr instr) { 611 Register Assembler::GetRd(Instr instr) {
612 Register reg; 612 Register reg;
613 reg.code_ = Instruction::RdValue(instr); 613 reg.code_ = Instruction::RdValue(instr);
614 return reg; 614 return reg;
615 } 615 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 741 }
742 742
743 743
744 bool Assembler::IsCmpImmediate(Instr instr) { 744 bool Assembler::IsCmpImmediate(Instr instr) {
745 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) == 745 return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
746 (I | CMP | S); 746 (I | CMP | S);
747 } 747 }
748 748
749 749
750 Register Assembler::GetCmpImmediateRegister(Instr instr) { 750 Register Assembler::GetCmpImmediateRegister(Instr instr) {
751 ASSERT(IsCmpImmediate(instr)); 751 DCHECK(IsCmpImmediate(instr));
752 return GetRn(instr); 752 return GetRn(instr);
753 } 753 }
754 754
755 755
756 int Assembler::GetCmpImmediateRawImmediate(Instr instr) { 756 int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
757 ASSERT(IsCmpImmediate(instr)); 757 DCHECK(IsCmpImmediate(instr));
758 return instr & kOff12Mask; 758 return instr & kOff12Mask;
759 } 759 }
760 760
761 761
762 // Labels refer to positions in the (to be) generated code. 762 // Labels refer to positions in the (to be) generated code.
763 // There are bound, linked, and unused labels. 763 // There are bound, linked, and unused labels.
764 // 764 //
765 // Bound labels refer to known positions in the already 765 // Bound labels refer to known positions in the already
766 // generated code. pos() is the position the label refers to. 766 // generated code. pos() is the position the label refers to.
767 // 767 //
768 // Linked labels refer to unknown positions in the code 768 // Linked labels refer to unknown positions in the code
769 // to be generated; pos() is the position of the last 769 // to be generated; pos() is the position of the last
770 // instruction using the label. 770 // instruction using the label.
771 // 771 //
772 // The linked labels form a link chain by making the branch offset 772 // The linked labels form a link chain by making the branch offset
773 // in the instruction steam to point to the previous branch 773 // in the instruction steam to point to the previous branch
774 // instruction using the same label. 774 // instruction using the same label.
775 // 775 //
776 // The link chain is terminated by a branch offset pointing to the 776 // The link chain is terminated by a branch offset pointing to the
777 // same position. 777 // same position.
778 778
779 779
780 int Assembler::target_at(int pos) { 780 int Assembler::target_at(int pos) {
781 Instr instr = instr_at(pos); 781 Instr instr = instr_at(pos);
782 if (is_uint24(instr)) { 782 if (is_uint24(instr)) {
783 // Emitted link to a label, not part of a branch. 783 // Emitted link to a label, not part of a branch.
784 return instr; 784 return instr;
785 } 785 }
786 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 786 DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
787 int imm26 = ((instr & kImm24Mask) << 8) >> 6; 787 int imm26 = ((instr & kImm24Mask) << 8) >> 6;
788 if ((Instruction::ConditionField(instr) == kSpecialCondition) && 788 if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
789 ((instr & B24) != 0)) { 789 ((instr & B24) != 0)) {
790 // blx uses bit 24 to encode bit 2 of imm26 790 // blx uses bit 24 to encode bit 2 of imm26
791 imm26 += 2; 791 imm26 += 2;
792 } 792 }
793 return pos + kPcLoadDelta + imm26; 793 return pos + kPcLoadDelta + imm26;
794 } 794 }
795 795
796 796
797 void Assembler::target_at_put(int pos, int target_pos) { 797 void Assembler::target_at_put(int pos, int target_pos) {
798 Instr instr = instr_at(pos); 798 Instr instr = instr_at(pos);
799 if (is_uint24(instr)) { 799 if (is_uint24(instr)) {
800 ASSERT(target_pos == pos || target_pos >= 0); 800 DCHECK(target_pos == pos || target_pos >= 0);
801 // Emitted link to a label, not part of a branch. 801 // Emitted link to a label, not part of a branch.
802 // Load the position of the label relative to the generated code object 802 // Load the position of the label relative to the generated code object
803 // pointer in a register. 803 // pointer in a register.
804 804
805 // Here are the instructions we need to emit: 805 // Here are the instructions we need to emit:
806 // For ARMv7: target24 => target16_1:target16_0 806 // For ARMv7: target24 => target16_1:target16_0
807 // movw dst, #target16_0 807 // movw dst, #target16_0
808 // movt dst, #target16_1 808 // movt dst, #target16_1
809 // For ARMv6: target24 => target8_2:target8_1:target8_0 809 // For ARMv6: target24 => target8_2:target8_1:target8_0
810 // mov dst, #target8_0 810 // mov dst, #target8_0
811 // orr dst, dst, #target8_1 << 8 811 // orr dst, dst, #target8_1 << 8
812 // orr dst, dst, #target8_2 << 16 812 // orr dst, dst, #target8_2 << 16
813 813
814 // We extract the destination register from the emitted nop instruction. 814 // We extract the destination register from the emitted nop instruction.
815 Register dst = Register::from_code( 815 Register dst = Register::from_code(
816 Instruction::RmValue(instr_at(pos + kInstrSize))); 816 Instruction::RmValue(instr_at(pos + kInstrSize)));
817 ASSERT(IsNop(instr_at(pos + kInstrSize), dst.code())); 817 DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
818 uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag); 818 uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
819 ASSERT(is_uint24(target24)); 819 DCHECK(is_uint24(target24));
820 if (is_uint8(target24)) { 820 if (is_uint8(target24)) {
821 // If the target fits in a byte then only patch with a mov 821 // If the target fits in a byte then only patch with a mov
822 // instruction. 822 // instruction.
823 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 823 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
824 1, 824 1,
825 CodePatcher::DONT_FLUSH); 825 CodePatcher::DONT_FLUSH);
826 patcher.masm()->mov(dst, Operand(target24)); 826 patcher.masm()->mov(dst, Operand(target24));
827 } else { 827 } else {
828 uint16_t target16_0 = target24 & kImm16Mask; 828 uint16_t target16_0 = target24 & kImm16Mask;
829 uint16_t target16_1 = target24 >> 16; 829 uint16_t target16_1 = target24 >> 16;
(...skipping 28 matching lines...) Expand all
858 CodePatcher::DONT_FLUSH); 858 CodePatcher::DONT_FLUSH);
859 patcher.masm()->mov(dst, Operand(target8_0)); 859 patcher.masm()->mov(dst, Operand(target8_0));
860 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8)); 860 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
861 patcher.masm()->orr(dst, dst, Operand(target8_2 << 16)); 861 patcher.masm()->orr(dst, dst, Operand(target8_2 << 16));
862 } 862 }
863 } 863 }
864 } 864 }
865 return; 865 return;
866 } 866 }
867 int imm26 = target_pos - (pos + kPcLoadDelta); 867 int imm26 = target_pos - (pos + kPcLoadDelta);
868 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 868 DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
869 if (Instruction::ConditionField(instr) == kSpecialCondition) { 869 if (Instruction::ConditionField(instr) == kSpecialCondition) {
870 // blx uses bit 24 to encode bit 2 of imm26 870 // blx uses bit 24 to encode bit 2 of imm26
871 ASSERT((imm26 & 1) == 0); 871 DCHECK((imm26 & 1) == 0);
872 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24; 872 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
873 } else { 873 } else {
874 ASSERT((imm26 & 3) == 0); 874 DCHECK((imm26 & 3) == 0);
875 instr &= ~kImm24Mask; 875 instr &= ~kImm24Mask;
876 } 876 }
877 int imm24 = imm26 >> 2; 877 int imm24 = imm26 >> 2;
878 ASSERT(is_int24(imm24)); 878 DCHECK(is_int24(imm24));
879 instr_at_put(pos, instr | (imm24 & kImm24Mask)); 879 instr_at_put(pos, instr | (imm24 & kImm24Mask));
880 } 880 }
881 881
882 882
883 void Assembler::print(Label* L) { 883 void Assembler::print(Label* L) {
884 if (L->is_unused()) { 884 if (L->is_unused()) {
885 PrintF("unused label\n"); 885 PrintF("unused label\n");
886 } else if (L->is_bound()) { 886 } else if (L->is_bound()) {
887 PrintF("bound label to %d\n", L->pos()); 887 PrintF("bound label to %d\n", L->pos());
888 } else if (L->is_linked()) { 888 } else if (L->is_linked()) {
889 Label l = *L; 889 Label l = *L;
890 PrintF("unbound label"); 890 PrintF("unbound label");
891 while (l.is_linked()) { 891 while (l.is_linked()) {
892 PrintF("@ %d ", l.pos()); 892 PrintF("@ %d ", l.pos());
893 Instr instr = instr_at(l.pos()); 893 Instr instr = instr_at(l.pos());
894 if ((instr & ~kImm24Mask) == 0) { 894 if ((instr & ~kImm24Mask) == 0) {
895 PrintF("value\n"); 895 PrintF("value\n");
896 } else { 896 } else {
897 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx 897 DCHECK((instr & 7*B25) == 5*B25); // b, bl, or blx
898 Condition cond = Instruction::ConditionField(instr); 898 Condition cond = Instruction::ConditionField(instr);
899 const char* b; 899 const char* b;
900 const char* c; 900 const char* c;
901 if (cond == kSpecialCondition) { 901 if (cond == kSpecialCondition) {
902 b = "blx"; 902 b = "blx";
903 c = ""; 903 c = "";
904 } else { 904 } else {
905 if ((instr & B24) != 0) 905 if ((instr & B24) != 0)
906 b = "bl"; 906 b = "bl";
907 else 907 else
(...skipping 24 matching lines...) Expand all
932 } 932 }
933 next(&l); 933 next(&l);
934 } 934 }
935 } else { 935 } else {
936 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 936 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
937 } 937 }
938 } 938 }
939 939
940 940
941 void Assembler::bind_to(Label* L, int pos) { 941 void Assembler::bind_to(Label* L, int pos) {
942 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position 942 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position
943 while (L->is_linked()) { 943 while (L->is_linked()) {
944 int fixup_pos = L->pos(); 944 int fixup_pos = L->pos();
945 next(L); // call next before overwriting link with target at fixup_pos 945 next(L); // call next before overwriting link with target at fixup_pos
946 target_at_put(fixup_pos, pos); 946 target_at_put(fixup_pos, pos);
947 } 947 }
948 L->bind_to(pos); 948 L->bind_to(pos);
949 949
950 // Keep track of the last bound label so we don't eliminate any instructions 950 // Keep track of the last bound label so we don't eliminate any instructions
951 // before a bound label. 951 // before a bound label.
952 if (pos > last_bound_pos_) 952 if (pos > last_bound_pos_)
953 last_bound_pos_ = pos; 953 last_bound_pos_ = pos;
954 } 954 }
955 955
956 956
957 void Assembler::bind(Label* L) { 957 void Assembler::bind(Label* L) {
958 ASSERT(!L->is_bound()); // label can only be bound once 958 DCHECK(!L->is_bound()); // label can only be bound once
959 bind_to(L, pc_offset()); 959 bind_to(L, pc_offset());
960 } 960 }
961 961
962 962
963 void Assembler::next(Label* L) { 963 void Assembler::next(Label* L) {
964 ASSERT(L->is_linked()); 964 DCHECK(L->is_linked());
965 int link = target_at(L->pos()); 965 int link = target_at(L->pos());
966 if (link == L->pos()) { 966 if (link == L->pos()) {
967 // Branch target points to the same instuction. This is the end of the link 967 // Branch target points to the same instuction. This is the end of the link
968 // chain. 968 // chain.
969 L->Unuse(); 969 L->Unuse();
970 } else { 970 } else {
971 ASSERT(link >= 0); 971 DCHECK(link >= 0);
972 L->link_to(link); 972 L->link_to(link);
973 } 973 }
974 } 974 }
975 975
976 976
977 // Low-level code emission routines depending on the addressing mode. 977 // Low-level code emission routines depending on the addressing mode.
978 // If this returns true then you have to use the rotate_imm and immed_8 978 // If this returns true then you have to use the rotate_imm and immed_8
979 // that it returns, because it may have already changed the instruction 979 // that it returns, because it may have already changed the instruction
980 // to match them! 980 // to match them!
981 static bool fits_shifter(uint32_t imm32, 981 static bool fits_shifter(uint32_t imm32,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 } 1047 }
1048 return true; 1048 return true;
1049 } 1049 }
1050 1050
1051 1051
1052 static bool use_mov_immediate_load(const Operand& x, 1052 static bool use_mov_immediate_load(const Operand& x,
1053 const Assembler* assembler) { 1053 const Assembler* assembler) {
1054 if (assembler != NULL && !assembler->is_constant_pool_available()) { 1054 if (assembler != NULL && !assembler->is_constant_pool_available()) {
1055 // If there is no constant pool available, we must use an mov immediate. 1055 // If there is no constant pool available, we must use an mov immediate.
1056 // TODO(rmcilroy): enable ARMv6 support. 1056 // TODO(rmcilroy): enable ARMv6 support.
1057 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1057 DCHECK(CpuFeatures::IsSupported(ARMv7));
1058 return true; 1058 return true;
1059 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && 1059 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1060 (assembler == NULL || !assembler->predictable_code_size())) { 1060 (assembler == NULL || !assembler->predictable_code_size())) {
1061 // Prefer movw / movt to constant pool if it is more efficient on the CPU. 1061 // Prefer movw / movt to constant pool if it is more efficient on the CPU.
1062 return true; 1062 return true;
1063 } else if (x.must_output_reloc_info(assembler)) { 1063 } else if (x.must_output_reloc_info(assembler)) {
1064 // Prefer constant pool if data is likely to be patched. 1064 // Prefer constant pool if data is likely to be patched.
1065 return false; 1065 return false;
1066 } else { 1066 } else {
1067 // Otherwise, use immediate load if movw / movt is available. 1067 // Otherwise, use immediate load if movw / movt is available.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 const Operand& x, 1107 const Operand& x,
1108 Condition cond) { 1108 Condition cond) {
1109 RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL); 1109 RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL);
1110 if (x.must_output_reloc_info(this)) { 1110 if (x.must_output_reloc_info(this)) {
1111 RecordRelocInfo(rinfo); 1111 RecordRelocInfo(rinfo);
1112 } 1112 }
1113 1113
1114 if (use_mov_immediate_load(x, this)) { 1114 if (use_mov_immediate_load(x, this)) {
1115 Register target = rd.code() == pc.code() ? ip : rd; 1115 Register target = rd.code() == pc.code() ? ip : rd;
1116 // TODO(rmcilroy): add ARMv6 support for immediate loads. 1116 // TODO(rmcilroy): add ARMv6 support for immediate loads.
1117 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1117 DCHECK(CpuFeatures::IsSupported(ARMv7));
1118 if (!FLAG_enable_ool_constant_pool && 1118 if (!FLAG_enable_ool_constant_pool &&
1119 x.must_output_reloc_info(this)) { 1119 x.must_output_reloc_info(this)) {
1120 // Make sure the movw/movt doesn't get separated. 1120 // Make sure the movw/movt doesn't get separated.
1121 BlockConstPoolFor(2); 1121 BlockConstPoolFor(2);
1122 } 1122 }
1123 movw(target, static_cast<uint32_t>(x.imm32_ & 0xffff), cond); 1123 movw(target, static_cast<uint32_t>(x.imm32_ & 0xffff), cond);
1124 movt(target, static_cast<uint32_t>(x.imm32_) >> 16, cond); 1124 movt(target, static_cast<uint32_t>(x.imm32_) >> 16, cond);
1125 if (target.code() != rd.code()) { 1125 if (target.code() != rd.code()) {
1126 mov(rd, target, LeaveCC, cond); 1126 mov(rd, target, LeaveCC, cond);
1127 } 1127 }
1128 } else { 1128 } else {
1129 ASSERT(is_constant_pool_available()); 1129 DCHECK(is_constant_pool_available());
1130 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo); 1130 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
1131 if (section == ConstantPoolArray::EXTENDED_SECTION) { 1131 if (section == ConstantPoolArray::EXTENDED_SECTION) {
1132 ASSERT(FLAG_enable_ool_constant_pool); 1132 DCHECK(FLAG_enable_ool_constant_pool);
1133 Register target = rd.code() == pc.code() ? ip : rd; 1133 Register target = rd.code() == pc.code() ? ip : rd;
1134 // Emit instructions to load constant pool offset. 1134 // Emit instructions to load constant pool offset.
1135 movw(target, 0, cond); 1135 movw(target, 0, cond);
1136 movt(target, 0, cond); 1136 movt(target, 0, cond);
1137 // Load from constant pool at offset. 1137 // Load from constant pool at offset.
1138 ldr(rd, MemOperand(pp, target), cond); 1138 ldr(rd, MemOperand(pp, target), cond);
1139 } else { 1139 } else {
1140 ASSERT(section == ConstantPoolArray::SMALL_SECTION); 1140 DCHECK(section == ConstantPoolArray::SMALL_SECTION);
1141 ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond); 1141 ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond);
1142 } 1142 }
1143 } 1143 }
1144 } 1144 }
1145 1145
1146 1146
1147 void Assembler::addrmod1(Instr instr, 1147 void Assembler::addrmod1(Instr instr,
1148 Register rn, 1148 Register rn,
1149 Register rd, 1149 Register rd,
1150 const Operand& x) { 1150 const Operand& x) {
1151 CheckBuffer(); 1151 CheckBuffer();
1152 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); 1152 DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
1153 if (!x.rm_.is_valid()) { 1153 if (!x.rm_.is_valid()) {
1154 // Immediate. 1154 // Immediate.
1155 uint32_t rotate_imm; 1155 uint32_t rotate_imm;
1156 uint32_t immed_8; 1156 uint32_t immed_8;
1157 if (x.must_output_reloc_info(this) || 1157 if (x.must_output_reloc_info(this) ||
1158 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { 1158 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
1159 // The immediate operand cannot be encoded as a shifter operand, so load 1159 // The immediate operand cannot be encoded as a shifter operand, so load
1160 // it first to register ip and change the original instruction to use ip. 1160 // it first to register ip and change the original instruction to use ip.
1161 // However, if the original instruction is a 'mov rd, x' (not setting the 1161 // However, if the original instruction is a 'mov rd, x' (not setting the
1162 // condition code), then replace it with a 'ldr rd, [pc]'. 1162 // condition code), then replace it with a 'ldr rd, [pc]'.
1163 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed 1163 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed
1164 Condition cond = Instruction::ConditionField(instr); 1164 Condition cond = Instruction::ConditionField(instr);
1165 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set 1165 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
1166 move_32_bit_immediate(rd, x, cond); 1166 move_32_bit_immediate(rd, x, cond);
1167 } else { 1167 } else {
1168 mov(ip, x, LeaveCC, cond); 1168 mov(ip, x, LeaveCC, cond);
1169 addrmod1(instr, rn, rd, Operand(ip)); 1169 addrmod1(instr, rn, rd, Operand(ip));
1170 } 1170 }
1171 return; 1171 return;
1172 } 1172 }
1173 instr |= I | rotate_imm*B8 | immed_8; 1173 instr |= I | rotate_imm*B8 | immed_8;
1174 } else if (!x.rs_.is_valid()) { 1174 } else if (!x.rs_.is_valid()) {
1175 // Immediate shift. 1175 // Immediate shift.
1176 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 1176 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1177 } else { 1177 } else {
1178 // Register shift. 1178 // Register shift.
1179 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 1179 DCHECK(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
1180 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 1180 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
1181 } 1181 }
1182 emit(instr | rn.code()*B16 | rd.code()*B12); 1182 emit(instr | rn.code()*B16 | rd.code()*B12);
1183 if (rn.is(pc) || x.rm_.is(pc)) { 1183 if (rn.is(pc) || x.rm_.is(pc)) {
1184 // Block constant pool emission for one instruction after reading pc. 1184 // Block constant pool emission for one instruction after reading pc.
1185 BlockConstPoolFor(1); 1185 BlockConstPoolFor(1);
1186 } 1186 }
1187 } 1187 }
1188 1188
1189 1189
1190 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 1190 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
1191 ASSERT((instr & ~(kCondMask | B | L)) == B26); 1191 DCHECK((instr & ~(kCondMask | B | L)) == B26);
1192 int am = x.am_; 1192 int am = x.am_;
1193 if (!x.rm_.is_valid()) { 1193 if (!x.rm_.is_valid()) {
1194 // Immediate offset. 1194 // Immediate offset.
1195 int offset_12 = x.offset_; 1195 int offset_12 = x.offset_;
1196 if (offset_12 < 0) { 1196 if (offset_12 < 0) {
1197 offset_12 = -offset_12; 1197 offset_12 = -offset_12;
1198 am ^= U; 1198 am ^= U;
1199 } 1199 }
1200 if (!is_uint12(offset_12)) { 1200 if (!is_uint12(offset_12)) {
1201 // Immediate offset cannot be encoded, load it first to register ip 1201 // Immediate offset cannot be encoded, load it first to register ip
1202 // rn (and rd in a load) should never be ip, or will be trashed. 1202 // rn (and rd in a load) should never be ip, or will be trashed.
1203 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1203 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1204 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 1204 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1205 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1205 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
1206 return; 1206 return;
1207 } 1207 }
1208 ASSERT(offset_12 >= 0); // no masking needed 1208 DCHECK(offset_12 >= 0); // no masking needed
1209 instr |= offset_12; 1209 instr |= offset_12;
1210 } else { 1210 } else {
1211 // Register offset (shift_imm_ and shift_op_ are 0) or scaled 1211 // Register offset (shift_imm_ and shift_op_ are 0) or scaled
1212 // register offset the constructors make sure than both shift_imm_ 1212 // register offset the constructors make sure than both shift_imm_
1213 // and shift_op_ are initialized. 1213 // and shift_op_ are initialized.
1214 ASSERT(!x.rm_.is(pc)); 1214 DCHECK(!x.rm_.is(pc));
1215 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 1215 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
1216 } 1216 }
1217 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1217 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
1218 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 1218 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1219 } 1219 }
1220 1220
1221 1221
1222 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) { 1222 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
1223 ASSERT((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7)); 1223 DCHECK((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
1224 ASSERT(x.rn_.is_valid()); 1224 DCHECK(x.rn_.is_valid());
1225 int am = x.am_; 1225 int am = x.am_;
1226 if (!x.rm_.is_valid()) { 1226 if (!x.rm_.is_valid()) {
1227 // Immediate offset. 1227 // Immediate offset.
1228 int offset_8 = x.offset_; 1228 int offset_8 = x.offset_;
1229 if (offset_8 < 0) { 1229 if (offset_8 < 0) {
1230 offset_8 = -offset_8; 1230 offset_8 = -offset_8;
1231 am ^= U; 1231 am ^= U;
1232 } 1232 }
1233 if (!is_uint8(offset_8)) { 1233 if (!is_uint8(offset_8)) {
1234 // Immediate offset cannot be encoded, load it first to register ip 1234 // Immediate offset cannot be encoded, load it first to register ip
1235 // rn (and rd in a load) should never be ip, or will be trashed. 1235 // rn (and rd in a load) should never be ip, or will be trashed.
1236 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1236 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1237 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr)); 1237 mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
1238 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1238 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1239 return; 1239 return;
1240 } 1240 }
1241 ASSERT(offset_8 >= 0); // no masking needed 1241 DCHECK(offset_8 >= 0); // no masking needed
1242 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf); 1242 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
1243 } else if (x.shift_imm_ != 0) { 1243 } else if (x.shift_imm_ != 0) {
1244 // Scaled register offset not supported, load index first 1244 // Scaled register offset not supported, load index first
1245 // rn (and rd in a load) should never be ip, or will be trashed. 1245 // rn (and rd in a load) should never be ip, or will be trashed.
1246 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 1246 DCHECK(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
1247 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC, 1247 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
1248 Instruction::ConditionField(instr)); 1248 Instruction::ConditionField(instr));
1249 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 1249 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
1250 return; 1250 return;
1251 } else { 1251 } else {
1252 // Register offset. 1252 // Register offset.
1253 ASSERT((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback 1253 DCHECK((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback
1254 instr |= x.rm_.code(); 1254 instr |= x.rm_.code();
1255 } 1255 }
1256 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1256 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
1257 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 1257 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
1258 } 1258 }
1259 1259
1260 1260
1261 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) { 1261 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
1262 ASSERT((instr & ~(kCondMask | P | U | W | L)) == B27); 1262 DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
1263 ASSERT(rl != 0); 1263 DCHECK(rl != 0);
1264 ASSERT(!rn.is(pc)); 1264 DCHECK(!rn.is(pc));
1265 emit(instr | rn.code()*B16 | rl); 1265 emit(instr | rn.code()*B16 | rl);
1266 } 1266 }
1267 1267
1268 1268
1269 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { 1269 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
1270 // Unindexed addressing is not encoded by this function. 1270 // Unindexed addressing is not encoded by this function.
1271 ASSERT_EQ((B27 | B26), 1271 DCHECK_EQ((B27 | B26),
1272 (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L))); 1272 (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
1273 ASSERT(x.rn_.is_valid() && !x.rm_.is_valid()); 1273 DCHECK(x.rn_.is_valid() && !x.rm_.is_valid());
1274 int am = x.am_; 1274 int am = x.am_;
1275 int offset_8 = x.offset_; 1275 int offset_8 = x.offset_;
1276 ASSERT((offset_8 & 3) == 0); // offset must be an aligned word offset 1276 DCHECK((offset_8 & 3) == 0); // offset must be an aligned word offset
1277 offset_8 >>= 2; 1277 offset_8 >>= 2;
1278 if (offset_8 < 0) { 1278 if (offset_8 < 0) {
1279 offset_8 = -offset_8; 1279 offset_8 = -offset_8;
1280 am ^= U; 1280 am ^= U;
1281 } 1281 }
1282 ASSERT(is_uint8(offset_8)); // unsigned word offset must fit in a byte 1282 DCHECK(is_uint8(offset_8)); // unsigned word offset must fit in a byte
1283 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 1283 DCHECK((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
1284 1284
1285 // Post-indexed addressing requires W == 1; different than in addrmod2/3. 1285 // Post-indexed addressing requires W == 1; different than in addrmod2/3.
1286 if ((am & P) == 0) 1286 if ((am & P) == 0)
1287 am |= W; 1287 am |= W;
1288 1288
1289 ASSERT(offset_8 >= 0); // no masking needed 1289 DCHECK(offset_8 >= 0); // no masking needed
1290 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); 1290 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
1291 } 1291 }
1292 1292
1293 1293
1294 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 1294 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
1295 int target_pos; 1295 int target_pos;
1296 if (L->is_bound()) { 1296 if (L->is_bound()) {
1297 target_pos = L->pos(); 1297 target_pos = L->pos();
1298 } else { 1298 } else {
1299 if (L->is_linked()) { 1299 if (L->is_linked()) {
1300 // Point to previous instruction that uses the link. 1300 // Point to previous instruction that uses the link.
1301 target_pos = L->pos(); 1301 target_pos = L->pos();
1302 } else { 1302 } else {
1303 // First entry of the link chain points to itself. 1303 // First entry of the link chain points to itself.
1304 target_pos = pc_offset(); 1304 target_pos = pc_offset();
1305 } 1305 }
1306 L->link_to(pc_offset()); 1306 L->link_to(pc_offset());
1307 } 1307 }
1308 1308
1309 // Block the emission of the constant pool, since the branch instruction must 1309 // Block the emission of the constant pool, since the branch instruction must
1310 // be emitted at the pc offset recorded by the label. 1310 // be emitted at the pc offset recorded by the label.
1311 BlockConstPoolFor(1); 1311 BlockConstPoolFor(1);
1312 return target_pos - (pc_offset() + kPcLoadDelta); 1312 return target_pos - (pc_offset() + kPcLoadDelta);
1313 } 1313 }
1314 1314
1315 1315
1316 // Branch instructions. 1316 // Branch instructions.
1317 void Assembler::b(int branch_offset, Condition cond) { 1317 void Assembler::b(int branch_offset, Condition cond) {
1318 ASSERT((branch_offset & 3) == 0); 1318 DCHECK((branch_offset & 3) == 0);
1319 int imm24 = branch_offset >> 2; 1319 int imm24 = branch_offset >> 2;
1320 ASSERT(is_int24(imm24)); 1320 DCHECK(is_int24(imm24));
1321 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); 1321 emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1322 1322
1323 if (cond == al) { 1323 if (cond == al) {
1324 // Dead code is a good location to emit the constant pool. 1324 // Dead code is a good location to emit the constant pool.
1325 CheckConstPool(false, false); 1325 CheckConstPool(false, false);
1326 } 1326 }
1327 } 1327 }
1328 1328
1329 1329
1330 void Assembler::bl(int branch_offset, Condition cond) { 1330 void Assembler::bl(int branch_offset, Condition cond) {
1331 positions_recorder()->WriteRecordedPositions(); 1331 positions_recorder()->WriteRecordedPositions();
1332 ASSERT((branch_offset & 3) == 0); 1332 DCHECK((branch_offset & 3) == 0);
1333 int imm24 = branch_offset >> 2; 1333 int imm24 = branch_offset >> 2;
1334 ASSERT(is_int24(imm24)); 1334 DCHECK(is_int24(imm24));
1335 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask)); 1335 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1336 } 1336 }
1337 1337
1338 1338
1339 void Assembler::blx(int branch_offset) { // v5 and above 1339 void Assembler::blx(int branch_offset) { // v5 and above
1340 positions_recorder()->WriteRecordedPositions(); 1340 positions_recorder()->WriteRecordedPositions();
1341 ASSERT((branch_offset & 1) == 0); 1341 DCHECK((branch_offset & 1) == 0);
1342 int h = ((branch_offset & 2) >> 1)*B24; 1342 int h = ((branch_offset & 2) >> 1)*B24;
1343 int imm24 = branch_offset >> 2; 1343 int imm24 = branch_offset >> 2;
1344 ASSERT(is_int24(imm24)); 1344 DCHECK(is_int24(imm24));
1345 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask)); 1345 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1346 } 1346 }
1347 1347
1348 1348
1349 void Assembler::blx(Register target, Condition cond) { // v5 and above 1349 void Assembler::blx(Register target, Condition cond) { // v5 and above
1350 positions_recorder()->WriteRecordedPositions(); 1350 positions_recorder()->WriteRecordedPositions();
1351 ASSERT(!target.is(pc)); 1351 DCHECK(!target.is(pc));
1352 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code()); 1352 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1353 } 1353 }
1354 1354
1355 1355
1356 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t 1356 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
1357 positions_recorder()->WriteRecordedPositions(); 1357 positions_recorder()->WriteRecordedPositions();
1358 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged 1358 DCHECK(!target.is(pc)); // use of pc is actually allowed, but discouraged
1359 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code()); 1359 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1360 } 1360 }
1361 1361
1362 1362
1363 // Data-processing instructions. 1363 // Data-processing instructions.
1364 1364
1365 void Assembler::and_(Register dst, Register src1, const Operand& src2, 1365 void Assembler::and_(Register dst, Register src1, const Operand& src2,
1366 SBit s, Condition cond) { 1366 SBit s, Condition cond) {
1367 addrmod1(cond | AND | s, src1, dst, src2); 1367 addrmod1(cond | AND | s, src1, dst, src2);
1368 } 1368 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1420 } 1420 }
1421 1421
1422 1422
1423 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { 1423 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1424 addrmod1(cond | CMP | S, src1, r0, src2); 1424 addrmod1(cond | CMP | S, src1, r0, src2);
1425 } 1425 }
1426 1426
1427 1427
1428 void Assembler::cmp_raw_immediate( 1428 void Assembler::cmp_raw_immediate(
1429 Register src, int raw_immediate, Condition cond) { 1429 Register src, int raw_immediate, Condition cond) {
1430 ASSERT(is_uint12(raw_immediate)); 1430 DCHECK(is_uint12(raw_immediate));
1431 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate); 1431 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1432 } 1432 }
1433 1433
1434 1434
1435 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { 1435 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1436 addrmod1(cond | CMN | S, src1, r0, src2); 1436 addrmod1(cond | CMN | S, src1, r0, src2);
1437 } 1437 }
1438 1438
1439 1439
1440 void Assembler::orr(Register dst, Register src1, const Operand& src2, 1440 void Assembler::orr(Register dst, Register src1, const Operand& src2,
1441 SBit s, Condition cond) { 1441 SBit s, Condition cond) {
1442 addrmod1(cond | ORR | s, src1, dst, src2); 1442 addrmod1(cond | ORR | s, src1, dst, src2);
1443 } 1443 }
1444 1444
1445 1445
1446 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { 1446 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1447 if (dst.is(pc)) { 1447 if (dst.is(pc)) {
1448 positions_recorder()->WriteRecordedPositions(); 1448 positions_recorder()->WriteRecordedPositions();
1449 } 1449 }
1450 // Don't allow nop instructions in the form mov rn, rn to be generated using 1450 // Don't allow nop instructions in the form mov rn, rn to be generated using
1451 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) 1451 // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
1452 // or MarkCode(int/NopMarkerTypes) pseudo instructions. 1452 // or MarkCode(int/NopMarkerTypes) pseudo instructions.
1453 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); 1453 DCHECK(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
1454 addrmod1(cond | MOV | s, r0, dst, src); 1454 addrmod1(cond | MOV | s, r0, dst, src);
1455 } 1455 }
1456 1456
1457 1457
1458 void Assembler::mov_label_offset(Register dst, Label* label) { 1458 void Assembler::mov_label_offset(Register dst, Label* label) {
1459 if (label->is_bound()) { 1459 if (label->is_bound()) {
1460 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag))); 1460 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
1461 } else { 1461 } else {
1462 // Emit the link to the label in the code stream followed by extra nop 1462 // Emit the link to the label in the code stream followed by extra nop
1463 // instructions. 1463 // instructions.
(...skipping 12 matching lines...) Expand all
1476 // For ARMv7: 1476 // For ARMv7:
1477 // link 1477 // link
1478 // mov dst, dst 1478 // mov dst, dst
1479 // For ARMv6: 1479 // For ARMv6:
1480 // link 1480 // link
1481 // mov dst, dst 1481 // mov dst, dst
1482 // mov dst, dst 1482 // mov dst, dst
1483 // 1483 //
1484 // When the label gets bound: target_at extracts the link and target_at_put 1484 // When the label gets bound: target_at extracts the link and target_at_put
1485 // patches the instructions. 1485 // patches the instructions.
1486 ASSERT(is_uint24(link)); 1486 DCHECK(is_uint24(link));
1487 BlockConstPoolScope block_const_pool(this); 1487 BlockConstPoolScope block_const_pool(this);
1488 emit(link); 1488 emit(link);
1489 nop(dst.code()); 1489 nop(dst.code());
1490 if (!CpuFeatures::IsSupported(ARMv7)) { 1490 if (!CpuFeatures::IsSupported(ARMv7)) {
1491 nop(dst.code()); 1491 nop(dst.code());
1492 } 1492 }
1493 } 1493 }
1494 } 1494 }
1495 1495
1496 1496
1497 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { 1497 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1498 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1498 DCHECK(CpuFeatures::IsSupported(ARMv7));
1499 emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); 1499 emit(cond | 0x30*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1500 } 1500 }
1501 1501
1502 1502
1503 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { 1503 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
1504 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1504 DCHECK(CpuFeatures::IsSupported(ARMv7));
1505 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); 1505 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1506 } 1506 }
1507 1507
1508 1508
1509 void Assembler::bic(Register dst, Register src1, const Operand& src2, 1509 void Assembler::bic(Register dst, Register src1, const Operand& src2,
1510 SBit s, Condition cond) { 1510 SBit s, Condition cond) {
1511 addrmod1(cond | BIC | s, src1, dst, src2); 1511 addrmod1(cond | BIC | s, src1, dst, src2);
1512 } 1512 }
1513 1513
1514 1514
1515 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 1515 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
1516 addrmod1(cond | MVN | s, r0, dst, src); 1516 addrmod1(cond | MVN | s, r0, dst, src);
1517 } 1517 }
1518 1518
1519 1519
1520 // Multiply instructions. 1520 // Multiply instructions.
1521 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, 1521 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1522 SBit s, Condition cond) { 1522 SBit s, Condition cond) {
1523 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1523 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1524 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | 1524 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1525 src2.code()*B8 | B7 | B4 | src1.code()); 1525 src2.code()*B8 | B7 | B4 | src1.code());
1526 } 1526 }
1527 1527
1528 1528
1529 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA, 1529 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
1530 Condition cond) { 1530 Condition cond) {
1531 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 1531 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1532 ASSERT(IsEnabled(MLS)); 1532 DCHECK(IsEnabled(MLS));
1533 emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 | 1533 emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
1534 src2.code()*B8 | B7 | B4 | src1.code()); 1534 src2.code()*B8 | B7 | B4 | src1.code());
1535 } 1535 }
1536 1536
1537 1537
1538 void Assembler::sdiv(Register dst, Register src1, Register src2, 1538 void Assembler::sdiv(Register dst, Register src1, Register src2,
1539 Condition cond) { 1539 Condition cond) {
1540 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1540 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1541 ASSERT(IsEnabled(SUDIV)); 1541 DCHECK(IsEnabled(SUDIV));
1542 emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 | 1542 emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 |
1543 src2.code()*B8 | B4 | src1.code()); 1543 src2.code()*B8 | B4 | src1.code());
1544 } 1544 }
1545 1545
1546 1546
1547 void Assembler::udiv(Register dst, Register src1, Register src2, 1547 void Assembler::udiv(Register dst, Register src1, Register src2,
1548 Condition cond) { 1548 Condition cond) {
1549 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1549 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1550 ASSERT(IsEnabled(SUDIV)); 1550 DCHECK(IsEnabled(SUDIV));
1551 emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 | 1551 emit(cond | B26 | B25 | B24 | B21 | B20 | dst.code() * B16 | 0xf * B12 |
1552 src2.code() * B8 | B4 | src1.code()); 1552 src2.code() * B8 | B4 | src1.code());
1553 } 1553 }
1554 1554
1555 1555
1556 void Assembler::mul(Register dst, Register src1, Register src2, 1556 void Assembler::mul(Register dst, Register src1, Register src2,
1557 SBit s, Condition cond) { 1557 SBit s, Condition cond) {
1558 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 1558 DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1559 // dst goes in bits 16-19 for this instruction! 1559 // dst goes in bits 16-19 for this instruction!
1560 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); 1560 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
1561 } 1561 }
1562 1562
1563 1563
1564 void Assembler::smlal(Register dstL, 1564 void Assembler::smlal(Register dstL,
1565 Register dstH, 1565 Register dstH,
1566 Register src1, 1566 Register src1,
1567 Register src2, 1567 Register src2,
1568 SBit s, 1568 SBit s,
1569 Condition cond) { 1569 Condition cond) {
1570 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1570 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1571 ASSERT(!dstL.is(dstH)); 1571 DCHECK(!dstL.is(dstH));
1572 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1572 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1573 src2.code()*B8 | B7 | B4 | src1.code()); 1573 src2.code()*B8 | B7 | B4 | src1.code());
1574 } 1574 }
1575 1575
1576 1576
1577 void Assembler::smull(Register dstL, 1577 void Assembler::smull(Register dstL,
1578 Register dstH, 1578 Register dstH,
1579 Register src1, 1579 Register src1,
1580 Register src2, 1580 Register src2,
1581 SBit s, 1581 SBit s,
1582 Condition cond) { 1582 Condition cond) {
1583 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1583 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1584 ASSERT(!dstL.is(dstH)); 1584 DCHECK(!dstL.is(dstH));
1585 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | 1585 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1586 src2.code()*B8 | B7 | B4 | src1.code()); 1586 src2.code()*B8 | B7 | B4 | src1.code());
1587 } 1587 }
1588 1588
1589 1589
1590 void Assembler::umlal(Register dstL, 1590 void Assembler::umlal(Register dstL,
1591 Register dstH, 1591 Register dstH,
1592 Register src1, 1592 Register src1,
1593 Register src2, 1593 Register src2,
1594 SBit s, 1594 SBit s,
1595 Condition cond) { 1595 Condition cond) {
1596 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1596 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1597 ASSERT(!dstL.is(dstH)); 1597 DCHECK(!dstL.is(dstH));
1598 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1598 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1599 src2.code()*B8 | B7 | B4 | src1.code()); 1599 src2.code()*B8 | B7 | B4 | src1.code());
1600 } 1600 }
1601 1601
1602 1602
1603 void Assembler::umull(Register dstL, 1603 void Assembler::umull(Register dstL,
1604 Register dstH, 1604 Register dstH,
1605 Register src1, 1605 Register src1,
1606 Register src2, 1606 Register src2,
1607 SBit s, 1607 SBit s,
1608 Condition cond) { 1608 Condition cond) {
1609 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1609 DCHECK(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1610 ASSERT(!dstL.is(dstH)); 1610 DCHECK(!dstL.is(dstH));
1611 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | 1611 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1612 src2.code()*B8 | B7 | B4 | src1.code()); 1612 src2.code()*B8 | B7 | B4 | src1.code());
1613 } 1613 }
1614 1614
1615 1615
1616 // Miscellaneous arithmetic instructions. 1616 // Miscellaneous arithmetic instructions.
1617 void Assembler::clz(Register dst, Register src, Condition cond) { 1617 void Assembler::clz(Register dst, Register src, Condition cond) {
1618 // v5 and above. 1618 // v5 and above.
1619 ASSERT(!dst.is(pc) && !src.is(pc)); 1619 DCHECK(!dst.is(pc) && !src.is(pc));
1620 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | 1620 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
1621 15*B8 | CLZ | src.code()); 1621 15*B8 | CLZ | src.code());
1622 } 1622 }
1623 1623
1624 1624
1625 // Saturating instructions. 1625 // Saturating instructions.
1626 1626
1627 // Unsigned saturate. 1627 // Unsigned saturate.
1628 void Assembler::usat(Register dst, 1628 void Assembler::usat(Register dst,
1629 int satpos, 1629 int satpos,
1630 const Operand& src, 1630 const Operand& src,
1631 Condition cond) { 1631 Condition cond) {
1632 // v6 and above. 1632 // v6 and above.
1633 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1633 DCHECK(CpuFeatures::IsSupported(ARMv7));
1634 ASSERT(!dst.is(pc) && !src.rm_.is(pc)); 1634 DCHECK(!dst.is(pc) && !src.rm_.is(pc));
1635 ASSERT((satpos >= 0) && (satpos <= 31)); 1635 DCHECK((satpos >= 0) && (satpos <= 31));
1636 ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL)); 1636 DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
1637 ASSERT(src.rs_.is(no_reg)); 1637 DCHECK(src.rs_.is(no_reg));
1638 1638
1639 int sh = 0; 1639 int sh = 0;
1640 if (src.shift_op_ == ASR) { 1640 if (src.shift_op_ == ASR) {
1641 sh = 1; 1641 sh = 1;
1642 } 1642 }
1643 1643
1644 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 | 1644 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
1645 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code()); 1645 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
1646 } 1646 }
1647 1647
1648 1648
1649 // Bitfield manipulation instructions. 1649 // Bitfield manipulation instructions.
1650 1650
1651 // Unsigned bit field extract. 1651 // Unsigned bit field extract.
1652 // Extracts #width adjacent bits from position #lsb in a register, and 1652 // Extracts #width adjacent bits from position #lsb in a register, and
1653 // writes them to the low bits of a destination register. 1653 // writes them to the low bits of a destination register.
1654 // ubfx dst, src, #lsb, #width 1654 // ubfx dst, src, #lsb, #width
1655 void Assembler::ubfx(Register dst, 1655 void Assembler::ubfx(Register dst,
1656 Register src, 1656 Register src,
1657 int lsb, 1657 int lsb,
1658 int width, 1658 int width,
1659 Condition cond) { 1659 Condition cond) {
1660 // v7 and above. 1660 // v7 and above.
1661 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1661 DCHECK(CpuFeatures::IsSupported(ARMv7));
1662 ASSERT(!dst.is(pc) && !src.is(pc)); 1662 DCHECK(!dst.is(pc) && !src.is(pc));
1663 ASSERT((lsb >= 0) && (lsb <= 31)); 1663 DCHECK((lsb >= 0) && (lsb <= 31));
1664 ASSERT((width >= 1) && (width <= (32 - lsb))); 1664 DCHECK((width >= 1) && (width <= (32 - lsb)));
1665 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 | 1665 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
1666 lsb*B7 | B6 | B4 | src.code()); 1666 lsb*B7 | B6 | B4 | src.code());
1667 } 1667 }
1668 1668
1669 1669
1670 // Signed bit field extract. 1670 // Signed bit field extract.
1671 // Extracts #width adjacent bits from position #lsb in a register, and 1671 // Extracts #width adjacent bits from position #lsb in a register, and
1672 // writes them to the low bits of a destination register. The extracted 1672 // writes them to the low bits of a destination register. The extracted
1673 // value is sign extended to fill the destination register. 1673 // value is sign extended to fill the destination register.
1674 // sbfx dst, src, #lsb, #width 1674 // sbfx dst, src, #lsb, #width
1675 void Assembler::sbfx(Register dst, 1675 void Assembler::sbfx(Register dst,
1676 Register src, 1676 Register src,
1677 int lsb, 1677 int lsb,
1678 int width, 1678 int width,
1679 Condition cond) { 1679 Condition cond) {
1680 // v7 and above. 1680 // v7 and above.
1681 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1681 DCHECK(CpuFeatures::IsSupported(ARMv7));
1682 ASSERT(!dst.is(pc) && !src.is(pc)); 1682 DCHECK(!dst.is(pc) && !src.is(pc));
1683 ASSERT((lsb >= 0) && (lsb <= 31)); 1683 DCHECK((lsb >= 0) && (lsb <= 31));
1684 ASSERT((width >= 1) && (width <= (32 - lsb))); 1684 DCHECK((width >= 1) && (width <= (32 - lsb)));
1685 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 | 1685 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
1686 lsb*B7 | B6 | B4 | src.code()); 1686 lsb*B7 | B6 | B4 | src.code());
1687 } 1687 }
1688 1688
1689 1689
1690 // Bit field clear. 1690 // Bit field clear.
1691 // Sets #width adjacent bits at position #lsb in the destination register 1691 // Sets #width adjacent bits at position #lsb in the destination register
1692 // to zero, preserving the value of the other bits. 1692 // to zero, preserving the value of the other bits.
1693 // bfc dst, #lsb, #width 1693 // bfc dst, #lsb, #width
1694 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) { 1694 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
1695 // v7 and above. 1695 // v7 and above.
1696 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1696 DCHECK(CpuFeatures::IsSupported(ARMv7));
1697 ASSERT(!dst.is(pc)); 1697 DCHECK(!dst.is(pc));
1698 ASSERT((lsb >= 0) && (lsb <= 31)); 1698 DCHECK((lsb >= 0) && (lsb <= 31));
1699 ASSERT((width >= 1) && (width <= (32 - lsb))); 1699 DCHECK((width >= 1) && (width <= (32 - lsb)));
1700 int msb = lsb + width - 1; 1700 int msb = lsb + width - 1;
1701 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf); 1701 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
1702 } 1702 }
1703 1703
1704 1704
1705 // Bit field insert. 1705 // Bit field insert.
1706 // Inserts #width adjacent bits from the low bits of the source register 1706 // Inserts #width adjacent bits from the low bits of the source register
1707 // into position #lsb of the destination register. 1707 // into position #lsb of the destination register.
1708 // bfi dst, src, #lsb, #width 1708 // bfi dst, src, #lsb, #width
1709 void Assembler::bfi(Register dst, 1709 void Assembler::bfi(Register dst,
1710 Register src, 1710 Register src,
1711 int lsb, 1711 int lsb,
1712 int width, 1712 int width,
1713 Condition cond) { 1713 Condition cond) {
1714 // v7 and above. 1714 // v7 and above.
1715 ASSERT(CpuFeatures::IsSupported(ARMv7)); 1715 DCHECK(CpuFeatures::IsSupported(ARMv7));
1716 ASSERT(!dst.is(pc) && !src.is(pc)); 1716 DCHECK(!dst.is(pc) && !src.is(pc));
1717 ASSERT((lsb >= 0) && (lsb <= 31)); 1717 DCHECK((lsb >= 0) && (lsb <= 31));
1718 ASSERT((width >= 1) && (width <= (32 - lsb))); 1718 DCHECK((width >= 1) && (width <= (32 - lsb)));
1719 int msb = lsb + width - 1; 1719 int msb = lsb + width - 1;
1720 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 1720 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
1721 src.code()); 1721 src.code());
1722 } 1722 }
1723 1723
1724 1724
1725 void Assembler::pkhbt(Register dst, 1725 void Assembler::pkhbt(Register dst,
1726 Register src1, 1726 Register src1,
1727 const Operand& src2, 1727 const Operand& src2,
1728 Condition cond ) { 1728 Condition cond ) {
1729 // Instruction details available in ARM DDI 0406C.b, A8.8.125. 1729 // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1730 // cond(31-28) | 01101000(27-20) | Rn(19-16) | 1730 // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1731 // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0) 1731 // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0)
1732 ASSERT(!dst.is(pc)); 1732 DCHECK(!dst.is(pc));
1733 ASSERT(!src1.is(pc)); 1733 DCHECK(!src1.is(pc));
1734 ASSERT(!src2.rm().is(pc)); 1734 DCHECK(!src2.rm().is(pc));
1735 ASSERT(!src2.rm().is(no_reg)); 1735 DCHECK(!src2.rm().is(no_reg));
1736 ASSERT(src2.rs().is(no_reg)); 1736 DCHECK(src2.rs().is(no_reg));
1737 ASSERT((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31)); 1737 DCHECK((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31));
1738 ASSERT(src2.shift_op() == LSL); 1738 DCHECK(src2.shift_op() == LSL);
1739 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | 1739 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1740 src2.shift_imm_*B7 | B4 | src2.rm().code()); 1740 src2.shift_imm_*B7 | B4 | src2.rm().code());
1741 } 1741 }
1742 1742
1743 1743
1744 void Assembler::pkhtb(Register dst, 1744 void Assembler::pkhtb(Register dst,
1745 Register src1, 1745 Register src1,
1746 const Operand& src2, 1746 const Operand& src2,
1747 Condition cond) { 1747 Condition cond) {
1748 // Instruction details available in ARM DDI 0406C.b, A8.8.125. 1748 // Instruction details available in ARM DDI 0406C.b, A8.8.125.
1749 // cond(31-28) | 01101000(27-20) | Rn(19-16) | 1749 // cond(31-28) | 01101000(27-20) | Rn(19-16) |
1750 // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0) 1750 // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0)
1751 ASSERT(!dst.is(pc)); 1751 DCHECK(!dst.is(pc));
1752 ASSERT(!src1.is(pc)); 1752 DCHECK(!src1.is(pc));
1753 ASSERT(!src2.rm().is(pc)); 1753 DCHECK(!src2.rm().is(pc));
1754 ASSERT(!src2.rm().is(no_reg)); 1754 DCHECK(!src2.rm().is(no_reg));
1755 ASSERT(src2.rs().is(no_reg)); 1755 DCHECK(src2.rs().is(no_reg));
1756 ASSERT((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32)); 1756 DCHECK((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32));
1757 ASSERT(src2.shift_op() == ASR); 1757 DCHECK(src2.shift_op() == ASR);
1758 int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_; 1758 int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_;
1759 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | 1759 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 |
1760 asr*B7 | B6 | B4 | src2.rm().code()); 1760 asr*B7 | B6 | B4 | src2.rm().code());
1761 } 1761 }
1762 1762
1763 1763
1764 void Assembler::uxtb(Register dst, 1764 void Assembler::uxtb(Register dst,
1765 const Operand& src, 1765 const Operand& src,
1766 Condition cond) { 1766 Condition cond) {
1767 // Instruction details available in ARM DDI 0406C.b, A8.8.274. 1767 // Instruction details available in ARM DDI 0406C.b, A8.8.274.
1768 // cond(31-28) | 01101110(27-20) | 1111(19-16) | 1768 // cond(31-28) | 01101110(27-20) | 1111(19-16) |
1769 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1769 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1770 ASSERT(!dst.is(pc)); 1770 DCHECK(!dst.is(pc));
1771 ASSERT(!src.rm().is(pc)); 1771 DCHECK(!src.rm().is(pc));
1772 ASSERT(!src.rm().is(no_reg)); 1772 DCHECK(!src.rm().is(no_reg));
1773 ASSERT(src.rs().is(no_reg)); 1773 DCHECK(src.rs().is(no_reg));
1774 ASSERT((src.shift_imm_ == 0) || 1774 DCHECK((src.shift_imm_ == 0) ||
1775 (src.shift_imm_ == 8) || 1775 (src.shift_imm_ == 8) ||
1776 (src.shift_imm_ == 16) || 1776 (src.shift_imm_ == 16) ||
1777 (src.shift_imm_ == 24)); 1777 (src.shift_imm_ == 24));
1778 // Operand maps ROR #0 to LSL #0. 1778 // Operand maps ROR #0 to LSL #0.
1779 ASSERT((src.shift_op() == ROR) || 1779 DCHECK((src.shift_op() == ROR) ||
1780 ((src.shift_op() == LSL) && (src.shift_imm_ == 0))); 1780 ((src.shift_op() == LSL) && (src.shift_imm_ == 0)));
1781 emit(cond | 0x6E*B20 | 0xF*B16 | dst.code()*B12 | 1781 emit(cond | 0x6E*B20 | 0xF*B16 | dst.code()*B12 |
1782 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code()); 1782 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code());
1783 } 1783 }
1784 1784
1785 1785
1786 void Assembler::uxtab(Register dst, 1786 void Assembler::uxtab(Register dst,
1787 Register src1, 1787 Register src1,
1788 const Operand& src2, 1788 const Operand& src2,
1789 Condition cond) { 1789 Condition cond) {
1790 // Instruction details available in ARM DDI 0406C.b, A8.8.271. 1790 // Instruction details available in ARM DDI 0406C.b, A8.8.271.
1791 // cond(31-28) | 01101110(27-20) | Rn(19-16) | 1791 // cond(31-28) | 01101110(27-20) | Rn(19-16) |
1792 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1792 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1793 ASSERT(!dst.is(pc)); 1793 DCHECK(!dst.is(pc));
1794 ASSERT(!src1.is(pc)); 1794 DCHECK(!src1.is(pc));
1795 ASSERT(!src2.rm().is(pc)); 1795 DCHECK(!src2.rm().is(pc));
1796 ASSERT(!src2.rm().is(no_reg)); 1796 DCHECK(!src2.rm().is(no_reg));
1797 ASSERT(src2.rs().is(no_reg)); 1797 DCHECK(src2.rs().is(no_reg));
1798 ASSERT((src2.shift_imm_ == 0) || 1798 DCHECK((src2.shift_imm_ == 0) ||
1799 (src2.shift_imm_ == 8) || 1799 (src2.shift_imm_ == 8) ||
1800 (src2.shift_imm_ == 16) || 1800 (src2.shift_imm_ == 16) ||
1801 (src2.shift_imm_ == 24)); 1801 (src2.shift_imm_ == 24));
1802 // Operand maps ROR #0 to LSL #0. 1802 // Operand maps ROR #0 to LSL #0.
1803 ASSERT((src2.shift_op() == ROR) || 1803 DCHECK((src2.shift_op() == ROR) ||
1804 ((src2.shift_op() == LSL) && (src2.shift_imm_ == 0))); 1804 ((src2.shift_op() == LSL) && (src2.shift_imm_ == 0)));
1805 emit(cond | 0x6E*B20 | src1.code()*B16 | dst.code()*B12 | 1805 emit(cond | 0x6E*B20 | src1.code()*B16 | dst.code()*B12 |
1806 ((src2.shift_imm_ >> 1) &0xC)*B8 | 7*B4 | src2.rm().code()); 1806 ((src2.shift_imm_ >> 1) &0xC)*B8 | 7*B4 | src2.rm().code());
1807 } 1807 }
1808 1808
1809 1809
1810 void Assembler::uxtb16(Register dst, 1810 void Assembler::uxtb16(Register dst,
1811 const Operand& src, 1811 const Operand& src,
1812 Condition cond) { 1812 Condition cond) {
1813 // Instruction details available in ARM DDI 0406C.b, A8.8.275. 1813 // Instruction details available in ARM DDI 0406C.b, A8.8.275.
1814 // cond(31-28) | 01101100(27-20) | 1111(19-16) | 1814 // cond(31-28) | 01101100(27-20) | 1111(19-16) |
1815 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) 1815 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0)
1816 ASSERT(!dst.is(pc)); 1816 DCHECK(!dst.is(pc));
1817 ASSERT(!src.rm().is(pc)); 1817 DCHECK(!src.rm().is(pc));
1818 ASSERT(!src.rm().is(no_reg)); 1818 DCHECK(!src.rm().is(no_reg));
1819 ASSERT(src.rs().is(no_reg)); 1819 DCHECK(src.rs().is(no_reg));
1820 ASSERT((src.shift_imm_ == 0) || 1820 DCHECK((src.shift_imm_ == 0) ||
1821 (src.shift_imm_ == 8) || 1821 (src.shift_imm_ == 8) ||
1822 (src.shift_imm_ == 16) || 1822 (src.shift_imm_ == 16) ||
1823 (src.shift_imm_ == 24)); 1823 (src.shift_imm_ == 24));
1824 // Operand maps ROR #0 to LSL #0. 1824 // Operand maps ROR #0 to LSL #0.
1825 ASSERT((src.shift_op() == ROR) || 1825 DCHECK((src.shift_op() == ROR) ||
1826 ((src.shift_op() == LSL) && (src.shift_imm_ == 0))); 1826 ((src.shift_op() == LSL) && (src.shift_imm_ == 0)));
1827 emit(cond | 0x6C*B20 | 0xF*B16 | dst.code()*B12 | 1827 emit(cond | 0x6C*B20 | 0xF*B16 | dst.code()*B12 |
1828 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code()); 1828 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code());
1829 } 1829 }
1830 1830
1831 1831
1832 // Status register access instructions. 1832 // Status register access instructions.
1833 void Assembler::mrs(Register dst, SRegister s, Condition cond) { 1833 void Assembler::mrs(Register dst, SRegister s, Condition cond) {
1834 ASSERT(!dst.is(pc)); 1834 DCHECK(!dst.is(pc));
1835 emit(cond | B24 | s | 15*B16 | dst.code()*B12); 1835 emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1836 } 1836 }
1837 1837
1838 1838
1839 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, 1839 void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1840 Condition cond) { 1840 Condition cond) {
1841 ASSERT(fields >= B16 && fields < B20); // at least one field set 1841 DCHECK(fields >= B16 && fields < B20); // at least one field set
1842 Instr instr; 1842 Instr instr;
1843 if (!src.rm_.is_valid()) { 1843 if (!src.rm_.is_valid()) {
1844 // Immediate. 1844 // Immediate.
1845 uint32_t rotate_imm; 1845 uint32_t rotate_imm;
1846 uint32_t immed_8; 1846 uint32_t immed_8;
1847 if (src.must_output_reloc_info(this) || 1847 if (src.must_output_reloc_info(this) ||
1848 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { 1848 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1849 // Immediate operand cannot be encoded, load it first to register ip. 1849 // Immediate operand cannot be encoded, load it first to register ip.
1850 move_32_bit_immediate(ip, src); 1850 move_32_bit_immediate(ip, src);
1851 msr(fields, Operand(ip), cond); 1851 msr(fields, Operand(ip), cond);
1852 return; 1852 return;
1853 } 1853 }
1854 instr = I | rotate_imm*B8 | immed_8; 1854 instr = I | rotate_imm*B8 | immed_8;
1855 } else { 1855 } else {
1856 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed 1856 DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed
1857 instr = src.rm_.code(); 1857 instr = src.rm_.code();
1858 } 1858 }
1859 emit(cond | instr | B24 | B21 | fields | 15*B12); 1859 emit(cond | instr | B24 | B21 | fields | 15*B12);
1860 } 1860 }
1861 1861
1862 1862
1863 // Load/Store instructions. 1863 // Load/Store instructions.
1864 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1864 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1865 if (dst.is(pc)) { 1865 if (dst.is(pc)) {
1866 positions_recorder()->WriteRecordedPositions(); 1866 positions_recorder()->WriteRecordedPositions();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 } 1899 }
1900 1900
1901 1901
1902 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { 1902 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1903 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); 1903 addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1904 } 1904 }
1905 1905
1906 1906
1907 void Assembler::ldrd(Register dst1, Register dst2, 1907 void Assembler::ldrd(Register dst1, Register dst2,
1908 const MemOperand& src, Condition cond) { 1908 const MemOperand& src, Condition cond) {
1909 ASSERT(IsEnabled(ARMv7)); 1909 DCHECK(IsEnabled(ARMv7));
1910 ASSERT(src.rm().is(no_reg)); 1910 DCHECK(src.rm().is(no_reg));
1911 ASSERT(!dst1.is(lr)); // r14. 1911 DCHECK(!dst1.is(lr)); // r14.
1912 ASSERT_EQ(0, dst1.code() % 2); 1912 DCHECK_EQ(0, dst1.code() % 2);
1913 ASSERT_EQ(dst1.code() + 1, dst2.code()); 1913 DCHECK_EQ(dst1.code() + 1, dst2.code());
1914 addrmod3(cond | B7 | B6 | B4, dst1, src); 1914 addrmod3(cond | B7 | B6 | B4, dst1, src);
1915 } 1915 }
1916 1916
1917 1917
1918 void Assembler::strd(Register src1, Register src2, 1918 void Assembler::strd(Register src1, Register src2,
1919 const MemOperand& dst, Condition cond) { 1919 const MemOperand& dst, Condition cond) {
1920 ASSERT(dst.rm().is(no_reg)); 1920 DCHECK(dst.rm().is(no_reg));
1921 ASSERT(!src1.is(lr)); // r14. 1921 DCHECK(!src1.is(lr)); // r14.
1922 ASSERT_EQ(0, src1.code() % 2); 1922 DCHECK_EQ(0, src1.code() % 2);
1923 ASSERT_EQ(src1.code() + 1, src2.code()); 1923 DCHECK_EQ(src1.code() + 1, src2.code());
1924 ASSERT(IsEnabled(ARMv7)); 1924 DCHECK(IsEnabled(ARMv7));
1925 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); 1925 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
1926 } 1926 }
1927 1927
1928 1928
1929 // Preload instructions. 1929 // Preload instructions.
1930 void Assembler::pld(const MemOperand& address) { 1930 void Assembler::pld(const MemOperand& address) {
1931 // Instruction details available in ARM DDI 0406C.b, A8.8.128. 1931 // Instruction details available in ARM DDI 0406C.b, A8.8.128.
1932 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) | 1932 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
1933 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) | 1933 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
1934 ASSERT(address.rm().is(no_reg)); 1934 DCHECK(address.rm().is(no_reg));
1935 ASSERT(address.am() == Offset); 1935 DCHECK(address.am() == Offset);
1936 int U = B23; 1936 int U = B23;
1937 int offset = address.offset(); 1937 int offset = address.offset();
1938 if (offset < 0) { 1938 if (offset < 0) {
1939 offset = -offset; 1939 offset = -offset;
1940 U = 0; 1940 U = 0;
1941 } 1941 }
1942 ASSERT(offset < 4096); 1942 DCHECK(offset < 4096);
1943 emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 | 1943 emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 |
1944 0xf*B12 | offset); 1944 0xf*B12 | offset);
1945 } 1945 }
1946 1946
1947 1947
1948 // Load/Store multiple instructions. 1948 // Load/Store multiple instructions.
1949 void Assembler::ldm(BlockAddrMode am, 1949 void Assembler::ldm(BlockAddrMode am,
1950 Register base, 1950 Register base,
1951 RegList dst, 1951 RegList dst,
1952 Condition cond) { 1952 Condition cond) {
1953 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. 1953 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable.
1954 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); 1954 DCHECK(base.is(sp) || (dst & sp.bit()) == 0);
1955 1955
1956 addrmod4(cond | B27 | am | L, base, dst); 1956 addrmod4(cond | B27 | am | L, base, dst);
1957 1957
1958 // Emit the constant pool after a function return implemented by ldm ..{..pc}. 1958 // Emit the constant pool after a function return implemented by ldm ..{..pc}.
1959 if (cond == al && (dst & pc.bit()) != 0) { 1959 if (cond == al && (dst & pc.bit()) != 0) {
1960 // There is a slight chance that the ldm instruction was actually a call, 1960 // There is a slight chance that the ldm instruction was actually a call,
1961 // in which case it would be wrong to return into the constant pool; we 1961 // in which case it would be wrong to return into the constant pool; we
1962 // recognize this case by checking if the emission of the pool was blocked 1962 // recognize this case by checking if the emission of the pool was blocked
1963 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is 1963 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1964 // the case, we emit a jump over the pool. 1964 // the case, we emit a jump over the pool.
1965 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); 1965 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1966 } 1966 }
1967 } 1967 }
1968 1968
1969 1969
1970 void Assembler::stm(BlockAddrMode am, 1970 void Assembler::stm(BlockAddrMode am,
1971 Register base, 1971 Register base,
1972 RegList src, 1972 RegList src,
1973 Condition cond) { 1973 Condition cond) {
1974 addrmod4(cond | B27 | am, base, src); 1974 addrmod4(cond | B27 | am, base, src);
1975 } 1975 }
1976 1976
1977 1977
1978 // Exception-generating instructions and debugging support. 1978 // Exception-generating instructions and debugging support.
1979 // Stops with a non-negative code less than kNumOfWatchedStops support 1979 // Stops with a non-negative code less than kNumOfWatchedStops support
1980 // enabling/disabling and a counter feature. See simulator-arm.h . 1980 // enabling/disabling and a counter feature. See simulator-arm.h .
1981 void Assembler::stop(const char* msg, Condition cond, int32_t code) { 1981 void Assembler::stop(const char* msg, Condition cond, int32_t code) {
1982 #ifndef __arm__ 1982 #ifndef __arm__
1983 ASSERT(code >= kDefaultStopCode); 1983 DCHECK(code >= kDefaultStopCode);
1984 { 1984 {
1985 // The Simulator will handle the stop instruction and get the message 1985 // The Simulator will handle the stop instruction and get the message
1986 // address. It expects to find the address just after the svc instruction. 1986 // address. It expects to find the address just after the svc instruction.
1987 BlockConstPoolScope block_const_pool(this); 1987 BlockConstPoolScope block_const_pool(this);
1988 if (code >= 0) { 1988 if (code >= 0) {
1989 svc(kStopCode + code, cond); 1989 svc(kStopCode + code, cond);
1990 } else { 1990 } else {
1991 svc(kStopCode + kMaxStopCode, cond); 1991 svc(kStopCode + kMaxStopCode, cond);
1992 } 1992 }
1993 emit(reinterpret_cast<Instr>(msg)); 1993 emit(reinterpret_cast<Instr>(msg));
1994 } 1994 }
1995 #else // def __arm__ 1995 #else // def __arm__
1996 if (cond != al) { 1996 if (cond != al) {
1997 Label skip; 1997 Label skip;
1998 b(&skip, NegateCondition(cond)); 1998 b(&skip, NegateCondition(cond));
1999 bkpt(0); 1999 bkpt(0);
2000 bind(&skip); 2000 bind(&skip);
2001 } else { 2001 } else {
2002 bkpt(0); 2002 bkpt(0);
2003 } 2003 }
2004 #endif // def __arm__ 2004 #endif // def __arm__
2005 } 2005 }
2006 2006
2007 2007
2008 void Assembler::bkpt(uint32_t imm16) { // v5 and above 2008 void Assembler::bkpt(uint32_t imm16) { // v5 and above
2009 ASSERT(is_uint16(imm16)); 2009 DCHECK(is_uint16(imm16));
2010 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf)); 2010 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
2011 } 2011 }
2012 2012
2013 2013
2014 void Assembler::svc(uint32_t imm24, Condition cond) { 2014 void Assembler::svc(uint32_t imm24, Condition cond) {
2015 ASSERT(is_uint24(imm24)); 2015 DCHECK(is_uint24(imm24));
2016 emit(cond | 15*B24 | imm24); 2016 emit(cond | 15*B24 | imm24);
2017 } 2017 }
2018 2018
2019 2019
2020 // Coprocessor instructions. 2020 // Coprocessor instructions.
2021 void Assembler::cdp(Coprocessor coproc, 2021 void Assembler::cdp(Coprocessor coproc,
2022 int opcode_1, 2022 int opcode_1,
2023 CRegister crd, 2023 CRegister crd,
2024 CRegister crn, 2024 CRegister crn,
2025 CRegister crm, 2025 CRegister crm,
2026 int opcode_2, 2026 int opcode_2,
2027 Condition cond) { 2027 Condition cond) {
2028 ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2)); 2028 DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
2029 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | 2029 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
2030 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code()); 2030 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
2031 } 2031 }
2032 2032
2033 2033
2034 void Assembler::cdp2(Coprocessor coproc, 2034 void Assembler::cdp2(Coprocessor coproc,
2035 int opcode_1, 2035 int opcode_1,
2036 CRegister crd, 2036 CRegister crd,
2037 CRegister crn, 2037 CRegister crn,
2038 CRegister crm, 2038 CRegister crm,
2039 int opcode_2) { // v5 and above 2039 int opcode_2) { // v5 and above
2040 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition); 2040 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
2041 } 2041 }
2042 2042
2043 2043
2044 void Assembler::mcr(Coprocessor coproc, 2044 void Assembler::mcr(Coprocessor coproc,
2045 int opcode_1, 2045 int opcode_1,
2046 Register rd, 2046 Register rd,
2047 CRegister crn, 2047 CRegister crn,
2048 CRegister crm, 2048 CRegister crm,
2049 int opcode_2, 2049 int opcode_2,
2050 Condition cond) { 2050 Condition cond) {
2051 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 2051 DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2052 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | 2052 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
2053 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 2053 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2054 } 2054 }
2055 2055
2056 2056
2057 void Assembler::mcr2(Coprocessor coproc, 2057 void Assembler::mcr2(Coprocessor coproc,
2058 int opcode_1, 2058 int opcode_1,
2059 Register rd, 2059 Register rd,
2060 CRegister crn, 2060 CRegister crn,
2061 CRegister crm, 2061 CRegister crm,
2062 int opcode_2) { // v5 and above 2062 int opcode_2) { // v5 and above
2063 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition); 2063 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2064 } 2064 }
2065 2065
2066 2066
2067 void Assembler::mrc(Coprocessor coproc, 2067 void Assembler::mrc(Coprocessor coproc,
2068 int opcode_1, 2068 int opcode_1,
2069 Register rd, 2069 Register rd,
2070 CRegister crn, 2070 CRegister crn,
2071 CRegister crm, 2071 CRegister crm,
2072 int opcode_2, 2072 int opcode_2,
2073 Condition cond) { 2073 Condition cond) {
2074 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 2074 DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2075 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | 2075 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
2076 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 2076 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2077 } 2077 }
2078 2078
2079 2079
2080 void Assembler::mrc2(Coprocessor coproc, 2080 void Assembler::mrc2(Coprocessor coproc,
2081 int opcode_1, 2081 int opcode_1,
2082 Register rd, 2082 Register rd,
2083 CRegister crn, 2083 CRegister crn,
2084 CRegister crm, 2084 CRegister crm,
(...skipping 11 matching lines...) Expand all
2096 } 2096 }
2097 2097
2098 2098
2099 void Assembler::ldc(Coprocessor coproc, 2099 void Assembler::ldc(Coprocessor coproc,
2100 CRegister crd, 2100 CRegister crd,
2101 Register rn, 2101 Register rn,
2102 int option, 2102 int option,
2103 LFlag l, 2103 LFlag l,
2104 Condition cond) { 2104 Condition cond) {
2105 // Unindexed addressing. 2105 // Unindexed addressing.
2106 ASSERT(is_uint8(option)); 2106 DCHECK(is_uint8(option));
2107 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | 2107 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
2108 coproc*B8 | (option & 255)); 2108 coproc*B8 | (option & 255));
2109 } 2109 }
2110 2110
2111 2111
2112 void Assembler::ldc2(Coprocessor coproc, 2112 void Assembler::ldc2(Coprocessor coproc,
2113 CRegister crd, 2113 CRegister crd,
2114 const MemOperand& src, 2114 const MemOperand& src,
2115 LFlag l) { // v5 and above 2115 LFlag l) { // v5 and above
2116 ldc(coproc, crd, src, l, kSpecialCondition); 2116 ldc(coproc, crd, src, l, kSpecialCondition);
(...skipping 20 matching lines...) Expand all
2137 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) | 2137 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
2138 // Vd(15-12) | 1011(11-8) | offset 2138 // Vd(15-12) | 1011(11-8) | offset
2139 int u = 1; 2139 int u = 1;
2140 if (offset < 0) { 2140 if (offset < 0) {
2141 offset = -offset; 2141 offset = -offset;
2142 u = 0; 2142 u = 0;
2143 } 2143 }
2144 int vd, d; 2144 int vd, d;
2145 dst.split_code(&vd, &d); 2145 dst.split_code(&vd, &d);
2146 2146
2147 ASSERT(offset >= 0); 2147 DCHECK(offset >= 0);
2148 if ((offset % 4) == 0 && (offset / 4) < 256) { 2148 if ((offset % 4) == 0 && (offset / 4) < 256) {
2149 emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 | 2149 emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 |
2150 0xB*B8 | ((offset / 4) & 255)); 2150 0xB*B8 | ((offset / 4) & 255));
2151 } else { 2151 } else {
2152 // Larger offsets must be handled by computing the correct address 2152 // Larger offsets must be handled by computing the correct address
2153 // in the ip register. 2153 // in the ip register.
2154 ASSERT(!base.is(ip)); 2154 DCHECK(!base.is(ip));
2155 if (u == 1) { 2155 if (u == 1) {
2156 add(ip, base, Operand(offset)); 2156 add(ip, base, Operand(offset));
2157 } else { 2157 } else {
2158 sub(ip, base, Operand(offset)); 2158 sub(ip, base, Operand(offset));
2159 } 2159 }
2160 emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8); 2160 emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8);
2161 } 2161 }
2162 } 2162 }
2163 2163
2164 2164
2165 void Assembler::vldr(const DwVfpRegister dst, 2165 void Assembler::vldr(const DwVfpRegister dst,
2166 const MemOperand& operand, 2166 const MemOperand& operand,
2167 const Condition cond) { 2167 const Condition cond) {
2168 ASSERT(operand.am_ == Offset); 2168 DCHECK(operand.am_ == Offset);
2169 if (operand.rm().is_valid()) { 2169 if (operand.rm().is_valid()) {
2170 add(ip, operand.rn(), 2170 add(ip, operand.rn(),
2171 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2171 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2172 vldr(dst, ip, 0, cond); 2172 vldr(dst, ip, 0, cond);
2173 } else { 2173 } else {
2174 vldr(dst, operand.rn(), operand.offset(), cond); 2174 vldr(dst, operand.rn(), operand.offset(), cond);
2175 } 2175 }
2176 } 2176 }
2177 2177
2178 2178
2179 void Assembler::vldr(const SwVfpRegister dst, 2179 void Assembler::vldr(const SwVfpRegister dst,
2180 const Register base, 2180 const Register base,
2181 int offset, 2181 int offset,
2182 const Condition cond) { 2182 const Condition cond) {
2183 // Sdst = MEM(Rbase + offset). 2183 // Sdst = MEM(Rbase + offset).
2184 // Instruction details available in ARM DDI 0406A, A8-628. 2184 // Instruction details available in ARM DDI 0406A, A8-628.
2185 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | 2185 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
2186 // Vdst(15-12) | 1010(11-8) | offset 2186 // Vdst(15-12) | 1010(11-8) | offset
2187 int u = 1; 2187 int u = 1;
2188 if (offset < 0) { 2188 if (offset < 0) {
2189 offset = -offset; 2189 offset = -offset;
2190 u = 0; 2190 u = 0;
2191 } 2191 }
2192 int sd, d; 2192 int sd, d;
2193 dst.split_code(&sd, &d); 2193 dst.split_code(&sd, &d);
2194 ASSERT(offset >= 0); 2194 DCHECK(offset >= 0);
2195 2195
2196 if ((offset % 4) == 0 && (offset / 4) < 256) { 2196 if ((offset % 4) == 0 && (offset / 4) < 256) {
2197 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | 2197 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
2198 0xA*B8 | ((offset / 4) & 255)); 2198 0xA*B8 | ((offset / 4) & 255));
2199 } else { 2199 } else {
2200 // Larger offsets must be handled by computing the correct address 2200 // Larger offsets must be handled by computing the correct address
2201 // in the ip register. 2201 // in the ip register.
2202 ASSERT(!base.is(ip)); 2202 DCHECK(!base.is(ip));
2203 if (u == 1) { 2203 if (u == 1) {
2204 add(ip, base, Operand(offset)); 2204 add(ip, base, Operand(offset));
2205 } else { 2205 } else {
2206 sub(ip, base, Operand(offset)); 2206 sub(ip, base, Operand(offset));
2207 } 2207 }
2208 emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 2208 emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2209 } 2209 }
2210 } 2210 }
2211 2211
2212 2212
2213 void Assembler::vldr(const SwVfpRegister dst, 2213 void Assembler::vldr(const SwVfpRegister dst,
2214 const MemOperand& operand, 2214 const MemOperand& operand,
2215 const Condition cond) { 2215 const Condition cond) {
2216 ASSERT(operand.am_ == Offset); 2216 DCHECK(operand.am_ == Offset);
2217 if (operand.rm().is_valid()) { 2217 if (operand.rm().is_valid()) {
2218 add(ip, operand.rn(), 2218 add(ip, operand.rn(),
2219 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2219 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2220 vldr(dst, ip, 0, cond); 2220 vldr(dst, ip, 0, cond);
2221 } else { 2221 } else {
2222 vldr(dst, operand.rn(), operand.offset(), cond); 2222 vldr(dst, operand.rn(), operand.offset(), cond);
2223 } 2223 }
2224 } 2224 }
2225 2225
2226 2226
2227 void Assembler::vstr(const DwVfpRegister src, 2227 void Assembler::vstr(const DwVfpRegister src,
2228 const Register base, 2228 const Register base,
2229 int offset, 2229 int offset,
2230 const Condition cond) { 2230 const Condition cond) {
2231 // MEM(Rbase + offset) = Dsrc. 2231 // MEM(Rbase + offset) = Dsrc.
2232 // Instruction details available in ARM DDI 0406C.b, A8-1082. 2232 // Instruction details available in ARM DDI 0406C.b, A8-1082.
2233 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) | 2233 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
2234 // Vd(15-12) | 1011(11-8) | (offset/4) 2234 // Vd(15-12) | 1011(11-8) | (offset/4)
2235 int u = 1; 2235 int u = 1;
2236 if (offset < 0) { 2236 if (offset < 0) {
2237 offset = -offset; 2237 offset = -offset;
2238 u = 0; 2238 u = 0;
2239 } 2239 }
2240 ASSERT(offset >= 0); 2240 DCHECK(offset >= 0);
2241 int vd, d; 2241 int vd, d;
2242 src.split_code(&vd, &d); 2242 src.split_code(&vd, &d);
2243 2243
2244 if ((offset % 4) == 0 && (offset / 4) < 256) { 2244 if ((offset % 4) == 0 && (offset / 4) < 256) {
2245 emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 | 2245 emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 |
2246 ((offset / 4) & 255)); 2246 ((offset / 4) & 255));
2247 } else { 2247 } else {
2248 // Larger offsets must be handled by computing the correct address 2248 // Larger offsets must be handled by computing the correct address
2249 // in the ip register. 2249 // in the ip register.
2250 ASSERT(!base.is(ip)); 2250 DCHECK(!base.is(ip));
2251 if (u == 1) { 2251 if (u == 1) {
2252 add(ip, base, Operand(offset)); 2252 add(ip, base, Operand(offset));
2253 } else { 2253 } else {
2254 sub(ip, base, Operand(offset)); 2254 sub(ip, base, Operand(offset));
2255 } 2255 }
2256 emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8); 2256 emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8);
2257 } 2257 }
2258 } 2258 }
2259 2259
2260 2260
2261 void Assembler::vstr(const DwVfpRegister src, 2261 void Assembler::vstr(const DwVfpRegister src,
2262 const MemOperand& operand, 2262 const MemOperand& operand,
2263 const Condition cond) { 2263 const Condition cond) {
2264 ASSERT(operand.am_ == Offset); 2264 DCHECK(operand.am_ == Offset);
2265 if (operand.rm().is_valid()) { 2265 if (operand.rm().is_valid()) {
2266 add(ip, operand.rn(), 2266 add(ip, operand.rn(),
2267 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2267 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2268 vstr(src, ip, 0, cond); 2268 vstr(src, ip, 0, cond);
2269 } else { 2269 } else {
2270 vstr(src, operand.rn(), operand.offset(), cond); 2270 vstr(src, operand.rn(), operand.offset(), cond);
2271 } 2271 }
2272 } 2272 }
2273 2273
2274 2274
2275 void Assembler::vstr(const SwVfpRegister src, 2275 void Assembler::vstr(const SwVfpRegister src,
2276 const Register base, 2276 const Register base,
2277 int offset, 2277 int offset,
2278 const Condition cond) { 2278 const Condition cond) {
2279 // MEM(Rbase + offset) = SSrc. 2279 // MEM(Rbase + offset) = SSrc.
2280 // Instruction details available in ARM DDI 0406A, A8-786. 2280 // Instruction details available in ARM DDI 0406A, A8-786.
2281 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) | 2281 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
2282 // Vdst(15-12) | 1010(11-8) | (offset/4) 2282 // Vdst(15-12) | 1010(11-8) | (offset/4)
2283 int u = 1; 2283 int u = 1;
2284 if (offset < 0) { 2284 if (offset < 0) {
2285 offset = -offset; 2285 offset = -offset;
2286 u = 0; 2286 u = 0;
2287 } 2287 }
2288 int sd, d; 2288 int sd, d;
2289 src.split_code(&sd, &d); 2289 src.split_code(&sd, &d);
2290 ASSERT(offset >= 0); 2290 DCHECK(offset >= 0);
2291 if ((offset % 4) == 0 && (offset / 4) < 256) { 2291 if ((offset % 4) == 0 && (offset / 4) < 256) {
2292 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | 2292 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
2293 0xA*B8 | ((offset / 4) & 255)); 2293 0xA*B8 | ((offset / 4) & 255));
2294 } else { 2294 } else {
2295 // Larger offsets must be handled by computing the correct address 2295 // Larger offsets must be handled by computing the correct address
2296 // in the ip register. 2296 // in the ip register.
2297 ASSERT(!base.is(ip)); 2297 DCHECK(!base.is(ip));
2298 if (u == 1) { 2298 if (u == 1) {
2299 add(ip, base, Operand(offset)); 2299 add(ip, base, Operand(offset));
2300 } else { 2300 } else {
2301 sub(ip, base, Operand(offset)); 2301 sub(ip, base, Operand(offset));
2302 } 2302 }
2303 emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); 2303 emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2304 } 2304 }
2305 } 2305 }
2306 2306
2307 2307
2308 void Assembler::vstr(const SwVfpRegister src, 2308 void Assembler::vstr(const SwVfpRegister src,
2309 const MemOperand& operand, 2309 const MemOperand& operand,
2310 const Condition cond) { 2310 const Condition cond) {
2311 ASSERT(operand.am_ == Offset); 2311 DCHECK(operand.am_ == Offset);
2312 if (operand.rm().is_valid()) { 2312 if (operand.rm().is_valid()) {
2313 add(ip, operand.rn(), 2313 add(ip, operand.rn(),
2314 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_)); 2314 Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2315 vstr(src, ip, 0, cond); 2315 vstr(src, ip, 0, cond);
2316 } else { 2316 } else {
2317 vstr(src, operand.rn(), operand.offset(), cond); 2317 vstr(src, operand.rn(), operand.offset(), cond);
2318 } 2318 }
2319 } 2319 }
2320 2320
2321 2321
2322 void Assembler::vldm(BlockAddrMode am, 2322 void Assembler::vldm(BlockAddrMode am,
2323 Register base, 2323 Register base,
2324 DwVfpRegister first, 2324 DwVfpRegister first,
2325 DwVfpRegister last, 2325 DwVfpRegister last,
2326 Condition cond) { 2326 Condition cond) {
2327 // Instruction details available in ARM DDI 0406C.b, A8-922. 2327 // Instruction details available in ARM DDI 0406C.b, A8-922.
2328 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 2328 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2329 // first(15-12) | 1011(11-8) | (count * 2) 2329 // first(15-12) | 1011(11-8) | (count * 2)
2330 ASSERT_LE(first.code(), last.code()); 2330 DCHECK_LE(first.code(), last.code());
2331 ASSERT(am == ia || am == ia_w || am == db_w); 2331 DCHECK(am == ia || am == ia_w || am == db_w);
2332 ASSERT(!base.is(pc)); 2332 DCHECK(!base.is(pc));
2333 2333
2334 int sd, d; 2334 int sd, d;
2335 first.split_code(&sd, &d); 2335 first.split_code(&sd, &d);
2336 int count = last.code() - first.code() + 1; 2336 int count = last.code() - first.code() + 1;
2337 ASSERT(count <= 16); 2337 DCHECK(count <= 16);
2338 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 2338 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2339 0xB*B8 | count*2); 2339 0xB*B8 | count*2);
2340 } 2340 }
2341 2341
2342 2342
2343 void Assembler::vstm(BlockAddrMode am, 2343 void Assembler::vstm(BlockAddrMode am,
2344 Register base, 2344 Register base,
2345 DwVfpRegister first, 2345 DwVfpRegister first,
2346 DwVfpRegister last, 2346 DwVfpRegister last,
2347 Condition cond) { 2347 Condition cond) {
2348 // Instruction details available in ARM DDI 0406C.b, A8-1080. 2348 // Instruction details available in ARM DDI 0406C.b, A8-1080.
2349 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 2349 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2350 // first(15-12) | 1011(11-8) | (count * 2) 2350 // first(15-12) | 1011(11-8) | (count * 2)
2351 ASSERT_LE(first.code(), last.code()); 2351 DCHECK_LE(first.code(), last.code());
2352 ASSERT(am == ia || am == ia_w || am == db_w); 2352 DCHECK(am == ia || am == ia_w || am == db_w);
2353 ASSERT(!base.is(pc)); 2353 DCHECK(!base.is(pc));
2354 2354
2355 int sd, d; 2355 int sd, d;
2356 first.split_code(&sd, &d); 2356 first.split_code(&sd, &d);
2357 int count = last.code() - first.code() + 1; 2357 int count = last.code() - first.code() + 1;
2358 ASSERT(count <= 16); 2358 DCHECK(count <= 16);
2359 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 2359 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2360 0xB*B8 | count*2); 2360 0xB*B8 | count*2);
2361 } 2361 }
2362 2362
2363 void Assembler::vldm(BlockAddrMode am, 2363 void Assembler::vldm(BlockAddrMode am,
2364 Register base, 2364 Register base,
2365 SwVfpRegister first, 2365 SwVfpRegister first,
2366 SwVfpRegister last, 2366 SwVfpRegister last,
2367 Condition cond) { 2367 Condition cond) {
2368 // Instruction details available in ARM DDI 0406A, A8-626. 2368 // Instruction details available in ARM DDI 0406A, A8-626.
2369 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | 2369 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2370 // first(15-12) | 1010(11-8) | (count/2) 2370 // first(15-12) | 1010(11-8) | (count/2)
2371 ASSERT_LE(first.code(), last.code()); 2371 DCHECK_LE(first.code(), last.code());
2372 ASSERT(am == ia || am == ia_w || am == db_w); 2372 DCHECK(am == ia || am == ia_w || am == db_w);
2373 ASSERT(!base.is(pc)); 2373 DCHECK(!base.is(pc));
2374 2374
2375 int sd, d; 2375 int sd, d;
2376 first.split_code(&sd, &d); 2376 first.split_code(&sd, &d);
2377 int count = last.code() - first.code() + 1; 2377 int count = last.code() - first.code() + 1;
2378 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | 2378 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2379 0xA*B8 | count); 2379 0xA*B8 | count);
2380 } 2380 }
2381 2381
2382 2382
2383 void Assembler::vstm(BlockAddrMode am, 2383 void Assembler::vstm(BlockAddrMode am,
2384 Register base, 2384 Register base,
2385 SwVfpRegister first, 2385 SwVfpRegister first,
2386 SwVfpRegister last, 2386 SwVfpRegister last,
2387 Condition cond) { 2387 Condition cond) {
2388 // Instruction details available in ARM DDI 0406A, A8-784. 2388 // Instruction details available in ARM DDI 0406A, A8-784.
2389 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | 2389 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2390 // first(15-12) | 1011(11-8) | (count/2) 2390 // first(15-12) | 1011(11-8) | (count/2)
2391 ASSERT_LE(first.code(), last.code()); 2391 DCHECK_LE(first.code(), last.code());
2392 ASSERT(am == ia || am == ia_w || am == db_w); 2392 DCHECK(am == ia || am == ia_w || am == db_w);
2393 ASSERT(!base.is(pc)); 2393 DCHECK(!base.is(pc));
2394 2394
2395 int sd, d; 2395 int sd, d;
2396 first.split_code(&sd, &d); 2396 first.split_code(&sd, &d);
2397 int count = last.code() - first.code() + 1; 2397 int count = last.code() - first.code() + 1;
2398 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 | 2398 emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2399 0xA*B8 | count); 2399 0xA*B8 | count);
2400 } 2400 }
2401 2401
2402 2402
2403 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { 2403 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2404 uint64_t i; 2404 uint64_t i;
2405 memcpy(&i, &d, 8); 2405 memcpy(&i, &d, 8);
2406 2406
2407 *lo = i & 0xffffffff; 2407 *lo = i & 0xffffffff;
2408 *hi = i >> 32; 2408 *hi = i >> 32;
2409 } 2409 }
2410 2410
2411 2411
2412 // Only works for little endian floating point formats. 2412 // Only works for little endian floating point formats.
2413 // We don't support VFP on the mixed endian floating point platform. 2413 // We don't support VFP on the mixed endian floating point platform.
2414 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) { 2414 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
2415 ASSERT(CpuFeatures::IsSupported(VFP3)); 2415 DCHECK(CpuFeatures::IsSupported(VFP3));
2416 2416
2417 // VMOV can accept an immediate of the form: 2417 // VMOV can accept an immediate of the form:
2418 // 2418 //
2419 // +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7 2419 // +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
2420 // 2420 //
2421 // The immediate is encoded using an 8-bit quantity, comprised of two 2421 // The immediate is encoded using an 8-bit quantity, comprised of two
2422 // 4-bit fields. For an 8-bit immediate of the form: 2422 // 4-bit fields. For an 8-bit immediate of the form:
2423 // 2423 //
2424 // [abcdefgh] 2424 // [abcdefgh]
2425 // 2425 //
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 // We could also add a few peepholes here like detecting 0.0 and 2486 // We could also add a few peepholes here like detecting 0.0 and
2487 // -0.0 and doing a vmov from the sequestered d14, forcing denorms 2487 // -0.0 and doing a vmov from the sequestered d14, forcing denorms
2488 // to zero (we set flush-to-zero), and normalizing NaN values. 2488 // to zero (we set flush-to-zero), and normalizing NaN values.
2489 // We could also detect redundant values. 2489 // We could also detect redundant values.
2490 // The code could also randomize the order of values, though 2490 // The code could also randomize the order of values, though
2491 // that's tricky because vldr has a limited reach. Furthermore 2491 // that's tricky because vldr has a limited reach. Furthermore
2492 // it breaks load locality. 2492 // it breaks load locality.
2493 RelocInfo rinfo(pc_, imm); 2493 RelocInfo rinfo(pc_, imm);
2494 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo); 2494 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
2495 if (section == ConstantPoolArray::EXTENDED_SECTION) { 2495 if (section == ConstantPoolArray::EXTENDED_SECTION) {
2496 ASSERT(FLAG_enable_ool_constant_pool); 2496 DCHECK(FLAG_enable_ool_constant_pool);
2497 // Emit instructions to load constant pool offset. 2497 // Emit instructions to load constant pool offset.
2498 movw(ip, 0); 2498 movw(ip, 0);
2499 movt(ip, 0); 2499 movt(ip, 0);
2500 // Load from constant pool at offset. 2500 // Load from constant pool at offset.
2501 vldr(dst, MemOperand(pp, ip)); 2501 vldr(dst, MemOperand(pp, ip));
2502 } else { 2502 } else {
2503 ASSERT(section == ConstantPoolArray::SMALL_SECTION); 2503 DCHECK(section == ConstantPoolArray::SMALL_SECTION);
2504 vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0)); 2504 vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0));
2505 } 2505 }
2506 } else { 2506 } else {
2507 // Synthesise the double from ARM immediates. 2507 // Synthesise the double from ARM immediates.
2508 uint32_t lo, hi; 2508 uint32_t lo, hi;
2509 DoubleAsTwoUInt32(imm, &lo, &hi); 2509 DoubleAsTwoUInt32(imm, &lo, &hi);
2510 2510
2511 if (scratch.is(no_reg)) { 2511 if (scratch.is(no_reg)) {
2512 if (dst.code() < 16) { 2512 if (dst.code() < 16) {
2513 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code()); 2513 const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2569 2569
2570 2570
2571 void Assembler::vmov(const DwVfpRegister dst, 2571 void Assembler::vmov(const DwVfpRegister dst,
2572 const VmovIndex index, 2572 const VmovIndex index,
2573 const Register src, 2573 const Register src,
2574 const Condition cond) { 2574 const Condition cond) {
2575 // Dd[index] = Rt 2575 // Dd[index] = Rt
2576 // Instruction details available in ARM DDI 0406C.b, A8-940. 2576 // Instruction details available in ARM DDI 0406C.b, A8-940.
2577 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | 2577 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
2578 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) 2578 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2579 ASSERT(index.index == 0 || index.index == 1); 2579 DCHECK(index.index == 0 || index.index == 1);
2580 int vd, d; 2580 int vd, d;
2581 dst.split_code(&vd, &d); 2581 dst.split_code(&vd, &d);
2582 emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | 2582 emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
2583 d*B7 | B4); 2583 d*B7 | B4);
2584 } 2584 }
2585 2585
2586 2586
2587 void Assembler::vmov(const Register dst, 2587 void Assembler::vmov(const Register dst,
2588 const VmovIndex index, 2588 const VmovIndex index,
2589 const DwVfpRegister src, 2589 const DwVfpRegister src,
2590 const Condition cond) { 2590 const Condition cond) {
2591 // Dd[index] = Rt 2591 // Dd[index] = Rt
2592 // Instruction details available in ARM DDI 0406C.b, A8.8.342. 2592 // Instruction details available in ARM DDI 0406C.b, A8.8.342.
2593 // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) | 2593 // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
2594 // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0) 2594 // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2595 ASSERT(index.index == 0 || index.index == 1); 2595 DCHECK(index.index == 0 || index.index == 1);
2596 int vn, n; 2596 int vn, n;
2597 src.split_code(&vn, &n); 2597 src.split_code(&vn, &n);
2598 emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 | 2598 emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
2599 0xB*B8 | n*B7 | B4); 2599 0xB*B8 | n*B7 | B4);
2600 } 2600 }
2601 2601
2602 2602
2603 void Assembler::vmov(const DwVfpRegister dst, 2603 void Assembler::vmov(const DwVfpRegister dst,
2604 const Register src1, 2604 const Register src1,
2605 const Register src2, 2605 const Register src2,
2606 const Condition cond) { 2606 const Condition cond) {
2607 // Dm = <Rt,Rt2>. 2607 // Dm = <Rt,Rt2>.
2608 // Instruction details available in ARM DDI 0406C.b, A8-948. 2608 // Instruction details available in ARM DDI 0406C.b, A8-948.
2609 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | 2609 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2610 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2610 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2611 ASSERT(!src1.is(pc) && !src2.is(pc)); 2611 DCHECK(!src1.is(pc) && !src2.is(pc));
2612 int vm, m; 2612 int vm, m;
2613 dst.split_code(&vm, &m); 2613 dst.split_code(&vm, &m);
2614 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | 2614 emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2615 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); 2615 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2616 } 2616 }
2617 2617
2618 2618
2619 void Assembler::vmov(const Register dst1, 2619 void Assembler::vmov(const Register dst1,
2620 const Register dst2, 2620 const Register dst2,
2621 const DwVfpRegister src, 2621 const DwVfpRegister src,
2622 const Condition cond) { 2622 const Condition cond) {
2623 // <Rt,Rt2> = Dm. 2623 // <Rt,Rt2> = Dm.
2624 // Instruction details available in ARM DDI 0406C.b, A8-948. 2624 // Instruction details available in ARM DDI 0406C.b, A8-948.
2625 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | 2625 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2626 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 2626 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2627 ASSERT(!dst1.is(pc) && !dst2.is(pc)); 2627 DCHECK(!dst1.is(pc) && !dst2.is(pc));
2628 int vm, m; 2628 int vm, m;
2629 src.split_code(&vm, &m); 2629 src.split_code(&vm, &m);
2630 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | 2630 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2631 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); 2631 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2632 } 2632 }
2633 2633
2634 2634
2635 void Assembler::vmov(const SwVfpRegister dst, 2635 void Assembler::vmov(const SwVfpRegister dst,
2636 const Register src, 2636 const Register src,
2637 const Condition cond) { 2637 const Condition cond) {
2638 // Sn = Rt. 2638 // Sn = Rt.
2639 // Instruction details available in ARM DDI 0406A, A8-642. 2639 // Instruction details available in ARM DDI 0406A, A8-642.
2640 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | 2640 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2641 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2641 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2642 ASSERT(!src.is(pc)); 2642 DCHECK(!src.is(pc));
2643 int sn, n; 2643 int sn, n;
2644 dst.split_code(&sn, &n); 2644 dst.split_code(&sn, &n);
2645 emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4); 2645 emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2646 } 2646 }
2647 2647
2648 2648
2649 void Assembler::vmov(const Register dst, 2649 void Assembler::vmov(const Register dst,
2650 const SwVfpRegister src, 2650 const SwVfpRegister src,
2651 const Condition cond) { 2651 const Condition cond) {
2652 // Rt = Sn. 2652 // Rt = Sn.
2653 // Instruction details available in ARM DDI 0406A, A8-642. 2653 // Instruction details available in ARM DDI 0406A, A8-642.
2654 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | 2654 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2655 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 2655 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2656 ASSERT(!dst.is(pc)); 2656 DCHECK(!dst.is(pc));
2657 int sn, n; 2657 int sn, n;
2658 src.split_code(&sn, &n); 2658 src.split_code(&sn, &n);
2659 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4); 2659 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2660 } 2660 }
2661 2661
2662 2662
2663 // Type of data to read from or write to VFP register. 2663 // Type of data to read from or write to VFP register.
2664 // Used as specifier in generic vcvt instruction. 2664 // Used as specifier in generic vcvt instruction.
2665 enum VFPType { S32, U32, F32, F64 }; 2665 enum VFPType { S32, U32, F32, F64 };
2666 2666
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2707 2707
2708 2708
2709 // Split five bit reg_code based on size of reg_type. 2709 // Split five bit reg_code based on size of reg_type.
2710 // 32-bit register codes are Vm:M 2710 // 32-bit register codes are Vm:M
2711 // 64-bit register codes are M:Vm 2711 // 64-bit register codes are M:Vm
2712 // where Vm is four bits, and M is a single bit. 2712 // where Vm is four bits, and M is a single bit.
2713 static void SplitRegCode(VFPType reg_type, 2713 static void SplitRegCode(VFPType reg_type,
2714 int reg_code, 2714 int reg_code,
2715 int* vm, 2715 int* vm,
2716 int* m) { 2716 int* m) {
2717 ASSERT((reg_code >= 0) && (reg_code <= 31)); 2717 DCHECK((reg_code >= 0) && (reg_code <= 31));
2718 if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) { 2718 if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
2719 // 32 bit type. 2719 // 32 bit type.
2720 *m = reg_code & 0x1; 2720 *m = reg_code & 0x1;
2721 *vm = reg_code >> 1; 2721 *vm = reg_code >> 1;
2722 } else { 2722 } else {
2723 // 64 bit type. 2723 // 64 bit type.
2724 *m = (reg_code & 0x10) >> 4; 2724 *m = (reg_code & 0x10) >> 4;
2725 *vm = reg_code & 0x0F; 2725 *vm = reg_code & 0x0F;
2726 } 2726 }
2727 } 2727 }
2728 2728
2729 2729
2730 // Encode vcvt.src_type.dst_type instruction. 2730 // Encode vcvt.src_type.dst_type instruction.
2731 static Instr EncodeVCVT(const VFPType dst_type, 2731 static Instr EncodeVCVT(const VFPType dst_type,
2732 const int dst_code, 2732 const int dst_code,
2733 const VFPType src_type, 2733 const VFPType src_type,
2734 const int src_code, 2734 const int src_code,
2735 VFPConversionMode mode, 2735 VFPConversionMode mode,
2736 const Condition cond) { 2736 const Condition cond) {
2737 ASSERT(src_type != dst_type); 2737 DCHECK(src_type != dst_type);
2738 int D, Vd, M, Vm; 2738 int D, Vd, M, Vm;
2739 SplitRegCode(src_type, src_code, &Vm, &M); 2739 SplitRegCode(src_type, src_code, &Vm, &M);
2740 SplitRegCode(dst_type, dst_code, &Vd, &D); 2740 SplitRegCode(dst_type, dst_code, &Vd, &D);
2741 2741
2742 if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) { 2742 if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
2743 // Conversion between IEEE floating point and 32-bit integer. 2743 // Conversion between IEEE floating point and 32-bit integer.
2744 // Instruction details available in ARM DDI 0406B, A8.6.295. 2744 // Instruction details available in ARM DDI 0406B, A8.6.295.
2745 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) | 2745 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
2746 // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0) 2746 // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2747 ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type)); 2747 DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
2748 2748
2749 int sz, opc2, op; 2749 int sz, opc2, op;
2750 2750
2751 if (IsIntegerVFPType(dst_type)) { 2751 if (IsIntegerVFPType(dst_type)) {
2752 opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4; 2752 opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
2753 sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0; 2753 sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2754 op = mode; 2754 op = mode;
2755 } else { 2755 } else {
2756 ASSERT(IsIntegerVFPType(src_type)); 2756 DCHECK(IsIntegerVFPType(src_type));
2757 opc2 = 0x0; 2757 opc2 = 0x0;
2758 sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0; 2758 sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
2759 op = IsSignedVFPType(src_type) ? 0x1 : 0x0; 2759 op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
2760 } 2760 }
2761 2761
2762 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 | 2762 return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
2763 Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm); 2763 Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
2764 } else { 2764 } else {
2765 // Conversion between IEEE double and single precision. 2765 // Conversion between IEEE double and single precision.
2766 // Instruction details available in ARM DDI 0406B, A8.6.298. 2766 // Instruction details available in ARM DDI 0406B, A8.6.298.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2828 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); 2828 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2829 } 2829 }
2830 2830
2831 2831
2832 void Assembler::vcvt_f64_s32(const DwVfpRegister dst, 2832 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
2833 int fraction_bits, 2833 int fraction_bits,
2834 const Condition cond) { 2834 const Condition cond) {
2835 // Instruction details available in ARM DDI 0406C.b, A8-874. 2835 // Instruction details available in ARM DDI 0406C.b, A8-874.
2836 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) | 2836 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
2837 // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0) 2837 // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
2838 ASSERT(fraction_bits > 0 && fraction_bits <= 32); 2838 DCHECK(fraction_bits > 0 && fraction_bits <= 32);
2839 ASSERT(CpuFeatures::IsSupported(VFP3)); 2839 DCHECK(CpuFeatures::IsSupported(VFP3));
2840 int vd, d; 2840 int vd, d;
2841 dst.split_code(&vd, &d); 2841 dst.split_code(&vd, &d);
2842 int imm5 = 32 - fraction_bits; 2842 int imm5 = 32 - fraction_bits;
2843 int i = imm5 & 1; 2843 int i = imm5 & 1;
2844 int imm4 = (imm5 >> 1) & 0xf; 2844 int imm4 = (imm5 >> 1) & 0xf;
2845 emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 | 2845 emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 |
2846 vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4); 2846 vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4);
2847 } 2847 }
2848 2848
2849 2849
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3010 } 3010 }
3011 3011
3012 3012
3013 void Assembler::vcmp(const DwVfpRegister src1, 3013 void Assembler::vcmp(const DwVfpRegister src1,
3014 const double src2, 3014 const double src2,
3015 const Condition cond) { 3015 const Condition cond) {
3016 // vcmp(Dd, #0.0) double precision floating point comparison. 3016 // vcmp(Dd, #0.0) double precision floating point comparison.
3017 // Instruction details available in ARM DDI 0406C.b, A8-864. 3017 // Instruction details available in ARM DDI 0406C.b, A8-864.
3018 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | 3018 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3019 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) 3019 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3020 ASSERT(src2 == 0.0); 3020 DCHECK(src2 == 0.0);
3021 int vd, d; 3021 int vd, d;
3022 src1.split_code(&vd, &d); 3022 src1.split_code(&vd, &d);
3023 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); 3023 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6);
3024 } 3024 }
3025 3025
3026 3026
3027 void Assembler::vmsr(Register dst, Condition cond) { 3027 void Assembler::vmsr(Register dst, Condition cond) {
3028 // Instruction details available in ARM DDI 0406A, A8-652. 3028 // Instruction details available in ARM DDI 0406A, A8-652.
3029 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | 3029 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
3030 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 3030 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
(...skipping 27 matching lines...) Expand all
3058 3058
3059 3059
3060 // Support for NEON. 3060 // Support for NEON.
3061 3061
3062 void Assembler::vld1(NeonSize size, 3062 void Assembler::vld1(NeonSize size,
3063 const NeonListOperand& dst, 3063 const NeonListOperand& dst,
3064 const NeonMemOperand& src) { 3064 const NeonMemOperand& src) {
3065 // Instruction details available in ARM DDI 0406C.b, A8.8.320. 3065 // Instruction details available in ARM DDI 0406C.b, A8.8.320.
3066 // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) | 3066 // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
3067 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) 3067 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3068 ASSERT(CpuFeatures::IsSupported(NEON)); 3068 DCHECK(CpuFeatures::IsSupported(NEON));
3069 int vd, d; 3069 int vd, d;
3070 dst.base().split_code(&vd, &d); 3070 dst.base().split_code(&vd, &d);
3071 emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 | 3071 emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 |
3072 dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code()); 3072 dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
3073 } 3073 }
3074 3074
3075 3075
3076 void Assembler::vst1(NeonSize size, 3076 void Assembler::vst1(NeonSize size,
3077 const NeonListOperand& src, 3077 const NeonListOperand& src,
3078 const NeonMemOperand& dst) { 3078 const NeonMemOperand& dst) {
3079 // Instruction details available in ARM DDI 0406C.b, A8.8.404. 3079 // Instruction details available in ARM DDI 0406C.b, A8.8.404.
3080 // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) | 3080 // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
3081 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) 3081 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3082 ASSERT(CpuFeatures::IsSupported(NEON)); 3082 DCHECK(CpuFeatures::IsSupported(NEON));
3083 int vd, d; 3083 int vd, d;
3084 src.base().split_code(&vd, &d); 3084 src.base().split_code(&vd, &d);
3085 emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 | 3085 emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 |
3086 size*B6 | dst.align()*B4 | dst.rm().code()); 3086 size*B6 | dst.align()*B4 | dst.rm().code());
3087 } 3087 }
3088 3088
3089 3089
3090 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) { 3090 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
3091 // Instruction details available in ARM DDI 0406C.b, A8.8.346. 3091 // Instruction details available in ARM DDI 0406C.b, A8.8.346.
3092 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) | 3092 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
3093 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) 3093 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
3094 ASSERT(CpuFeatures::IsSupported(NEON)); 3094 DCHECK(CpuFeatures::IsSupported(NEON));
3095 int vd, d; 3095 int vd, d;
3096 dst.split_code(&vd, &d); 3096 dst.split_code(&vd, &d);
3097 int vm, m; 3097 int vm, m;
3098 src.split_code(&vm, &m); 3098 src.split_code(&vm, &m);
3099 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | 3099 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 |
3100 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); 3100 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm);
3101 } 3101 }
3102 3102
3103 3103
3104 // Pseudo instructions. 3104 // Pseudo instructions.
3105 void Assembler::nop(int type) { 3105 void Assembler::nop(int type) {
3106 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes 3106 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
3107 // some of the CPU's pipeline and has to issue. Older ARM chips simply used 3107 // some of the CPU's pipeline and has to issue. Older ARM chips simply used
3108 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. 3108 // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
3109 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode 3109 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
3110 // a type. 3110 // a type.
3111 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. 3111 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop.
3112 emit(al | 13*B21 | type*B12 | type); 3112 emit(al | 13*B21 | type*B12 | type);
3113 } 3113 }
3114 3114
3115 3115
3116 bool Assembler::IsMovT(Instr instr) { 3116 bool Assembler::IsMovT(Instr instr) {
3117 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions 3117 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions
3118 ((kNumRegisters-1)*B12) | // mask out register 3118 ((kNumRegisters-1)*B12) | // mask out register
3119 EncodeMovwImmediate(0xFFFF)); // mask out immediate value 3119 EncodeMovwImmediate(0xFFFF)); // mask out immediate value
3120 return instr == kMovtPattern; 3120 return instr == kMovtPattern;
3121 } 3121 }
3122 3122
3123 3123
3124 bool Assembler::IsMovW(Instr instr) { 3124 bool Assembler::IsMovW(Instr instr) {
3125 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions 3125 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions
3126 ((kNumRegisters-1)*B12) | // mask out destination 3126 ((kNumRegisters-1)*B12) | // mask out destination
3127 EncodeMovwImmediate(0xFFFF)); // mask out immediate value 3127 EncodeMovwImmediate(0xFFFF)); // mask out immediate value
3128 return instr == kMovwPattern; 3128 return instr == kMovwPattern;
3129 } 3129 }
3130 3130
3131 3131
3132 Instr Assembler::GetMovTPattern() { return kMovtPattern; } 3132 Instr Assembler::GetMovTPattern() { return kMovtPattern; }
3133 3133
3134 3134
3135 Instr Assembler::GetMovWPattern() { return kMovwPattern; } 3135 Instr Assembler::GetMovWPattern() { return kMovwPattern; }
3136 3136
3137 3137
3138 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) { 3138 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) {
3139 ASSERT(immediate < 0x10000); 3139 DCHECK(immediate < 0x10000);
3140 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); 3140 return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
3141 } 3141 }
3142 3142
3143 3143
3144 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) { 3144 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
3145 instruction &= ~EncodeMovwImmediate(0xffff); 3145 instruction &= ~EncodeMovwImmediate(0xffff);
3146 return instruction | EncodeMovwImmediate(immediate); 3146 return instruction | EncodeMovwImmediate(immediate);
3147 } 3147 }
3148 3148
3149 3149
3150 bool Assembler::IsNop(Instr instr, int type) { 3150 bool Assembler::IsNop(Instr instr, int type) {
3151 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. 3151 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop.
3152 // Check for mov rx, rx where x = type. 3152 // Check for mov rx, rx where x = type.
3153 return instr == (al | 13*B21 | type*B12 | type); 3153 return instr == (al | 13*B21 | type*B12 | type);
3154 } 3154 }
3155 3155
3156 3156
3157 // static 3157 // static
3158 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 3158 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
3159 uint32_t dummy1; 3159 uint32_t dummy1;
3160 uint32_t dummy2; 3160 uint32_t dummy2;
3161 return fits_shifter(imm32, &dummy1, &dummy2, NULL); 3161 return fits_shifter(imm32, &dummy1, &dummy2, NULL);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3232 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 3232 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3233 reloc_info_writer.last_pc() + pc_delta); 3233 reloc_info_writer.last_pc() + pc_delta);
3234 3234
3235 // None of our relocation types are pc relative pointing outside the code 3235 // None of our relocation types are pc relative pointing outside the code
3236 // buffer nor pc absolute pointing inside the code buffer, so there is no need 3236 // buffer nor pc absolute pointing inside the code buffer, so there is no need
3237 // to relocate any emitted relocation entries. 3237 // to relocate any emitted relocation entries.
3238 3238
3239 // Relocate pending relocation entries. 3239 // Relocate pending relocation entries.
3240 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) { 3240 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
3241 RelocInfo& rinfo = pending_32_bit_reloc_info_[i]; 3241 RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
3242 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 3242 DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
3243 rinfo.rmode() != RelocInfo::POSITION); 3243 rinfo.rmode() != RelocInfo::POSITION);
3244 if (rinfo.rmode() != RelocInfo::JS_RETURN) { 3244 if (rinfo.rmode() != RelocInfo::JS_RETURN) {
3245 rinfo.set_pc(rinfo.pc() + pc_delta); 3245 rinfo.set_pc(rinfo.pc() + pc_delta);
3246 } 3246 }
3247 } 3247 }
3248 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) { 3248 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
3249 RelocInfo& rinfo = pending_64_bit_reloc_info_[i]; 3249 RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
3250 ASSERT(rinfo.rmode() == RelocInfo::NONE64); 3250 DCHECK(rinfo.rmode() == RelocInfo::NONE64);
3251 rinfo.set_pc(rinfo.pc() + pc_delta); 3251 rinfo.set_pc(rinfo.pc() + pc_delta);
3252 } 3252 }
3253 constant_pool_builder_.Relocate(pc_delta); 3253 constant_pool_builder_.Relocate(pc_delta);
3254 } 3254 }
3255 3255
3256 3256
3257 void Assembler::db(uint8_t data) { 3257 void Assembler::db(uint8_t data) {
3258 // No relocation info should be pending while using db. db is used 3258 // No relocation info should be pending while using db. db is used
3259 // to write pure data with no pointers and the constant pool should 3259 // to write pure data with no pointers and the constant pool should
3260 // be emitted before using db. 3260 // be emitted before using db.
3261 ASSERT(num_pending_32_bit_reloc_info_ == 0); 3261 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3262 ASSERT(num_pending_64_bit_reloc_info_ == 0); 3262 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3263 CheckBuffer(); 3263 CheckBuffer();
3264 *reinterpret_cast<uint8_t*>(pc_) = data; 3264 *reinterpret_cast<uint8_t*>(pc_) = data;
3265 pc_ += sizeof(uint8_t); 3265 pc_ += sizeof(uint8_t);
3266 } 3266 }
3267 3267
3268 3268
3269 void Assembler::dd(uint32_t data) { 3269 void Assembler::dd(uint32_t data) {
3270 // No relocation info should be pending while using dd. dd is used 3270 // No relocation info should be pending while using dd. dd is used
3271 // to write pure data with no pointers and the constant pool should 3271 // to write pure data with no pointers and the constant pool should
3272 // be emitted before using dd. 3272 // be emitted before using dd.
3273 ASSERT(num_pending_32_bit_reloc_info_ == 0); 3273 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3274 ASSERT(num_pending_64_bit_reloc_info_ == 0); 3274 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3275 CheckBuffer(); 3275 CheckBuffer();
3276 *reinterpret_cast<uint32_t*>(pc_) = data; 3276 *reinterpret_cast<uint32_t*>(pc_) = data;
3277 pc_ += sizeof(uint32_t); 3277 pc_ += sizeof(uint32_t);
3278 } 3278 }
3279 3279
3280 3280
3281 void Assembler::emit_code_stub_address(Code* stub) { 3281 void Assembler::emit_code_stub_address(Code* stub) {
3282 CheckBuffer(); 3282 CheckBuffer();
3283 *reinterpret_cast<uint32_t*>(pc_) = 3283 *reinterpret_cast<uint32_t*>(pc_) =
3284 reinterpret_cast<uint32_t>(stub->instruction_start()); 3284 reinterpret_cast<uint32_t>(stub->instruction_start());
3285 pc_ += sizeof(uint32_t); 3285 pc_ += sizeof(uint32_t);
3286 } 3286 }
3287 3287
3288 3288
3289 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 3289 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3290 RelocInfo rinfo(pc_, rmode, data, NULL); 3290 RelocInfo rinfo(pc_, rmode, data, NULL);
3291 RecordRelocInfo(rinfo); 3291 RecordRelocInfo(rinfo);
3292 } 3292 }
3293 3293
3294 3294
3295 void Assembler::RecordRelocInfo(const RelocInfo& rinfo) { 3295 void Assembler::RecordRelocInfo(const RelocInfo& rinfo) {
3296 if (!RelocInfo::IsNone(rinfo.rmode())) { 3296 if (!RelocInfo::IsNone(rinfo.rmode())) {
3297 // Don't record external references unless the heap will be serialized. 3297 // Don't record external references unless the heap will be serialized.
3298 if (rinfo.rmode() == RelocInfo::EXTERNAL_REFERENCE && 3298 if (rinfo.rmode() == RelocInfo::EXTERNAL_REFERENCE &&
3299 !serializer_enabled() && !emit_debug_code()) { 3299 !serializer_enabled() && !emit_debug_code()) {
3300 return; 3300 return;
3301 } 3301 }
3302 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 3302 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
3303 if (rinfo.rmode() == RelocInfo::CODE_TARGET_WITH_ID) { 3303 if (rinfo.rmode() == RelocInfo::CODE_TARGET_WITH_ID) {
3304 RelocInfo reloc_info_with_ast_id(rinfo.pc(), 3304 RelocInfo reloc_info_with_ast_id(rinfo.pc(),
3305 rinfo.rmode(), 3305 rinfo.rmode(),
3306 RecordedAstId().ToInt(), 3306 RecordedAstId().ToInt(),
3307 NULL); 3307 NULL);
3308 ClearRecordedAstId(); 3308 ClearRecordedAstId();
3309 reloc_info_writer.Write(&reloc_info_with_ast_id); 3309 reloc_info_writer.Write(&reloc_info_with_ast_id);
3310 } else { 3310 } else {
3311 reloc_info_writer.Write(&rinfo); 3311 reloc_info_writer.Write(&rinfo);
3312 } 3312 }
3313 } 3313 }
3314 } 3314 }
3315 3315
3316 3316
3317 ConstantPoolArray::LayoutSection Assembler::ConstantPoolAddEntry( 3317 ConstantPoolArray::LayoutSection Assembler::ConstantPoolAddEntry(
3318 const RelocInfo& rinfo) { 3318 const RelocInfo& rinfo) {
3319 if (FLAG_enable_ool_constant_pool) { 3319 if (FLAG_enable_ool_constant_pool) {
3320 return constant_pool_builder_.AddEntry(this, rinfo); 3320 return constant_pool_builder_.AddEntry(this, rinfo);
3321 } else { 3321 } else {
3322 if (rinfo.rmode() == RelocInfo::NONE64) { 3322 if (rinfo.rmode() == RelocInfo::NONE64) {
3323 ASSERT(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo); 3323 DCHECK(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo);
3324 if (num_pending_64_bit_reloc_info_ == 0) { 3324 if (num_pending_64_bit_reloc_info_ == 0) {
3325 first_const_pool_64_use_ = pc_offset(); 3325 first_const_pool_64_use_ = pc_offset();
3326 } 3326 }
3327 pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo; 3327 pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo;
3328 } else { 3328 } else {
3329 ASSERT(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo); 3329 DCHECK(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo);
3330 if (num_pending_32_bit_reloc_info_ == 0) { 3330 if (num_pending_32_bit_reloc_info_ == 0) {
3331 first_const_pool_32_use_ = pc_offset(); 3331 first_const_pool_32_use_ = pc_offset();
3332 } 3332 }
3333 pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo; 3333 pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo;
3334 } 3334 }
3335 // Make sure the constant pool is not emitted in place of the next 3335 // Make sure the constant pool is not emitted in place of the next
3336 // instruction for which we just recorded relocation info. 3336 // instruction for which we just recorded relocation info.
3337 BlockConstPoolFor(1); 3337 BlockConstPoolFor(1);
3338 return ConstantPoolArray::SMALL_SECTION; 3338 return ConstantPoolArray::SMALL_SECTION;
3339 } 3339 }
3340 } 3340 }
3341 3341
3342 3342
3343 void Assembler::BlockConstPoolFor(int instructions) { 3343 void Assembler::BlockConstPoolFor(int instructions) {
3344 if (FLAG_enable_ool_constant_pool) { 3344 if (FLAG_enable_ool_constant_pool) {
3345 // Should be a no-op if using an out-of-line constant pool. 3345 // Should be a no-op if using an out-of-line constant pool.
3346 ASSERT(num_pending_32_bit_reloc_info_ == 0); 3346 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3347 ASSERT(num_pending_64_bit_reloc_info_ == 0); 3347 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3348 return; 3348 return;
3349 } 3349 }
3350 3350
3351 int pc_limit = pc_offset() + instructions * kInstrSize; 3351 int pc_limit = pc_offset() + instructions * kInstrSize;
3352 if (no_const_pool_before_ < pc_limit) { 3352 if (no_const_pool_before_ < pc_limit) {
3353 // Max pool start (if we need a jump and an alignment). 3353 // Max pool start (if we need a jump and an alignment).
3354 #ifdef DEBUG 3354 #ifdef DEBUG
3355 int start = pc_limit + kInstrSize + 2 * kPointerSize; 3355 int start = pc_limit + kInstrSize + 2 * kPointerSize;
3356 ASSERT((num_pending_32_bit_reloc_info_ == 0) || 3356 DCHECK((num_pending_32_bit_reloc_info_ == 0) ||
3357 (start - first_const_pool_32_use_ + 3357 (start - first_const_pool_32_use_ +
3358 num_pending_64_bit_reloc_info_ * kDoubleSize < kMaxDistToIntPool)); 3358 num_pending_64_bit_reloc_info_ * kDoubleSize < kMaxDistToIntPool));
3359 ASSERT((num_pending_64_bit_reloc_info_ == 0) || 3359 DCHECK((num_pending_64_bit_reloc_info_ == 0) ||
3360 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); 3360 (start - first_const_pool_64_use_ < kMaxDistToFPPool));
3361 #endif 3361 #endif
3362 no_const_pool_before_ = pc_limit; 3362 no_const_pool_before_ = pc_limit;
3363 } 3363 }
3364 3364
3365 if (next_buffer_check_ < no_const_pool_before_) { 3365 if (next_buffer_check_ < no_const_pool_before_) {
3366 next_buffer_check_ = no_const_pool_before_; 3366 next_buffer_check_ = no_const_pool_before_;
3367 } 3367 }
3368 } 3368 }
3369 3369
3370 3370
3371 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 3371 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
3372 if (FLAG_enable_ool_constant_pool) { 3372 if (FLAG_enable_ool_constant_pool) {
3373 // Should be a no-op if using an out-of-line constant pool. 3373 // Should be a no-op if using an out-of-line constant pool.
3374 ASSERT(num_pending_32_bit_reloc_info_ == 0); 3374 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3375 ASSERT(num_pending_64_bit_reloc_info_ == 0); 3375 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3376 return; 3376 return;
3377 } 3377 }
3378 3378
3379 // Some short sequence of instruction mustn't be broken up by constant pool 3379 // Some short sequence of instruction mustn't be broken up by constant pool
3380 // emission, such sequences are protected by calls to BlockConstPoolFor and 3380 // emission, such sequences are protected by calls to BlockConstPoolFor and
3381 // BlockConstPoolScope. 3381 // BlockConstPoolScope.
3382 if (is_const_pool_blocked()) { 3382 if (is_const_pool_blocked()) {
3383 // Something is wrong if emission is forced and blocked at the same time. 3383 // Something is wrong if emission is forced and blocked at the same time.
3384 ASSERT(!force_emit); 3384 DCHECK(!force_emit);
3385 return; 3385 return;
3386 } 3386 }
3387 3387
3388 // There is nothing to do if there are no pending constant pool entries. 3388 // There is nothing to do if there are no pending constant pool entries.
3389 if ((num_pending_32_bit_reloc_info_ == 0) && 3389 if ((num_pending_32_bit_reloc_info_ == 0) &&
3390 (num_pending_64_bit_reloc_info_ == 0)) { 3390 (num_pending_64_bit_reloc_info_ == 0)) {
3391 // Calculate the offset of the next check. 3391 // Calculate the offset of the next check.
3392 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 3392 next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3393 return; 3393 return;
3394 } 3394 }
(...skipping 18 matching lines...) Expand all
3413 3413
3414 // We emit a constant pool when: 3414 // We emit a constant pool when:
3415 // * requested to do so by parameter force_emit (e.g. after each function). 3415 // * requested to do so by parameter force_emit (e.g. after each function).
3416 // * the distance from the first instruction accessing the constant pool to 3416 // * the distance from the first instruction accessing the constant pool to
3417 // any of the constant pool entries will exceed its limit the next 3417 // any of the constant pool entries will exceed its limit the next
3418 // time the pool is checked. This is overly restrictive, but we don't emit 3418 // time the pool is checked. This is overly restrictive, but we don't emit
3419 // constant pool entries in-order so it's conservatively correct. 3419 // constant pool entries in-order so it's conservatively correct.
3420 // * the instruction doesn't require a jump after itself to jump over the 3420 // * the instruction doesn't require a jump after itself to jump over the
3421 // constant pool, and we're getting close to running out of range. 3421 // constant pool, and we're getting close to running out of range.
3422 if (!force_emit) { 3422 if (!force_emit) {
3423 ASSERT((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0)); 3423 DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0));
3424 bool need_emit = false; 3424 bool need_emit = false;
3425 if (has_fp_values) { 3425 if (has_fp_values) {
3426 int dist64 = pc_offset() + 3426 int dist64 = pc_offset() +
3427 size - 3427 size -
3428 num_pending_32_bit_reloc_info_ * kPointerSize - 3428 num_pending_32_bit_reloc_info_ * kPointerSize -
3429 first_const_pool_64_use_; 3429 first_const_pool_64_use_;
3430 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || 3430 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
3431 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { 3431 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
3432 need_emit = true; 3432 need_emit = true;
3433 } 3433 }
(...skipping 29 matching lines...) Expand all
3463 3463
3464 if (require_64_bit_align) { 3464 if (require_64_bit_align) {
3465 emit(kConstantPoolMarker); 3465 emit(kConstantPoolMarker);
3466 } 3466 }
3467 3467
3468 // Emit 64-bit constant pool entries first: their range is smaller than 3468 // Emit 64-bit constant pool entries first: their range is smaller than
3469 // 32-bit entries. 3469 // 32-bit entries.
3470 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) { 3470 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
3471 RelocInfo& rinfo = pending_64_bit_reloc_info_[i]; 3471 RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
3472 3472
3473 ASSERT(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment. 3473 DCHECK(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment.
3474 3474
3475 Instr instr = instr_at(rinfo.pc()); 3475 Instr instr = instr_at(rinfo.pc());
3476 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. 3476 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
3477 ASSERT((IsVldrDPcImmediateOffset(instr) && 3477 DCHECK((IsVldrDPcImmediateOffset(instr) &&
3478 GetVldrDRegisterImmediateOffset(instr) == 0)); 3478 GetVldrDRegisterImmediateOffset(instr) == 0));
3479 3479
3480 int delta = pc_ - rinfo.pc() - kPcLoadDelta; 3480 int delta = pc_ - rinfo.pc() - kPcLoadDelta;
3481 ASSERT(is_uint10(delta)); 3481 DCHECK(is_uint10(delta));
3482 3482
3483 bool found = false; 3483 bool found = false;
3484 uint64_t value = rinfo.raw_data64(); 3484 uint64_t value = rinfo.raw_data64();
3485 for (int j = 0; j < i; j++) { 3485 for (int j = 0; j < i; j++) {
3486 RelocInfo& rinfo2 = pending_64_bit_reloc_info_[j]; 3486 RelocInfo& rinfo2 = pending_64_bit_reloc_info_[j];
3487 if (value == rinfo2.raw_data64()) { 3487 if (value == rinfo2.raw_data64()) {
3488 found = true; 3488 found = true;
3489 ASSERT(rinfo2.rmode() == RelocInfo::NONE64); 3489 DCHECK(rinfo2.rmode() == RelocInfo::NONE64);
3490 Instr instr2 = instr_at(rinfo2.pc()); 3490 Instr instr2 = instr_at(rinfo2.pc());
3491 ASSERT(IsVldrDPcImmediateOffset(instr2)); 3491 DCHECK(IsVldrDPcImmediateOffset(instr2));
3492 delta = GetVldrDRegisterImmediateOffset(instr2); 3492 delta = GetVldrDRegisterImmediateOffset(instr2);
3493 delta += rinfo2.pc() - rinfo.pc(); 3493 delta += rinfo2.pc() - rinfo.pc();
3494 break; 3494 break;
3495 } 3495 }
3496 } 3496 }
3497 3497
3498 instr_at_put(rinfo.pc(), SetVldrDRegisterImmediateOffset(instr, delta)); 3498 instr_at_put(rinfo.pc(), SetVldrDRegisterImmediateOffset(instr, delta));
3499 3499
3500 if (!found) { 3500 if (!found) {
3501 uint64_t uint_data = rinfo.raw_data64(); 3501 uint64_t uint_data = rinfo.raw_data64();
3502 emit(uint_data & 0xFFFFFFFF); 3502 emit(uint_data & 0xFFFFFFFF);
3503 emit(uint_data >> 32); 3503 emit(uint_data >> 32);
3504 } 3504 }
3505 } 3505 }
3506 3506
3507 // Emit 32-bit constant pool entries. 3507 // Emit 32-bit constant pool entries.
3508 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) { 3508 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
3509 RelocInfo& rinfo = pending_32_bit_reloc_info_[i]; 3509 RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
3510 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 3510 DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
3511 rinfo.rmode() != RelocInfo::POSITION && 3511 rinfo.rmode() != RelocInfo::POSITION &&
3512 rinfo.rmode() != RelocInfo::STATEMENT_POSITION && 3512 rinfo.rmode() != RelocInfo::STATEMENT_POSITION &&
3513 rinfo.rmode() != RelocInfo::CONST_POOL && 3513 rinfo.rmode() != RelocInfo::CONST_POOL &&
3514 rinfo.rmode() != RelocInfo::NONE64); 3514 rinfo.rmode() != RelocInfo::NONE64);
3515 3515
3516 Instr instr = instr_at(rinfo.pc()); 3516 Instr instr = instr_at(rinfo.pc());
3517 3517
3518 // 64-bit loads shouldn't get here. 3518 // 64-bit loads shouldn't get here.
3519 ASSERT(!IsVldrDPcImmediateOffset(instr)); 3519 DCHECK(!IsVldrDPcImmediateOffset(instr));
3520 3520
3521 if (IsLdrPcImmediateOffset(instr) && 3521 if (IsLdrPcImmediateOffset(instr) &&
3522 GetLdrRegisterImmediateOffset(instr) == 0) { 3522 GetLdrRegisterImmediateOffset(instr) == 0) {
3523 int delta = pc_ - rinfo.pc() - kPcLoadDelta; 3523 int delta = pc_ - rinfo.pc() - kPcLoadDelta;
3524 ASSERT(is_uint12(delta)); 3524 DCHECK(is_uint12(delta));
3525 // 0 is the smallest delta: 3525 // 0 is the smallest delta:
3526 // ldr rd, [pc, #0] 3526 // ldr rd, [pc, #0]
3527 // constant pool marker 3527 // constant pool marker
3528 // data 3528 // data
3529 3529
3530 bool found = false; 3530 bool found = false;
3531 if (!serializer_enabled() && rinfo.rmode() >= RelocInfo::CELL) { 3531 if (!serializer_enabled() && rinfo.rmode() >= RelocInfo::CELL) {
3532 for (int j = 0; j < i; j++) { 3532 for (int j = 0; j < i; j++) {
3533 RelocInfo& rinfo2 = pending_32_bit_reloc_info_[j]; 3533 RelocInfo& rinfo2 = pending_32_bit_reloc_info_[j];
3534 3534
3535 if ((rinfo2.data() == rinfo.data()) && 3535 if ((rinfo2.data() == rinfo.data()) &&
3536 (rinfo2.rmode() == rinfo.rmode())) { 3536 (rinfo2.rmode() == rinfo.rmode())) {
3537 Instr instr2 = instr_at(rinfo2.pc()); 3537 Instr instr2 = instr_at(rinfo2.pc());
3538 if (IsLdrPcImmediateOffset(instr2)) { 3538 if (IsLdrPcImmediateOffset(instr2)) {
3539 delta = GetLdrRegisterImmediateOffset(instr2); 3539 delta = GetLdrRegisterImmediateOffset(instr2);
3540 delta += rinfo2.pc() - rinfo.pc(); 3540 delta += rinfo2.pc() - rinfo.pc();
3541 found = true; 3541 found = true;
3542 break; 3542 break;
3543 } 3543 }
3544 } 3544 }
3545 } 3545 }
3546 } 3546 }
3547 3547
3548 instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta)); 3548 instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
3549 3549
3550 if (!found) { 3550 if (!found) {
3551 emit(rinfo.data()); 3551 emit(rinfo.data());
3552 } 3552 }
3553 } else { 3553 } else {
3554 ASSERT(IsMovW(instr)); 3554 DCHECK(IsMovW(instr));
3555 } 3555 }
3556 } 3556 }
3557 3557
3558 num_pending_32_bit_reloc_info_ = 0; 3558 num_pending_32_bit_reloc_info_ = 0;
3559 num_pending_64_bit_reloc_info_ = 0; 3559 num_pending_64_bit_reloc_info_ = 0;
3560 first_const_pool_32_use_ = -1; 3560 first_const_pool_32_use_ = -1;
3561 first_const_pool_64_use_ = -1; 3561 first_const_pool_64_use_ = -1;
3562 3562
3563 RecordComment("]"); 3563 RecordComment("]");
3564 3564
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3597 3597
3598 ConstantPoolArray::Type ConstantPoolBuilder::GetConstantPoolType( 3598 ConstantPoolArray::Type ConstantPoolBuilder::GetConstantPoolType(
3599 RelocInfo::Mode rmode) { 3599 RelocInfo::Mode rmode) {
3600 if (rmode == RelocInfo::NONE64) { 3600 if (rmode == RelocInfo::NONE64) {
3601 return ConstantPoolArray::INT64; 3601 return ConstantPoolArray::INT64;
3602 } else if (!RelocInfo::IsGCRelocMode(rmode)) { 3602 } else if (!RelocInfo::IsGCRelocMode(rmode)) {
3603 return ConstantPoolArray::INT32; 3603 return ConstantPoolArray::INT32;
3604 } else if (RelocInfo::IsCodeTarget(rmode)) { 3604 } else if (RelocInfo::IsCodeTarget(rmode)) {
3605 return ConstantPoolArray::CODE_PTR; 3605 return ConstantPoolArray::CODE_PTR;
3606 } else { 3606 } else {
3607 ASSERT(RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode)); 3607 DCHECK(RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode));
3608 return ConstantPoolArray::HEAP_PTR; 3608 return ConstantPoolArray::HEAP_PTR;
3609 } 3609 }
3610 } 3610 }
3611 3611
3612 3612
3613 ConstantPoolArray::LayoutSection ConstantPoolBuilder::AddEntry( 3613 ConstantPoolArray::LayoutSection ConstantPoolBuilder::AddEntry(
3614 Assembler* assm, const RelocInfo& rinfo) { 3614 Assembler* assm, const RelocInfo& rinfo) {
3615 RelocInfo::Mode rmode = rinfo.rmode(); 3615 RelocInfo::Mode rmode = rinfo.rmode();
3616 ASSERT(rmode != RelocInfo::COMMENT && 3616 DCHECK(rmode != RelocInfo::COMMENT &&
3617 rmode != RelocInfo::POSITION && 3617 rmode != RelocInfo::POSITION &&
3618 rmode != RelocInfo::STATEMENT_POSITION && 3618 rmode != RelocInfo::STATEMENT_POSITION &&
3619 rmode != RelocInfo::CONST_POOL); 3619 rmode != RelocInfo::CONST_POOL);
3620 3620
3621 // Try to merge entries which won't be patched. 3621 // Try to merge entries which won't be patched.
3622 int merged_index = -1; 3622 int merged_index = -1;
3623 ConstantPoolArray::LayoutSection entry_section = current_section_; 3623 ConstantPoolArray::LayoutSection entry_section = current_section_;
3624 if (RelocInfo::IsNone(rmode) || 3624 if (RelocInfo::IsNone(rmode) ||
3625 (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) { 3625 (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) {
3626 size_t i; 3626 size_t i;
3627 std::vector<ConstantPoolEntry>::const_iterator it; 3627 std::vector<ConstantPoolEntry>::const_iterator it;
3628 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) { 3628 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) {
3629 if (RelocInfo::IsEqual(rinfo, it->rinfo_)) { 3629 if (RelocInfo::IsEqual(rinfo, it->rinfo_)) {
3630 // Merge with found entry. 3630 // Merge with found entry.
3631 merged_index = i; 3631 merged_index = i;
3632 entry_section = entries_[i].section_; 3632 entry_section = entries_[i].section_;
3633 break; 3633 break;
3634 } 3634 }
3635 } 3635 }
3636 } 3636 }
3637 ASSERT(entry_section <= current_section_); 3637 DCHECK(entry_section <= current_section_);
3638 entries_.push_back(ConstantPoolEntry(rinfo, entry_section, merged_index)); 3638 entries_.push_back(ConstantPoolEntry(rinfo, entry_section, merged_index));
3639 3639
3640 if (merged_index == -1) { 3640 if (merged_index == -1) {
3641 // Not merged, so update the appropriate count. 3641 // Not merged, so update the appropriate count.
3642 number_of_entries_[entry_section].increment(GetConstantPoolType(rmode)); 3642 number_of_entries_[entry_section].increment(GetConstantPoolType(rmode));
3643 } 3643 }
3644 3644
3645 // Check if we still have room for another entry in the small section 3645 // Check if we still have room for another entry in the small section
3646 // given Arm's ldr and vldr immediate offset range. 3646 // given Arm's ldr and vldr immediate offset range.
3647 if (current_section_ == ConstantPoolArray::SMALL_SECTION && 3647 if (current_section_ == ConstantPoolArray::SMALL_SECTION &&
3648 !(is_uint12(ConstantPoolArray::SizeFor(*small_entries())) && 3648 !(is_uint12(ConstantPoolArray::SizeFor(*small_entries())) &&
3649 is_uint10(ConstantPoolArray::MaxInt64Offset( 3649 is_uint10(ConstantPoolArray::MaxInt64Offset(
3650 small_entries()->count_of(ConstantPoolArray::INT64))))) { 3650 small_entries()->count_of(ConstantPoolArray::INT64))))) {
3651 current_section_ = ConstantPoolArray::EXTENDED_SECTION; 3651 current_section_ = ConstantPoolArray::EXTENDED_SECTION;
3652 } 3652 }
3653 return entry_section; 3653 return entry_section;
3654 } 3654 }
3655 3655
3656 3656
3657 void ConstantPoolBuilder::Relocate(int pc_delta) { 3657 void ConstantPoolBuilder::Relocate(int pc_delta) {
3658 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin(); 3658 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
3659 entry != entries_.end(); entry++) { 3659 entry != entries_.end(); entry++) {
3660 ASSERT(entry->rinfo_.rmode() != RelocInfo::JS_RETURN); 3660 DCHECK(entry->rinfo_.rmode() != RelocInfo::JS_RETURN);
3661 entry->rinfo_.set_pc(entry->rinfo_.pc() + pc_delta); 3661 entry->rinfo_.set_pc(entry->rinfo_.pc() + pc_delta);
3662 } 3662 }
3663 } 3663 }
3664 3664
3665 3665
3666 Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) { 3666 Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) {
3667 if (IsEmpty()) { 3667 if (IsEmpty()) {
3668 return isolate->factory()->empty_constant_pool_array(); 3668 return isolate->factory()->empty_constant_pool_array();
3669 } else if (extended_entries()->is_empty()) { 3669 } else if (extended_entries()->is_empty()) {
3670 return isolate->factory()->NewConstantPoolArray(*small_entries()); 3670 return isolate->factory()->NewConstantPoolArray(*small_entries());
3671 } else { 3671 } else {
3672 ASSERT(current_section_ == ConstantPoolArray::EXTENDED_SECTION); 3672 DCHECK(current_section_ == ConstantPoolArray::EXTENDED_SECTION);
3673 return isolate->factory()->NewExtendedConstantPoolArray( 3673 return isolate->factory()->NewExtendedConstantPoolArray(
3674 *small_entries(), *extended_entries()); 3674 *small_entries(), *extended_entries());
3675 } 3675 }
3676 } 3676 }
3677 3677
3678 3678
3679 void ConstantPoolBuilder::Populate(Assembler* assm, 3679 void ConstantPoolBuilder::Populate(Assembler* assm,
3680 ConstantPoolArray* constant_pool) { 3680 ConstantPoolArray* constant_pool) {
3681 ASSERT_EQ(extended_entries()->is_empty(), 3681 DCHECK_EQ(extended_entries()->is_empty(),
3682 !constant_pool->is_extended_layout()); 3682 !constant_pool->is_extended_layout());
3683 ASSERT(small_entries()->equals(ConstantPoolArray::NumberOfEntries( 3683 DCHECK(small_entries()->equals(ConstantPoolArray::NumberOfEntries(
3684 constant_pool, ConstantPoolArray::SMALL_SECTION))); 3684 constant_pool, ConstantPoolArray::SMALL_SECTION)));
3685 if (constant_pool->is_extended_layout()) { 3685 if (constant_pool->is_extended_layout()) {
3686 ASSERT(extended_entries()->equals(ConstantPoolArray::NumberOfEntries( 3686 DCHECK(extended_entries()->equals(ConstantPoolArray::NumberOfEntries(
3687 constant_pool, ConstantPoolArray::EXTENDED_SECTION))); 3687 constant_pool, ConstantPoolArray::EXTENDED_SECTION)));
3688 } 3688 }
3689 3689
3690 // Set up initial offsets. 3690 // Set up initial offsets.
3691 int offsets[ConstantPoolArray::NUMBER_OF_LAYOUT_SECTIONS] 3691 int offsets[ConstantPoolArray::NUMBER_OF_LAYOUT_SECTIONS]
3692 [ConstantPoolArray::NUMBER_OF_TYPES]; 3692 [ConstantPoolArray::NUMBER_OF_TYPES];
3693 for (int section = 0; section <= constant_pool->final_section(); section++) { 3693 for (int section = 0; section <= constant_pool->final_section(); section++) {
3694 int section_start = (section == ConstantPoolArray::EXTENDED_SECTION) 3694 int section_start = (section == ConstantPoolArray::EXTENDED_SECTION)
3695 ? small_entries()->total_count() 3695 ? small_entries()->total_count()
3696 : 0; 3696 : 0;
(...skipping 19 matching lines...) Expand all
3716 offsets[entry->section_][type] += ConstantPoolArray::entry_size(type); 3716 offsets[entry->section_][type] += ConstantPoolArray::entry_size(type);
3717 if (type == ConstantPoolArray::INT64) { 3717 if (type == ConstantPoolArray::INT64) {
3718 constant_pool->set_at_offset(offset, rinfo.data64()); 3718 constant_pool->set_at_offset(offset, rinfo.data64());
3719 } else if (type == ConstantPoolArray::INT32) { 3719 } else if (type == ConstantPoolArray::INT32) {
3720 constant_pool->set_at_offset(offset, 3720 constant_pool->set_at_offset(offset,
3721 static_cast<int32_t>(rinfo.data())); 3721 static_cast<int32_t>(rinfo.data()));
3722 } else if (type == ConstantPoolArray::CODE_PTR) { 3722 } else if (type == ConstantPoolArray::CODE_PTR) {
3723 constant_pool->set_at_offset(offset, 3723 constant_pool->set_at_offset(offset,
3724 reinterpret_cast<Address>(rinfo.data())); 3724 reinterpret_cast<Address>(rinfo.data()));
3725 } else { 3725 } else {
3726 ASSERT(type == ConstantPoolArray::HEAP_PTR); 3726 DCHECK(type == ConstantPoolArray::HEAP_PTR);
3727 constant_pool->set_at_offset(offset, 3727 constant_pool->set_at_offset(offset,
3728 reinterpret_cast<Object*>(rinfo.data())); 3728 reinterpret_cast<Object*>(rinfo.data()));
3729 } 3729 }
3730 offset -= kHeapObjectTag; 3730 offset -= kHeapObjectTag;
3731 entry->merged_index_ = offset; // Stash offset for merged entries. 3731 entry->merged_index_ = offset; // Stash offset for merged entries.
3732 } else { 3732 } else {
3733 ASSERT(entry->merged_index_ < (entry - entries_.begin())); 3733 DCHECK(entry->merged_index_ < (entry - entries_.begin()));
3734 offset = entries_[entry->merged_index_].merged_index_; 3734 offset = entries_[entry->merged_index_].merged_index_;
3735 } 3735 }
3736 3736
3737 // Patch vldr/ldr instruction with correct offset. 3737 // Patch vldr/ldr instruction with correct offset.
3738 Instr instr = assm->instr_at(rinfo.pc()); 3738 Instr instr = assm->instr_at(rinfo.pc());
3739 if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) { 3739 if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) {
3740 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0]. 3740 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
3741 Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize); 3741 Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
3742 ASSERT((Assembler::IsMovW(instr) && 3742 DCHECK((Assembler::IsMovW(instr) &&
3743 Instruction::ImmedMovwMovtValue(instr) == 0)); 3743 Instruction::ImmedMovwMovtValue(instr) == 0));
3744 ASSERT((Assembler::IsMovT(next_instr) && 3744 DCHECK((Assembler::IsMovT(next_instr) &&
3745 Instruction::ImmedMovwMovtValue(next_instr) == 0)); 3745 Instruction::ImmedMovwMovtValue(next_instr) == 0));
3746 assm->instr_at_put(rinfo.pc(), 3746 assm->instr_at_put(rinfo.pc(),
3747 Assembler::PatchMovwImmediate(instr, offset & 0xffff)); 3747 Assembler::PatchMovwImmediate(instr, offset & 0xffff));
3748 assm->instr_at_put( 3748 assm->instr_at_put(
3749 rinfo.pc() + Assembler::kInstrSize, 3749 rinfo.pc() + Assembler::kInstrSize,
3750 Assembler::PatchMovwImmediate(next_instr, offset >> 16)); 3750 Assembler::PatchMovwImmediate(next_instr, offset >> 16));
3751 } else if (type == ConstantPoolArray::INT64) { 3751 } else if (type == ConstantPoolArray::INT64) {
3752 // Instruction to patch must be 'vldr rd, [pp, #0]'. 3752 // Instruction to patch must be 'vldr rd, [pp, #0]'.
3753 ASSERT((Assembler::IsVldrDPpImmediateOffset(instr) && 3753 DCHECK((Assembler::IsVldrDPpImmediateOffset(instr) &&
3754 Assembler::GetVldrDRegisterImmediateOffset(instr) == 0)); 3754 Assembler::GetVldrDRegisterImmediateOffset(instr) == 0));
3755 ASSERT(is_uint10(offset)); 3755 DCHECK(is_uint10(offset));
3756 assm->instr_at_put(rinfo.pc(), Assembler::SetVldrDRegisterImmediateOffset( 3756 assm->instr_at_put(rinfo.pc(), Assembler::SetVldrDRegisterImmediateOffset(
3757 instr, offset)); 3757 instr, offset));
3758 } else { 3758 } else {
3759 // Instruction to patch must be 'ldr rd, [pp, #0]'. 3759 // Instruction to patch must be 'ldr rd, [pp, #0]'.
3760 ASSERT((Assembler::IsLdrPpImmediateOffset(instr) && 3760 DCHECK((Assembler::IsLdrPpImmediateOffset(instr) &&
3761 Assembler::GetLdrRegisterImmediateOffset(instr) == 0)); 3761 Assembler::GetLdrRegisterImmediateOffset(instr) == 0));
3762 ASSERT(is_uint12(offset)); 3762 DCHECK(is_uint12(offset));
3763 assm->instr_at_put( 3763 assm->instr_at_put(
3764 rinfo.pc(), Assembler::SetLdrRegisterImmediateOffset(instr, offset)); 3764 rinfo.pc(), Assembler::SetLdrRegisterImmediateOffset(instr, offset));
3765 } 3765 }
3766 } 3766 }
3767 } 3767 }
3768 3768
3769 3769
3770 } } // namespace v8::internal 3770 } } // namespace v8::internal
3771 3771
3772 #endif // V8_TARGET_ARCH_ARM 3772 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698