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

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

Issue 7239020: MIPS: Long branch implementation and trampoline improvement. (Closed)
Patch Set: Created 9 years, 6 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
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 are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 s8_fp, 133 s8_fp,
134 ra 134 ra
135 }; 135 };
136 return kRegisters[num]; 136 return kRegisters[num];
137 } 137 }
138 138
139 139
140 // ----------------------------------------------------------------------------- 140 // -----------------------------------------------------------------------------
141 // Implementation of RelocInfo. 141 // Implementation of RelocInfo.
142 142
143 const int RelocInfo::kApplyMask = 0; 143 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
144 144
145 145
146 bool RelocInfo::IsCodedSpecially() { 146 bool RelocInfo::IsCodedSpecially() {
147 // The deserializer needs to know whether a pointer is specially coded. Being 147 // The deserializer needs to know whether a pointer is specially coded. Being
148 // specially coded on MIPS means that it is a lui/ori instruction, and that is 148 // specially coded on MIPS means that it is a lui/ori instruction, and that is
149 // always the case inside code objects. 149 // always the case inside code objects.
150 return true; 150 return true;
151 } 151 }
152 152
153 153
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 268 }
269 269
270 // Setup buffer pointers. 270 // Setup buffer pointers.
271 ASSERT(buffer_ != NULL); 271 ASSERT(buffer_ != NULL);
272 pc_ = buffer_; 272 pc_ = buffer_;
273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
274 274
275 last_trampoline_pool_end_ = 0; 275 last_trampoline_pool_end_ = 0;
276 no_trampoline_pool_before_ = 0; 276 no_trampoline_pool_before_ = 0;
277 trampoline_pool_blocked_nesting_ = 0; 277 trampoline_pool_blocked_nesting_ = 0;
278 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize; 278 // We leave space (16 * kTrampolineSlotsSize)
279 // for BlockTrampolinePoolScope buffer.
280 next_buffer_check_ = kMaxBranchOffset - kTrampolineSlotsSize * 16;
279 internal_trampoline_exception_ = false; 281 internal_trampoline_exception_ = false;
280 last_bound_pos_ = 0; 282 last_bound_pos_ = 0;
281 283
284 trampoline_emitted_ = false;
285 unbound_labels_count = 0;
286
282 ast_id_for_reloc_info_ = kNoASTId; 287 ast_id_for_reloc_info_ = kNoASTId;
283 } 288 }
284 289
285 290
286 Assembler::~Assembler() { 291 Assembler::~Assembler() {
287 if (own_buffer_) { 292 if (own_buffer_) {
288 if (isolate()->assembler_spare_buffer() == NULL && 293 if (isolate()->assembler_spare_buffer() == NULL &&
289 buffer_size_ == kMinimalBufferSize) { 294 buffer_size_ == kMinimalBufferSize) {
290 isolate()->set_assembler_spare_buffer(buffer_); 295 isolate()->set_assembler_spare_buffer(buffer_);
291 } else { 296 } else {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 uint32_t Assembler::GetSaField(Instr instr) { 384 uint32_t Assembler::GetSaField(Instr instr) {
380 return instr & kSaFieldMask; 385 return instr & kSaFieldMask;
381 } 386 }
382 387
383 388
384 uint32_t Assembler::GetOpcodeField(Instr instr) { 389 uint32_t Assembler::GetOpcodeField(Instr instr) {
385 return instr & kOpcodeMask; 390 return instr & kOpcodeMask;
386 } 391 }
387 392
388 393
394 uint32_t Assembler::GetFunction(Instr instr) {
395 return (instr & kFunctionFieldMask) >> kFunctionShift;
396 }
397
398
399 uint32_t Assembler::GetFunctionField(Instr instr) {
400 return instr & kFunctionFieldMask;
401 }
402
403
389 uint32_t Assembler::GetImmediate16(Instr instr) { 404 uint32_t Assembler::GetImmediate16(Instr instr) {
390 return instr & kImm16Mask; 405 return instr & kImm16Mask;
391 } 406 }
392 407
393 408
394 uint32_t Assembler::GetLabelConst(Instr instr) { 409 uint32_t Assembler::GetLabelConst(Instr instr) {
395 return instr & ~kImm16Mask; 410 return instr & ~kImm16Mask;
396 } 411 }
397 412
398 413
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // Linked labels refer to unknown positions in the code 452 // Linked labels refer to unknown positions in the code
438 // to be generated; pos() is the position of the last 453 // to be generated; pos() is the position of the last
439 // instruction using the label. 454 // instruction using the label.
440 455
441 // The link chain is terminated by a value in the instruction of -1, 456 // The link chain is terminated by a value in the instruction of -1,
442 // which is an otherwise illegal value (branch -1 is inf loop). 457 // which is an otherwise illegal value (branch -1 is inf loop).
443 // The instruction 16-bit offset field addresses 32-bit words, but in 458 // The instruction 16-bit offset field addresses 32-bit words, but in
444 // code is conv to an 18-bit value addressing bytes, hence the -4 value. 459 // code is conv to an 18-bit value addressing bytes, hence the -4 value.
445 460
446 const int kEndOfChain = -4; 461 const int kEndOfChain = -4;
462 // Determines the end of the Jump chain (a subset of the label link chain).
463 const int kEndOfJumpChain = 0;
447 464
448 465
449 bool Assembler::IsBranch(Instr instr) { 466 bool Assembler::IsBranch(Instr instr) {
450 uint32_t opcode = GetOpcodeField(instr); 467 uint32_t opcode = GetOpcodeField(instr);
451 uint32_t rt_field = GetRtField(instr); 468 uint32_t rt_field = GetRtField(instr);
452 uint32_t rs_field = GetRsField(instr); 469 uint32_t rs_field = GetRsField(instr);
453 uint32_t label_constant = GetLabelConst(instr); 470 uint32_t label_constant = GetLabelConst(instr);
454 // Checks if the instruction is a branch. 471 // Checks if the instruction is a branch.
455 return opcode == BEQ || 472 return opcode == BEQ ||
456 opcode == BNE || 473 opcode == BNE ||
(...skipping 13 matching lines...) Expand all
470 bool Assembler::IsBeq(Instr instr) { 487 bool Assembler::IsBeq(Instr instr) {
471 return GetOpcodeField(instr) == BEQ; 488 return GetOpcodeField(instr) == BEQ;
472 } 489 }
473 490
474 491
475 bool Assembler::IsBne(Instr instr) { 492 bool Assembler::IsBne(Instr instr) {
476 return GetOpcodeField(instr) == BNE; 493 return GetOpcodeField(instr) == BNE;
477 } 494 }
478 495
479 496
497 bool Assembler::IsJump(Instr instr) {
498 uint32_t opcode = GetOpcodeField(instr);
499 uint32_t rt_field = GetRtField(instr);
500 uint32_t rd_field = GetRdField(instr);
501 uint32_t function_field = GetFunctionField(instr);
502 // Checks if the instruction is a jump.
503 return opcode == J || opcode == JAL ||
504 (opcode == SPECIAL && rt_field == 0 &&
505 ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
506 }
507
508
509 bool Assembler::IsJ(Instr instr) {
510 uint32_t opcode = GetOpcodeField(instr);
511 // Checks if the instruction is a jump.
512 return opcode == J;
513 }
514
515
516 bool Assembler::IsLui(Instr instr) {
517 uint32_t opcode = GetOpcodeField(instr);
518 // Checks if the instruction is a load upper immediate.
519 return opcode == LUI;
520 }
521
522
523 bool Assembler::IsOri(Instr instr) {
524 uint32_t opcode = GetOpcodeField(instr);
525 // Checks if the instruction is a load upper immediate.
526 return opcode == ORI;
527 }
528
529
480 bool Assembler::IsNop(Instr instr, unsigned int type) { 530 bool Assembler::IsNop(Instr instr, unsigned int type) {
481 // See Assembler::nop(type). 531 // See Assembler::nop(type).
482 ASSERT(type < 32); 532 ASSERT(type < 32);
483 uint32_t opcode = GetOpcodeField(instr); 533 uint32_t opcode = GetOpcodeField(instr);
484 uint32_t rt = GetRt(instr); 534 uint32_t rt = GetRt(instr);
485 uint32_t rs = GetRs(instr); 535 uint32_t rs = GetRs(instr);
486 uint32_t sa = GetSa(instr); 536 uint32_t sa = GetSa(instr);
487 537
488 // nop(type) == sll(zero_reg, zero_reg, type); 538 // nop(type) == sll(zero_reg, zero_reg, type);
489 // Technically all these values will be 0 but 539 // Technically all these values will be 0 but
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 Instr instr = instr_at(pos); 607 Instr instr = instr_at(pos);
558 if ((instr & ~kImm16Mask) == 0) { 608 if ((instr & ~kImm16Mask) == 0) {
559 // Emitted label constant, not part of a branch. 609 // Emitted label constant, not part of a branch.
560 if (instr == 0) { 610 if (instr == 0) {
561 return kEndOfChain; 611 return kEndOfChain;
562 } else { 612 } else {
563 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 613 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
564 return (imm18 + pos); 614 return (imm18 + pos);
565 } 615 }
566 } 616 }
567 // Check we have a branch instruction. 617 // Check we have a branch or jump instruction.
568 ASSERT(IsBranch(instr)); 618 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
569 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 619 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
570 // the compiler uses arithmectic shifts for signed integers. 620 // the compiler uses arithmectic shifts for signed integers.
571 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 621 if (IsBranch(instr)) {
622 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
572 623
573 if (imm18 == kEndOfChain) { 624 if (imm18 == kEndOfChain) {
574 // EndOfChain sentinel is returned directly, not relative to pc or pos. 625 // EndOfChain sentinel is returned directly, not relative to pc or pos.
575 return kEndOfChain; 626 return kEndOfChain;
627 } else {
628 return pos + kBranchPCOffset + imm18;
629 }
630 } else if (IsLui(instr)) {
631 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
632 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
633 ASSERT(IsLui(instr_lui) && IsOri(instr_ori));
Søren Thygesen Gjesse 2011/06/24 13:05:15 IsLui(instr_lui) is not needed in the ASSERT (alre
Paul Lind 2011/06/28 06:53:14 Done.
634 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
635 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
636
637 if (imm == kEndOfJumpChain) {
638 // EndOfChain sentinel is returned directly, not relative to pc or pos.
639 return kEndOfChain;
640 } else {
641 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
642 int32_t delta = instr_address - imm;
643 ASSERT(pos > delta);
644 return pos - delta;
645 }
576 } else { 646 } else {
577 return pos + kBranchPCOffset + imm18; 647 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
648 if (imm28 == kEndOfJumpChain) {
649 // EndOfChain sentinel is returned directly, not relative to pc or pos.
650 return kEndOfChain;
651 } else {
652 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
653 instr_address &= kImm28Mask;
654 int32_t delta = instr_address - imm28;
655 ASSERT(pos > delta);
656 return pos - delta;
657 }
578 } 658 }
579 } 659 }
580 660
581 661
582 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { 662 void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
583 Instr instr = instr_at(pos); 663 Instr instr = instr_at(pos);
584 if ((instr & ~kImm16Mask) == 0) { 664 if ((instr & ~kImm16Mask) == 0) {
585 ASSERT(target_pos == kEndOfChain || target_pos >= 0); 665 ASSERT(target_pos == kEndOfChain || target_pos >= 0);
586 // Emitted label constant, not part of a branch. 666 // Emitted label constant, not part of a branch.
587 // Make label relative to Code* of generated Code object. 667 // Make label relative to Code* of generated Code object.
588 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 668 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
589 return; 669 return;
590 } 670 }
591 671
592 ASSERT(IsBranch(instr)); 672 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr));
593 int32_t imm18 = target_pos - (pos + kBranchPCOffset); 673 if (IsBranch(instr)) {
594 ASSERT((imm18 & 3) == 0); 674 int32_t imm18 = target_pos - (pos + kBranchPCOffset);
675 ASSERT((imm18 & 3) == 0);
595 676
596 instr &= ~kImm16Mask; 677 instr &= ~kImm16Mask;
597 int32_t imm16 = imm18 >> 2; 678 int32_t imm16 = imm18 >> 2;
598 ASSERT(is_int16(imm16)); 679 ASSERT(is_int16(imm16));
599 680
600 instr_at_put(pos, instr | (imm16 & kImm16Mask)); 681 instr_at_put(pos, instr | (imm16 & kImm16Mask));
682 } else if (IsLui(instr)) {
683 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
684 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
685 ASSERT(IsLui(instr_lui) && IsOri(instr_ori));
Søren Thygesen Gjesse 2011/06/24 13:05:15 Ditto.
Paul Lind 2011/06/28 06:53:14 Done.
686 uint32_t imm = (uint32_t)buffer_ + target_pos;
687 ASSERT((imm & 3) == 0);
688
689 instr_lui &= ~kImm16Mask;
690 instr_ori &= ~kImm16Mask;
691
692 instr_at_put(pos + 0 * Assembler::kInstrSize,
693 instr_lui | ((imm & kHiMask) >> kLuiShift));
694 instr_at_put(pos + 1 * Assembler::kInstrSize,
695 instr_ori | (imm & kImm16Mask));
696 } else {
697 uint32_t imm28 = (uint32_t)buffer_ + target_pos;
698 imm28 &= kImm28Mask;
699 ASSERT((imm28 & 3) == 0);
700
701 instr &= ~kImm26Mask;
702 uint32_t imm26 = imm28 >> 2;
703 ASSERT(is_uint26(imm26));
704
705 instr_at_put(pos, instr | (imm26 & kImm26Mask));
706 }
601 } 707 }
602 708
603 709
604 void Assembler::print(Label* L) { 710 void Assembler::print(Label* L) {
605 if (L->is_unused()) { 711 if (L->is_unused()) {
606 PrintF("unused label\n"); 712 PrintF("unused label\n");
607 } else if (L->is_bound()) { 713 } else if (L->is_bound()) {
608 PrintF("bound label to %d\n", L->pos()); 714 PrintF("bound label to %d\n", L->pos());
609 } else if (L->is_linked()) { 715 } else if (L->is_linked()) {
610 Label l = *L; 716 Label l = *L;
611 PrintF("unbound label"); 717 PrintF("unbound label");
612 while (l.is_linked()) { 718 while (l.is_linked()) {
613 PrintF("@ %d ", l.pos()); 719 PrintF("@ %d ", l.pos());
614 Instr instr = instr_at(l.pos()); 720 Instr instr = instr_at(l.pos());
615 if ((instr & ~kImm16Mask) == 0) { 721 if ((instr & ~kImm16Mask) == 0) {
616 PrintF("value\n"); 722 PrintF("value\n");
617 } else { 723 } else {
618 PrintF("%d\n", instr); 724 PrintF("%d\n", instr);
619 } 725 }
620 next(&l); 726 next(&l);
621 } 727 }
622 } else { 728 } else {
623 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 729 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
624 } 730 }
625 } 731 }
626 732
627 733
628 void Assembler::bind_to(Label* L, int pos) { 734 void Assembler::bind_to(Label* L, int pos) {
629 ASSERT(0 <= pos && pos <= pc_offset()); // Must have valid binding position. 735 ASSERT(0 <= pos && pos <= pc_offset()); // Must have valid binding position.
736 int32_t trampoline_pos = kInvalidSlotPos;
737 if (L->is_linked() && !trampoline_emitted_) {
738 unbound_labels_count--;
739 next_buffer_check_ += kTrampolineSlotsSize;
740 }
741
630 while (L->is_linked()) { 742 while (L->is_linked()) {
631 int32_t fixup_pos = L->pos(); 743 int32_t fixup_pos = L->pos();
632 int32_t dist = pos - fixup_pos; 744 int32_t dist = pos - fixup_pos;
633 next(L); // Call next before overwriting link with target at fixup_pos. 745 next(L); // Call next before overwriting link with target at fixup_pos.
634 if (dist > kMaxBranchOffset) { 746 Instr instr = instr_at(fixup_pos);
635 do { 747 if (IsBranch(instr)) {
636 int32_t trampoline_pos = get_trampoline_entry(fixup_pos); 748 if (dist > kMaxBranchOffset) {
637 if (kInvalidSlotPos == trampoline_pos) { 749 if (trampoline_pos == kInvalidSlotPos) {
638 // Internal error. 750 trampoline_pos = get_trampoline_entry(fixup_pos);
639 return; 751 CHECK(trampoline_pos != kInvalidSlotPos);
640 } 752 }
641 ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset); 753 ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
642 target_at_put(fixup_pos, trampoline_pos); 754 target_at_put(fixup_pos, trampoline_pos);
643 fixup_pos = trampoline_pos; 755 fixup_pos = trampoline_pos;
644 dist = pos - fixup_pos; 756 dist = pos - fixup_pos;
645 } while (dist > kMaxBranchOffset); 757 }
646 } else if (dist < -kMaxBranchOffset) { 758 target_at_put(fixup_pos, pos);
647 do { 759 } else {
648 int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false); 760 ASSERT(IsJ(instr) || IsLui(instr));
649 if (kInvalidSlotPos == trampoline_pos) { 761 target_at_put(fixup_pos, pos);
650 // Internal error. 762 }
651 return;
652 }
653 ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset);
654 target_at_put(fixup_pos, trampoline_pos);
655 fixup_pos = trampoline_pos;
656 dist = pos - fixup_pos;
657 } while (dist < -kMaxBranchOffset);
658 };
659 target_at_put(fixup_pos, pos);
660 } 763 }
661 L->bind_to(pos); 764 L->bind_to(pos);
662 765
663 // Keep track of the last bound label so we don't eliminate any instructions 766 // Keep track of the last bound label so we don't eliminate any instructions
664 // before a bound label. 767 // before a bound label.
665 if (pos > last_bound_pos_) 768 if (pos > last_bound_pos_)
666 last_bound_pos_ = pos; 769 last_bound_pos_ = pos;
667 } 770 }
668 771
669 772
670 void Assembler::link_to(Label* L, Label* appendix) {
671 if (appendix->is_linked()) {
672 if (L->is_linked()) {
673 // Append appendix to L's list.
674 int fixup_pos;
675 int link = L->pos();
676 do {
677 fixup_pos = link;
678 link = target_at(fixup_pos);
679 } while (link > 0);
680 ASSERT(link == kEndOfChain);
681 target_at_put(fixup_pos, appendix->pos());
682 } else {
683 // L is empty, simply use appendix.
684 *L = *appendix;
685 }
686 }
687 appendix->Unuse(); // Appendix should not be used anymore.
688 }
689
690
691 void Assembler::bind(Label* L) { 773 void Assembler::bind(Label* L) {
692 ASSERT(!L->is_bound()); // Label can only be bound once. 774 ASSERT(!L->is_bound()); // Label can only be bound once.
693 bind_to(L, pc_offset()); 775 bind_to(L, pc_offset());
694 } 776 }
695 777
696 778
697 void Assembler::next(Label* L) { 779 void Assembler::next(Label* L) {
698 ASSERT(L->is_linked()); 780 ASSERT(L->is_linked());
699 int link = target_at(L->pos()); 781 int link = target_at(L->pos());
700 ASSERT(link > 0 || link == kEndOfChain); 782 ASSERT(link > 0 || link == kEndOfChain);
701 if (link == kEndOfChain) { 783 if (link == kEndOfChain) {
702 L->Unuse(); 784 L->Unuse();
703 } else if (link > 0) { 785 } else if (link > 0) {
704 L->link_to(link); 786 L->link_to(link);
705 } 787 }
706 } 788 }
707 789
790 bool Assembler::is_near(Label* L) {
791 if (L->is_bound()) {
792 return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
793 }
794 return false;
795 }
708 796
709 // We have to use a temporary register for things that can be relocated even 797 // We have to use a temporary register for things that can be relocated even
710 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 798 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
711 // space. There is no guarantee that the relocated location can be similarly 799 // space. There is no guarantee that the relocated location can be similarly
712 // encoded. 800 // encoded.
713 bool Assembler::MustUseReg(RelocInfo::Mode rmode) { 801 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
714 return rmode != RelocInfo::NONE; 802 return rmode != RelocInfo::NONE;
715 } 803 }
716 804
717 805
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 868 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
781 emit(instr); 869 emit(instr);
782 } 870 }
783 871
784 872
785 // Instructions with immediate value. 873 // Instructions with immediate value.
786 // Registers are in the order of the instruction encoding, from left to right. 874 // Registers are in the order of the instruction encoding, from left to right.
787 void Assembler::GenInstrImmediate(Opcode opcode, 875 void Assembler::GenInstrImmediate(Opcode opcode,
788 Register rs, 876 Register rs,
789 Register rt, 877 Register rt,
790 int32_t j) { 878 int32_t j,
879 bool check_buffer) {
791 ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 880 ASSERT(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
792 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 881 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
793 | (j & kImm16Mask); 882 | (j & kImm16Mask);
794 emit(instr); 883 emit(instr, check_buffer);
795 } 884 }
796 885
797 886
798 void Assembler::GenInstrImmediate(Opcode opcode, 887 void Assembler::GenInstrImmediate(Opcode opcode,
799 Register rs, 888 Register rs,
800 SecondaryField SF, 889 SecondaryField SF,
801 int32_t j) { 890 int32_t j) {
802 ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j))); 891 ASSERT(rs.is_valid() && (is_int16(j) || is_uint16(j)));
803 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); 892 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
804 emit(instr); 893 emit(instr);
(...skipping 11 matching lines...) Expand all
816 emit(instr); 905 emit(instr);
817 } 906 }
818 907
819 908
820 // Registers are in the order of the instruction encoding, from left to right. 909 // Registers are in the order of the instruction encoding, from left to right.
821 void Assembler::GenInstrJump(Opcode opcode, 910 void Assembler::GenInstrJump(Opcode opcode,
822 uint32_t address) { 911 uint32_t address) {
823 BlockTrampolinePoolScope block_trampoline_pool(this); 912 BlockTrampolinePoolScope block_trampoline_pool(this);
824 ASSERT(is_uint26(address)); 913 ASSERT(is_uint26(address));
825 Instr instr = opcode | address; 914 Instr instr = opcode | address;
826 emit(instr); 915 // Prevent buffer growth as internal reference in relocation info is linked
916 // to the instruction that has not been emitted yet.
917 emit(instr, false);
827 BlockTrampolinePoolFor(1); // For associated delay slot. 918 BlockTrampolinePoolFor(1); // For associated delay slot.
828 } 919 }
829 920
830 921
831 // Returns the next free label entry from the next trampoline pool. 922 // Returns the next free trampoline entry.
832 int32_t Assembler::get_label_entry(int32_t pos, bool next_pool) { 923 int32_t Assembler::get_trampoline_entry(int32_t pos) {
833 int trampoline_count = trampolines_.length();
834 int32_t label_entry = 0;
835 ASSERT(trampoline_count > 0);
836
837 if (next_pool) {
838 for (int i = 0; i < trampoline_count; i++) {
839 if (trampolines_[i].start() > pos) {
840 label_entry = trampolines_[i].take_label();
841 break;
842 }
843 }
844 } else { // Caller needs a label entry from the previous pool.
845 for (int i = trampoline_count-1; i >= 0; i--) {
846 if (trampolines_[i].end() < pos) {
847 label_entry = trampolines_[i].take_label();
848 break;
849 }
850 }
851 }
852 return label_entry;
853 }
854
855
856 // Returns the next free trampoline entry from the next trampoline pool.
857 int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) {
858 int trampoline_count = trampolines_.length();
859 int32_t trampoline_entry = kInvalidSlotPos; 924 int32_t trampoline_entry = kInvalidSlotPos;
860 ASSERT(trampoline_count > 0);
861 925
862 if (!internal_trampoline_exception_) { 926 if (!internal_trampoline_exception_) {
863 if (next_pool) { 927 if (trampoline_.start() > pos) {
864 for (int i = 0; i < trampoline_count; i++) { 928 trampoline_entry = trampoline_.take_slot();
865 if (trampolines_[i].start() > pos) {
866 trampoline_entry = trampolines_[i].take_slot();
867 break;
868 }
869 }
870 } else { // Caller needs a trampoline entry from the previous pool.
871 for (int i = trampoline_count-1; i >= 0; i--) {
872 if (trampolines_[i].end() < pos) {
873 trampoline_entry = trampolines_[i].take_slot();
874 break;
875 }
876 }
877 } 929 }
930
878 if (kInvalidSlotPos == trampoline_entry) { 931 if (kInvalidSlotPos == trampoline_entry) {
879 internal_trampoline_exception_ = true; 932 internal_trampoline_exception_ = true;
880 } 933 }
881 } 934 }
882 return trampoline_entry; 935 return trampoline_entry;
883 } 936 }
884 937
885 938
886 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 939 uint32_t Assembler::jump_address(Label* L) {
887 int32_t target_pos; 940 int32_t target_pos;
888 int32_t pc_offset_v = pc_offset();
889 941
890 if (L->is_bound()) { 942 if (L->is_bound()) {
891 target_pos = L->pos(); 943 target_pos = L->pos();
892 int32_t dist = pc_offset_v - target_pos;
893 if (dist > kMaxBranchOffset) {
894 do {
895 int32_t trampoline_pos = get_trampoline_entry(target_pos);
896 if (kInvalidSlotPos == trampoline_pos) {
897 // Internal error.
898 return 0;
899 }
900 ASSERT((trampoline_pos - target_pos) > 0);
901 ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset);
902 target_at_put(trampoline_pos, target_pos);
903 target_pos = trampoline_pos;
904 dist = pc_offset_v - target_pos;
905 } while (dist > kMaxBranchOffset);
906 } else if (dist < -kMaxBranchOffset) {
907 do {
908 int32_t trampoline_pos = get_trampoline_entry(target_pos, false);
909 if (kInvalidSlotPos == trampoline_pos) {
910 // Internal error.
911 return 0;
912 }
913 ASSERT((target_pos - trampoline_pos) > 0);
914 ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset);
915 target_at_put(trampoline_pos, target_pos);
916 target_pos = trampoline_pos;
917 dist = pc_offset_v - target_pos;
918 } while (dist < -kMaxBranchOffset);
919 }
920 } else { 944 } else {
921 if (L->is_linked()) { 945 if (L->is_linked()) {
922 target_pos = L->pos(); // L's link. 946 target_pos = L->pos(); // L's link.
923 int32_t dist = pc_offset_v - target_pos;
924 if (dist > kMaxBranchOffset) {
925 do {
926 int32_t label_pos = get_label_entry(target_pos);
927 ASSERT((label_pos - target_pos) < kMaxBranchOffset);
928 label_at_put(L, label_pos);
929 target_pos = label_pos;
930 dist = pc_offset_v - target_pos;
931 } while (dist > kMaxBranchOffset);
932 } else if (dist < -kMaxBranchOffset) {
933 do {
934 int32_t label_pos = get_label_entry(target_pos, false);
935 ASSERT((label_pos - target_pos) > -kMaxBranchOffset);
936 label_at_put(L, label_pos);
937 target_pos = label_pos;
938 dist = pc_offset_v - target_pos;
939 } while (dist < -kMaxBranchOffset);
940 }
941 L->link_to(pc_offset()); 947 L->link_to(pc_offset());
942 } else { 948 } else {
943 L->link_to(pc_offset()); 949 L->link_to(pc_offset());
950 return kEndOfJumpChain;
951 }
952 }
953
954 uint32_t imm = (uint32_t)buffer_ + target_pos;
955 ASSERT((imm & 3) == 0);
956
957 return imm;
958 }
959
960
961 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
962 int32_t target_pos;
963
964 if (L->is_bound()) {
965 target_pos = L->pos();
966 } else {
967 if (L->is_linked()) {
968 target_pos = L->pos();
969 L->link_to(pc_offset());
970 } else {
971 L->link_to(pc_offset());
972 if (!trampoline_emitted_) {
973 unbound_labels_count++;
974 next_buffer_check_ -= kTrampolineSlotsSize;
975 }
944 return kEndOfChain; 976 return kEndOfChain;
945 } 977 }
946 } 978 }
947 979
948 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); 980 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
949 ASSERT((offset & 3) == 0); 981 ASSERT((offset & 3) == 0);
950 ASSERT(is_int16(offset >> 2)); 982 ASSERT(is_int16(offset >> 2));
951 983
952 return offset; 984 return offset;
953 } 985 }
954 986
955 987
956 void Assembler::label_at_put(Label* L, int at_offset) { 988 void Assembler::label_at_put(Label* L, int at_offset) {
957 int target_pos; 989 int target_pos;
958 if (L->is_bound()) { 990 if (L->is_bound()) {
959 target_pos = L->pos(); 991 target_pos = L->pos();
960 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 992 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
961 } else { 993 } else {
962 if (L->is_linked()) { 994 if (L->is_linked()) {
963 target_pos = L->pos(); // L's link. 995 target_pos = L->pos(); // L's link.
964 int32_t imm18 = target_pos - at_offset; 996 int32_t imm18 = target_pos - at_offset;
965 ASSERT((imm18 & 3) == 0); 997 ASSERT((imm18 & 3) == 0);
966 int32_t imm16 = imm18 >> 2; 998 int32_t imm16 = imm18 >> 2;
967 ASSERT(is_int16(imm16)); 999 ASSERT(is_int16(imm16));
968 instr_at_put(at_offset, (imm16 & kImm16Mask)); 1000 instr_at_put(at_offset, (imm16 & kImm16Mask));
969 } else { 1001 } else {
970 target_pos = kEndOfChain; 1002 target_pos = kEndOfChain;
971 instr_at_put(at_offset, 0); 1003 instr_at_put(at_offset, 0);
1004 if (!trampoline_emitted_) {
1005 unbound_labels_count++;
1006 next_buffer_check_ -= kTrampolineSlotsSize;
1007 }
972 } 1008 }
973 L->link_to(at_offset); 1009 L->link_to(at_offset);
974 } 1010 }
975 } 1011 }
976 1012
977 1013
978 //------- Branch and jump instructions -------- 1014 //------- Branch and jump instructions --------
979 1015
980 void Assembler::b(int16_t offset) { 1016 void Assembler::b(int16_t offset) {
981 beq(zero_reg, zero_reg, offset); 1017 beq(zero_reg, zero_reg, offset);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 void Assembler::andi(Register rt, Register rs, int32_t j) { 1167 void Assembler::andi(Register rt, Register rs, int32_t j) {
1132 GenInstrImmediate(ANDI, rs, rt, j); 1168 GenInstrImmediate(ANDI, rs, rt, j);
1133 } 1169 }
1134 1170
1135 1171
1136 void Assembler::or_(Register rd, Register rs, Register rt) { 1172 void Assembler::or_(Register rd, Register rs, Register rt) {
1137 GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR); 1173 GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
1138 } 1174 }
1139 1175
1140 1176
1141 void Assembler::ori(Register rt, Register rs, int32_t j) { 1177 void Assembler::ori(Register rt, Register rs, int32_t j, bool check_buffer) {
1142 GenInstrImmediate(ORI, rs, rt, j); 1178 GenInstrImmediate(ORI, rs, rt, j, check_buffer);
1143 } 1179 }
1144 1180
1145 1181
1146 void Assembler::xor_(Register rd, Register rs, Register rt) { 1182 void Assembler::xor_(Register rd, Register rs, Register rt) {
1147 GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR); 1183 GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
1148 } 1184 }
1149 1185
1150 1186
1151 void Assembler::xori(Register rt, Register rs, int32_t j) { 1187 void Assembler::xori(Register rt, Register rs, int32_t j) {
1152 GenInstrImmediate(XORI, rs, rt, j); 1188 GenInstrImmediate(XORI, rs, rt, j);
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1321 void Assembler::swl(Register rd, const MemOperand& rs) { 1357 void Assembler::swl(Register rd, const MemOperand& rs) {
1322 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); 1358 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
1323 } 1359 }
1324 1360
1325 1361
1326 void Assembler::swr(Register rd, const MemOperand& rs) { 1362 void Assembler::swr(Register rd, const MemOperand& rs) {
1327 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); 1363 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
1328 } 1364 }
1329 1365
1330 1366
1331 void Assembler::lui(Register rd, int32_t j) { 1367 void Assembler::lui(Register rd, int32_t j, bool check_buffer) {
1332 GenInstrImmediate(LUI, zero_reg, rd, j); 1368 GenInstrImmediate(LUI, zero_reg, rd, j, check_buffer);
1333 } 1369 }
1334 1370
1335 1371
1336 //-------------Misc-instructions-------------- 1372 //-------------Misc-instructions--------------
1337 1373
1338 // Break / Trap instructions. 1374 // Break / Trap instructions.
1339 void Assembler::break_(uint32_t code, bool break_as_stop) { 1375 void Assembler::break_(uint32_t code, bool break_as_stop) {
1340 ASSERT((code & ~0xfffff) == 0); 1376 ASSERT((code & ~0xfffff) == 0);
1341 // We need to invalidate breaks that could be stops as well because the 1377 // We need to invalidate breaks that could be stops as well because the
1342 // simulator expects a char pointer after the stop instruction. 1378 // simulator expects a char pointer after the stop instruction.
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 1820
1785 1821
1786 void Assembler::RecordComment(const char* msg) { 1822 void Assembler::RecordComment(const char* msg) {
1787 if (FLAG_code_comments) { 1823 if (FLAG_code_comments) {
1788 CheckBuffer(); 1824 CheckBuffer();
1789 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 1825 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1790 } 1826 }
1791 } 1827 }
1792 1828
1793 1829
1830 void Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
1831 Instr instr = instr_at(pc);
1832 ASSERT(IsJ(instr) || IsLui(instr));
1833 if (IsLui(instr)) {
1834 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
1835 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
1836 ASSERT(IsLui(instr_lui) && IsOri(instr_ori));
Søren Thygesen Gjesse 2011/06/24 13:05:15 Ditto.
Paul Lind 2011/06/28 06:53:14 Done.
1837 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
1838 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
1839 if (imm == kEndOfJumpChain) {
1840 return;
1841 }
1842 imm += pc_delta;
1843 ASSERT((imm & 3) == 0);
1844
1845 instr_lui &= ~kImm16Mask;
1846 instr_ori &= ~kImm16Mask;
1847
1848 instr_at_put(pc + 0 * Assembler::kInstrSize,
1849 instr_lui | ((imm >> kLuiShift) & kImm16Mask));
1850 instr_at_put(pc + 1 * Assembler::kInstrSize,
1851 instr_ori | (imm & kImm16Mask));
1852 } else {
1853 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
1854 if ((int32_t)imm28 == kEndOfJumpChain) {
1855 return;
1856 }
1857 imm28 += pc_delta;
1858 imm28 &= kImm28Mask;
1859 ASSERT((imm28 & 3) == 0);
1860
1861 instr &= ~kImm26Mask;
1862 uint32_t imm26 = imm28 >> 2;
1863 ASSERT(is_uint26(imm26));
1864
1865 instr_at_put(pc, instr | (imm26 & kImm26Mask));
1866 }
1867 }
1868
1869
1794 void Assembler::GrowBuffer() { 1870 void Assembler::GrowBuffer() {
1795 if (!own_buffer_) FATAL("external code buffer is too small"); 1871 if (!own_buffer_) FATAL("external code buffer is too small");
1796 1872
1797 // Compute new buffer size. 1873 // Compute new buffer size.
1798 CodeDesc desc; // The new buffer. 1874 CodeDesc desc; // The new buffer.
1799 if (buffer_size_ < 4*KB) { 1875 if (buffer_size_ < 4*KB) {
1800 desc.buffer_size = 4*KB; 1876 desc.buffer_size = 4*KB;
1801 } else if (buffer_size_ < 1*MB) { 1877 } else if (buffer_size_ < 1*MB) {
1802 desc.buffer_size = 2*buffer_size_; 1878 desc.buffer_size = 2*buffer_size_;
1803 } else { 1879 } else {
(...skipping 15 matching lines...) Expand all
1819 reloc_info_writer.pos(), desc.reloc_size); 1895 reloc_info_writer.pos(), desc.reloc_size);
1820 1896
1821 // Switch buffers. 1897 // Switch buffers.
1822 DeleteArray(buffer_); 1898 DeleteArray(buffer_);
1823 buffer_ = desc.buffer; 1899 buffer_ = desc.buffer;
1824 buffer_size_ = desc.buffer_size; 1900 buffer_size_ = desc.buffer_size;
1825 pc_ += pc_delta; 1901 pc_ += pc_delta;
1826 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 1902 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
1827 reloc_info_writer.last_pc() + pc_delta); 1903 reloc_info_writer.last_pc() + pc_delta);
1828 1904
1829 // On ia32 and ARM pc relative addressing is used, and we thus need to apply a 1905 // Relocate runtime entries.
1830 // shift by pc_delta. But on MIPS the target address it directly loaded, so 1906 for (RelocIterator it(desc); !it.done(); it.next()) {
1831 // we do not need to relocate here. 1907 RelocInfo::Mode rmode = it.rinfo()->rmode();
1908 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
1909 byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
1910 RelocateInternalReference(p, pc_delta);
1911 }
1912 }
1832 1913
1833 ASSERT(!overflow()); 1914 ASSERT(!overflow());
1834 } 1915 }
1835 1916
1836 1917
1837 void Assembler::db(uint8_t data) { 1918 void Assembler::db(uint8_t data) {
1838 CheckBuffer(); 1919 CheckBuffer();
1839 *reinterpret_cast<uint8_t*>(pc_) = data; 1920 *reinterpret_cast<uint8_t*>(pc_) = data;
1840 pc_ += sizeof(uint8_t); 1921 pc_ += sizeof(uint8_t);
1841 } 1922 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1876 } 1957 }
1877 } 1958 }
1878 } 1959 }
1879 1960
1880 1961
1881 void Assembler::BlockTrampolinePoolFor(int instructions) { 1962 void Assembler::BlockTrampolinePoolFor(int instructions) {
1882 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 1963 BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
1883 } 1964 }
1884 1965
1885 1966
1886 void Assembler::CheckTrampolinePool(bool force_emit) { 1967 void Assembler::CheckTrampolinePool() {
1887 // Calculate the offset of the next check.
1888 next_buffer_check_ = pc_offset() + kCheckConstInterval;
1889
1890 int dist = pc_offset() - last_trampoline_pool_end_;
1891
1892 if (dist <= kMaxDistBetweenPools && !force_emit) {
1893 return;
1894 }
1895
1896 // Some small sequences of instructions must not be broken up by the 1968 // Some small sequences of instructions must not be broken up by the
1897 // insertion of a trampoline pool; such sequences are protected by setting 1969 // insertion of a trampoline pool; such sequences are protected by setting
1898 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, 1970 // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
1899 // which are both checked here. Also, recursive calls to CheckTrampolinePool 1971 // which are both checked here. Also, recursive calls to CheckTrampolinePool
1900 // are blocked by trampoline_pool_blocked_nesting_. 1972 // are blocked by trampoline_pool_blocked_nesting_.
1901 if ((trampoline_pool_blocked_nesting_ > 0) || 1973 if ((trampoline_pool_blocked_nesting_ > 0) ||
1902 (pc_offset() < no_trampoline_pool_before_)) { 1974 (pc_offset() < no_trampoline_pool_before_)) {
1903 // Emission is currently blocked; make sure we try again as soon as 1975 // Emission is currently blocked; make sure we try again as soon as
1904 // possible. 1976 // possible.
1905 if (trampoline_pool_blocked_nesting_ > 0) { 1977 if (trampoline_pool_blocked_nesting_ > 0) {
1906 next_buffer_check_ = pc_offset() + kInstrSize; 1978 next_buffer_check_ = pc_offset() + kInstrSize;
1907 } else { 1979 } else {
1908 next_buffer_check_ = no_trampoline_pool_before_; 1980 next_buffer_check_ = no_trampoline_pool_before_;
1909 } 1981 }
1910 return; 1982 return;
1911 } 1983 }
1912 1984
1913 // First we emit jump (2 instructions), then we emit trampoline pool. 1985 ASSERT(!trampoline_emitted_);
1914 { BlockTrampolinePoolScope block_trampoline_pool(this); 1986 ASSERT(unbound_labels_count >= 0);
1915 Label after_pool; 1987 if (unbound_labels_count > 0) {
1916 b(&after_pool); 1988 // First we emit jump (2 instructions), then we emit trampoline pool.
1917 nop(); 1989 { BlockTrampolinePoolScope block_trampoline_pool(this);
1918 1990 Label after_pool;
1919 int pool_start = pc_offset();
1920 for (int i = 0; i < kSlotsPerTrampoline; i++) {
1921 b(&after_pool); 1991 b(&after_pool);
1922 nop(); 1992 nop();
1993
1994 int pool_start = pc_offset();
1995 for (int i = 0; i < unbound_labels_count; i++) {
1996 uint32_t imm32;
1997 imm32 = jump_address(&after_pool);
1998 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
1999 lui(at, (imm32 & kHiMask) >> kLuiShift, false);
2000 ori(at, at, (imm32 & kImm16Mask), false);
Søren Thygesen Gjesse 2011/06/24 13:05:15 Can't the jr go between the lui and the ori and th
Paul Lind 2011/06/28 06:53:14 Unfortunately, it cannot. This is jr (jump) to 'at
2001 jr(at);
2002 nop();
2003 }
2004 bind(&after_pool);
2005 trampoline_ = Trampoline(pool_start, unbound_labels_count);
2006
2007 trampoline_emitted_ = true;
2008 // As we are only going to emit trampoline once, we need to prevent any
2009 // further emission.
2010 next_buffer_check_ = kMaxInt;
1923 } 2011 }
1924 for (int i = 0; i < kLabelsPerTrampoline; i++) { 2012 } else {
1925 emit(0); 2013 // Number of branches to unbound label at this point is zero, so we can
1926 } 2014 // move next buffer check to maximum.
1927 last_trampoline_pool_end_ = pc_offset() - kInstrSize; 2015 next_buffer_check_ = pc_offset() + kMaxBranchOffset
1928 bind(&after_pool); 2016 - kTrampolineSlotsSize * 16;
1929 trampolines_.Add(Trampoline(pool_start,
1930 kSlotsPerTrampoline,
1931 kLabelsPerTrampoline));
1932
1933 // Since a trampoline pool was just emitted,
1934 // move the check offset forward by the standard interval.
1935 next_buffer_check_ = last_trampoline_pool_end_ + kMaxDistBetweenPools;
1936 } 2017 }
1937 return; 2018 return;
1938 } 2019 }
1939 2020
1940 2021
1941 Address Assembler::target_address_at(Address pc) { 2022 Address Assembler::target_address_at(Address pc) {
1942 Instr instr1 = instr_at(pc); 2023 Instr instr1 = instr_at(pc);
1943 Instr instr2 = instr_at(pc + kInstrSize); 2024 Instr instr2 = instr_at(pc + kInstrSize);
1944 // Interpret 2 instructions generated by li: lui/ori 2025 // Interpret 2 instructions generated by li: lui/ori
1945 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { 2026 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) {
(...skipping 29 matching lines...) Expand all
1975 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); 2056 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift);
1976 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); 2057 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask);
1977 2058
1978 CPU::FlushICache(pc, 2 * sizeof(int32_t)); 2059 CPU::FlushICache(pc, 2 * sizeof(int32_t));
1979 } 2060 }
1980 2061
1981 2062
1982 } } // namespace v8::internal 2063 } } // namespace v8::internal
1983 2064
1984 #endif // V8_TARGET_ARCH_MIPS 2065 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698