Home | History | Annotate | Download | only in mips

Lines Matching full:branch

70       // the PC of the label preceding it so that no unconditional branch
236 // Commit the last branch target label (if any) and disable instruction reordering.
311 // existing instructions (branch placeholders) in the buffer.
313 for (auto& branch : branches_) {
314 EmitBranch(&branch);
1067 LOG(FATAL) << "Unexpected branch condition " << cond;
1131 LOG(FATAL) << "Unexpected branch condition " << cond;
1796 void MipsAssembler::Branch::InitShortOrLong(MipsAssembler::Branch::OffsetBits offset_size,
1797 MipsAssembler::Branch::Type short_type,
1798 MipsAssembler::Branch::Type long_type) {
1802 void MipsAssembler::Branch::InitializeType(Type initial_type, bool is_r6) {
1834 LOG(FATAL) << "Unexpected branch type " << initial_type;
1862 LOG(FATAL) << "Unexpected branch type " << initial_type;
1869 bool MipsAssembler::Branch::IsNop(BranchCondition condition, Register lhs, Register rhs) {
1881 bool MipsAssembler::Branch::IsUncond(BranchCondition condition, Register lhs, Register rhs) {
1895 MipsAssembler::Branch::Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call)
1906 MipsAssembler::Branch::Branch(bool is_r6,
1958 // Branch condition is always true, make the branch unconditional.
1964 MipsAssembler::Branch::Branch(bool is_r6,
1985 MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition(
2021 LOG(FATAL) << "Unexpected branch condition " << cond;
2026 MipsAssembler::Branch::Type MipsAssembler::Branch::GetType() const {
2030 MipsAssembler::BranchCondition MipsAssembler::Branch::GetCondition() const {
2034 Register MipsAssembler::Branch::GetLeftRegister() const {
2038 Register MipsAssembler::Branch::GetRightRegister() const {
2042 uint32_t MipsAssembler::Branch::GetTarget() const {
2046 uint32_t MipsAssembler::Branch::GetLocation() const {
2050 uint32_t MipsAssembler::Branch::GetOldLocation() const {
2054 uint32_t MipsAssembler::Branch::GetPrecedingInstructionLength(Type type) const {
2055 // Short branches with delay slots always consist of two instructions, the branch
2060 // to fill the short branch delay slot, but the branch eventually becomes long
2062 // beginning of the long composite branch and this needs to be accounted for in
2063 // the branch length and the location of the offset encoded in the branch.
2076 uint32_t MipsAssembler::Branch::GetPrecedingInstructionSize(Type type) const {
2080 uint32_t MipsAssembler::Branch::GetLength() const {
2084 uint32_t MipsAssembler::Branch::GetOldLength() const {
2088 uint32_t MipsAssembler::Branch::GetSize() const {
2092 uint32_t MipsAssembler::Branch::GetOldSize() const {
2096 uint32_t MipsAssembler::Branch::GetEndLocation() const {
2100 uint32_t MipsAssembler::Branch::GetOldEndLocation() const {
2104 bool MipsAssembler::Branch::IsLong() const {
2144 bool MipsAssembler::Branch::IsResolved() const {
2148 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSize() const {
2156 MipsAssembler::Branch::OffsetBits MipsAssembler::Branch::GetOffsetSizeNeeded(uint32_t location,
2164 // bump up the distance by a value larger than the max byte size of a composite branch.
2179 void MipsAssembler::Branch::Resolve(uint32_t target) {
2183 void MipsAssembler::Branch::Relocate(uint32_t expand_location, uint32_t delta) {
2195 void MipsAssembler::Branch::PromoteToLong() {
2240 uint32_t MipsAssembler::GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const {
2241 switch (branch->GetType()) {
2242 case Branch::kLabel:
2243 case Branch::kFarLabel:
2244 case Branch::kLiteral:
2245 case Branch::kFarLiteral:
2248 return branch->GetLocation();
2252 uint32_t MipsAssembler::Branch::PromoteIfNeeded(uint32_t location, uint32_t max_short_distance) {
2255 // If the branch is still unresolved or already long, nothing to do.
2259 // Promote the short branch to long if the offset size is too small
2284 uint32_t MipsAssembler::Branch::GetOffsetLocation() const {
2289 uint32_t MipsAssembler::GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const {
2290 switch (branch->GetType()) {
2291 case Branch::kLabel:
2292 case Branch::kFarLabel:
2293 case Branch::kLiteral:
2294 case Branch::kFarLiteral:
2297 return branch->GetOffsetLocation() +
2298 Branch::branch_info_[branch->GetType()].pc_org * sizeof(uint32_t);
2302 uint32_t MipsAssembler::Branch::GetOffset(uint32_t location) const {
2316 MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) {
2321 const MipsAssembler::Branch* MipsAssembler::GetBranch(uint32_t branch_id) const {
2337 Branch* branch = GetBranch(branch_id);
2338 branch->Resolve(bound_pc);
2340 uint32_t branch_location = branch->GetLocation();
2341 // Extract the location of the previous branch in the list (walking the list backwards;
2342 // the previous branch ID was stored in the space reserved for this branch).
2345 // On to the previous branch in the list...
2350 // branch, if any; it will be used by the branches referring to and following this label).
2354 const Branch* branch = GetBranch(branch_id);
2355 bound_pc -= branch->GetEndLocation();
2364 // Get label location based on the branch preceding it.
2366 const Branch* branch = GetBranch(branch_id);
2367 target += branch->GetEndLocation();
2384 const Branch* branch = GetBranch(last_branch_id_);
2385 if (branch->GetLocation() >= old_position + last_position_adjustment_) {
2388 last_position_adjustment_ += branch->GetSize() - branch->GetOldSize();
2405 // Commit the last branch target label (if any).
2408 // Branch forward (to a following label), distance is unknown.
2409 // The first branch forward will contain 0, serving as the terminator of
2415 // Now make the label object point to this branch
2420 // Reserve space for the branch.
2426 bool MipsAssembler::Branch::CanHaveDelayedInstruction(const DelaySlot& delay_slot) const {
2471 LOG(FATAL) << "Unexpected branch condition " << condition_;
2499 LOG(FATAL) << "Unexpected branch type " << type_;
2504 uint32_t MipsAssembler::Branch::GetDelayedInstruction() const {
2508 void MipsAssembler::Branch::SetDelayedInstruction(uint32_t instruction) {
2514 void MipsAssembler::Branch::DecrementLocations() {
2515 // We first create a branch object, which gets its type and locations initialized,
2516 // and then we check if the branch can actually have the preceding instruction moved
2517 // into its delay slot. If it can, the branch locations need to be decremented.
2519 // We could make the check before creating the branch object and avoid the location
2520 // adjustment, but the check is cleaner when performed on an initialized branch
2523 // If the branch is backwards (to a previously bound label), reducing the locations
2524 // cannot cause a short branch to exceed its offset range because the offset reduces.
2525 // And this is not at all a problem for a long branch backwards.
2527 // If the branch is forward (not linked to any label yet), reducing the locations
2528 // is harmless. The branch will be promoted to long if needed when the target is known.
2535 void MipsAssembler::MoveInstructionToDelaySlot(Branch& branch) {
2536 if (branch.CanHaveDelayedInstruction(delay_slot_)) {
2546 // Attach it to the branch and adjust the branch locations.
2547 branch.DecrementLocations();
2548 branch.SetDelayedInstruction(delay_slot_.instruction_);
2549 } else if (!reordering_ && branch.GetType() == Branch::kUncondBranch) {
2551 branch.SetDelayedInstruction(Branch::kUnfillableDelaySlot);
2556 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2564 if (Branch::IsNop(condition, lhs, rhs)) {
2567 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2574 uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;
2583 branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLabel);
2598 branches_.emplace_back(IsR6(), buffer_.Size(), dest_reg, base_reg, Branch::kLiteral);
2643 // be moving uninitialized data during branch promotion.
2684 for (auto& branch : branches_) {
2685 CHECK(branch.IsResolved());
2686 uint32_t base = GetBranchLocationOrPcRelBase(&branch);
2687 uint32_t delta = branch.PromoteIfNeeded(base);
2688 // If this branch has been promoted and needs to expand in size,
2692 uint32_t expand_location = branch.GetLocation();
2700 // Account for branch expansion by resizing the code buffer
2705 Branch& last_branch = branches_[branch_count - 1];
2709 // Move the code residing between branch placeholders.
2712 Branch& branch = branches_[--i];
2713 CHECK_GE(end, branch.GetOldEndLocation());
2714 uint32_t size = end - branch.GetOldEndLocation();
2715 buffer_.Move(branch.GetEndLocation(), branch.GetOldEndLocation(), size);
2716 end = branch.GetOldLocation();
2722 const MipsAssembler::Branch::BranchInfo MipsAssembler::Branch::branch_info_[] = {
2724 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kUncondBranch
2725 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCondBranch
2726 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kCall
2728 { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLabel
2730 { 1, 0, 0, MipsAssembler::Branch::kOffset16, 0 }, // kLiteral
2732 { 9, 3, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongUncondBranch
2733 { 10, 4, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCondBranch
2734 { 6, 1, 1, MipsAssembler::Branch::kOffset32, 0 }, // kLongCall
2736 { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLabel
2738 { 3, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kFarLiteral
2740 { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6UncondBranch
2741 { 2, 0, 1, MipsAssembler::Branch::kOffset18, 2 }, // kR6CondBranch
2743 { 1, 0, 1, MipsAssembler::Branch::kOffset28, 2 }, // kR6Call
2745 { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Label
2747 { 1, 0, 0, MipsAssembler::Branch::kOffset21, 2 }, // kR6Literal
2749 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongUncondBranch
2750 { 3, 1, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCondBranch
2751 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6LongCall
2753 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLabel
2755 { 2, 0, 0, MipsAssembler::Branch::kOffset32, 0 }, // kR6FarLiteral
2759 void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) {
2761 overwrite_location_ = branch->GetLocation();
2762 uint32_t offset = branch->GetOffset(GetBranchOrPcRelBaseForEncoding(branch));
2763 BranchCondition condition = branch->GetCondition();
2764 Register lhs = branch->GetLeftRegister();
2765 Register rhs = branch->GetRightRegister();
2766 uint32_t delayed_instruction = branch->GetDelayedInstruction();
2767 switch (branch->GetType()) {
2769 case Branch::kUncondBranch:
2770 if (delayed_instruction == Branch::kUnfillableDelaySlot) {
2771 // The branch was created when reordering was disabled, do not absorb the target
2774 } else if (delayed_instruction == Branch::kUnfilledDelaySlot) {
2780 uint32_t target = branch->GetTarget();
2787 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2791 case Branch::kCondBranch:
2792 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2793 if (delayed_instruction == Branch::kUnfilledDelaySlot) {
2796 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2800 case Branch::kCall:
2801 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2802 if (delayed_instruction == Branch::kUnfilledDelaySlot) {
2805 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2811 case Branch::kLabel:
2812 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2813 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2817 case Branch::kLiteral:
2818 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2819 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2824 case Branch::kLongUncondBranch:
2841 // vast majority of code a short PC-relative branch is sufficient.
2845 if (delayed_instruction != Branch::kUnfilledDelaySlot &&
2846 delayed_instruction != Branch::kUnfillableDelaySlot) {
2851 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2859 case Branch::kLongCondBranch:
2860 // The comment on case 'Branch::kLongUncondBranch' applies here as well.
2861 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2862 if (delayed_instruction != Branch::kUnfilledDelaySlot) {
2865 // Note: the opposite condition branch encodes 8 as the distance, which is equal to the
2868 EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8);
2871 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2879 case Branch::kLongCall:
2880 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2881 if (delayed_instruction != Branch::kUnfilledDelaySlot) {
2885 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2894 case Branch::kFarLabel:
2895 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2896 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2902 case Branch::kFarLiteral:
2903 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2905 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2912 case Branch::kR6UncondBranch:
2913 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2914 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2917 case Branch::kR6CondBranch:
2918 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2920 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2921 if (delayed_instruction != Branch::kUnfilledDelaySlot) {
2929 case Branch::kR6Call:
2930 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2931 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2936 case Branch::kR6Label:
2937 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2938 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2942 case Branch::kR6Literal:
2943 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2944 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2949 case Branch::kR6LongUncondBranch:
2950 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2952 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2956 case Branch::kR6LongCondBranch:
2957 DCHECK_NE(delayed_instruction, Branch::kUnfillableDelaySlot);
2958 if (delayed_instruction != Branch::kUnfilledDelaySlot) {
2961 EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2);
2963 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2967 case Branch::kR6LongCall:
2968 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2970 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2976 case Branch::kR6FarLabel:
2977 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2979 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2984 case Branch::kR6FarLiteral:
2985 DCHECK_EQ(delayed_instruction, Branch::kUnfilledDelaySlot);
2987 CHECK_EQ(overwrite_location_, branch->GetOffsetLocation());
2992 branch->GetEndLocation());
2993 CHECK_LT(branch->GetSize(), static_cast<uint32_t>(Branch::kMaxBranchSize));
3039 // conditional branch depends on AT set by slt[u].
3087 } else if (!Branch::IsNop(kCondLT, rs, rt)) {
3097 } else if (Branch::IsUncond(kCondGE, rs, rt)) {
3109 } else if (!Branch::IsNop(kCondLTU, rs, rt)) {
3119 } else if (Branch::IsUncond(kCondGEU, rs, rt)) {