Chromium Code Reviews| Index: runtime/vm/assembler_arm64.h |
| =================================================================== |
| --- runtime/vm/assembler_arm64.h (revision 41529) |
| +++ runtime/vm/assembler_arm64.h (working copy) |
| @@ -675,6 +675,9 @@ |
| void smulh(Register rd, Register rn, Register rm) { |
| EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); |
| } |
| + void umaddl(Register rd, Register rn, Register rm, Register ra) { |
| + EmitMiscDP3Source(UMADDL, rd, rn, rm, ra, kDoubleWord); |
| + } |
| // Move wide immediate. |
| void movk(Register rd, const Immediate& imm, int hw_idx) { |
| @@ -782,7 +785,7 @@ |
| // Conditional branch. |
| void b(Label* label, Condition cond = AL) { |
| - EmitBranch(BCOND, cond, label); |
| + EmitConditionalBranch(BCOND, cond, label); |
| } |
| void b(int32_t offset) { |
| @@ -792,8 +795,14 @@ |
| EmitUnconditionalBranchOp(BL, offset); |
| } |
| - // TODO(zra): cbz, cbnz. |
| + void cbz(Label* label, Register rt, OperandSize sz = kDoubleWord) { |
| + EmitCompareAndBranch(CBZ, rt, label, sz); |
| + } |
| + void cbnz(Label* label, Register rt, OperandSize sz = kDoubleWord) { |
| + EmitCompareAndBranch(CBNZ, rt, label, sz); |
| + } |
| + |
| // Branch, link, return. |
| void br(Register rn) { |
| EmitUnconditionalBranchRegOp(BR, rn); |
| @@ -1600,8 +1609,8 @@ |
| return static_cast<int64_t>(off); |
| } |
| - void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, |
| - OperandSize sz) { |
| + void EmitCompareAndBranchOp(CompareAndBranchOp op, Register rt, int64_t imm, |
| + OperandSize sz) { |
| ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| ASSERT((rt != CSP) && (rt != R31)); |
| @@ -1615,8 +1624,8 @@ |
| Emit(encoding); |
| } |
| - void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, |
| - int64_t imm) { |
| + void EmitConditionalBranchOp(ConditionalBranchOp op, Condition cond, |
| + int64_t imm) { |
| const int32_t off = EncodeImm19BranchOffset(imm, 0); |
| const int32_t encoding = |
| op | |
| @@ -1630,7 +1639,8 @@ |
| return Utils::IsInt(21, offset); |
| } |
| - void EmitBranch(ConditionalBranchOp op, Condition cond, Label* label) { |
| + void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, |
| + Label* label) { |
| if (label->IsBound()) { |
| const int64_t dest = label->Position() - buffer_.Size(); |
| if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) { |
| @@ -1639,12 +1649,12 @@ |
| // no need for a guard branch. |
| b(dest); |
| } else { |
| - EmitConditionalBranch( |
| + EmitConditionalBranchOp( |
| op, InvertCondition(cond), 2 * Instr::kInstrSize); |
| b(dest); |
| } |
| } else { |
| - EmitConditionalBranch(op, cond, dest); |
| + EmitConditionalBranchOp(op, cond, dest); |
| } |
| } else { |
| const int64_t position = buffer_.Size(); |
| @@ -1652,15 +1662,40 @@ |
| // When cond is AL, this guard branch will be rewritten as a nop when |
| // the label is bound. We don't write it as a nop initially because it |
| // makes the decoding code in Bind simpler. |
| - EmitConditionalBranch(op, InvertCondition(cond), 2 * Instr::kInstrSize); |
| + EmitConditionalBranchOp( |
| + op, InvertCondition(cond), 2 * Instr::kInstrSize); |
| b(label->position_); |
| } else { |
| - EmitConditionalBranch(op, cond, label->position_); |
| + EmitConditionalBranchOp(op, cond, label->position_); |
| } |
| label->LinkTo(position); |
| } |
| } |
| + void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, |
|
zra
2014/11/06 00:30:59
You also need to detect these instructions in Bind
|
| + Label* label, OperandSize sz) { |
| + if (label->IsBound()) { |
| + const int64_t dest = label->Position() - buffer_.Size(); |
| + if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) { |
| + EmitCompareAndBranchOp( |
| + op == CBZ ? CBNZ : CBZ, rt, 2 * Instr::kInstrSize, sz); |
| + b(dest); |
| + } else { |
| + EmitCompareAndBranchOp(op, rt, dest, sz); |
| + } |
| + } else { |
| + const int64_t position = buffer_.Size(); |
| + if (use_far_branches()) { |
| + EmitCompareAndBranchOp( |
| + op == CBZ ? CBNZ : CBZ, rt, 2 * Instr::kInstrSize, sz); |
| + b(label->position_); |
| + } else { |
| + EmitCompareAndBranchOp(op, rt, label->position_, sz); |
| + } |
| + label->LinkTo(position); |
| + } |
| + } |
| + |
| bool CanEncodeImm26BranchOffset(int64_t offset) { |
| ASSERT(Utils::IsAligned(offset, 4)); |
| return Utils::IsInt(26, offset); |