diff options
Diffstat (limited to 'compiler/utils/x86/assembler_x86.cc')
| -rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index 9b3d792903..a03f857e88 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -1510,6 +1510,38 @@ void X86Assembler::j(Condition condition, Label* label) { } +void X86Assembler::j(Condition condition, NearLabel* label) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + if (label->IsBound()) { + static const int kShortSize = 2; + int offset = label->Position() - buffer_.Size(); + CHECK_LE(offset, 0); + CHECK(IsInt<8>(offset - kShortSize)); + EmitUint8(0x70 + condition); + EmitUint8((offset - kShortSize) & 0xFF); + } else { + EmitUint8(0x70 + condition); + EmitLabelLink(label); + } +} + + +void X86Assembler::jecxz(NearLabel* label) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + if (label->IsBound()) { + static const int kShortSize = 2; + int offset = label->Position() - buffer_.Size(); + CHECK_LE(offset, 0); + CHECK(IsInt<8>(offset - kShortSize)); + EmitUint8(0xE3); + EmitUint8((offset - kShortSize) & 0xFF); + } else { + EmitUint8(0xE3); + EmitLabelLink(label); + } +} + + void X86Assembler::jmp(Register reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xFF); @@ -1543,6 +1575,22 @@ void X86Assembler::jmp(Label* label) { } +void X86Assembler::jmp(NearLabel* label) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + if (label->IsBound()) { + static const int kShortSize = 2; + int offset = label->Position() - buffer_.Size(); + CHECK_LE(offset, 0); + CHECK(IsInt<8>(offset - kShortSize)); + EmitUint8(0xEB); + EmitUint8((offset - kShortSize) & 0xFF); + } else { + EmitUint8(0xEB); + EmitLabelLink(label); + } +} + + void X86Assembler::repne_scasw() { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0x66); @@ -1675,6 +1723,21 @@ void X86Assembler::Bind(Label* label) { } +void X86Assembler::Bind(NearLabel* label) { + int bound = buffer_.Size(); + CHECK(!label->IsBound()); // Labels can only be bound once. + while (label->IsLinked()) { + int position = label->LinkPosition(); + uint8_t delta = buffer_.Load<uint8_t>(position); + int offset = bound - (position + 1); + CHECK(IsInt<8>(offset)); + buffer_.Store<int8_t>(position, offset); + label->position_ = delta != 0u ? label->position_ - delta : 0; + } + label->BindTo(bound); +} + + void X86Assembler::EmitOperand(int reg_or_opcode, const Operand& operand) { CHECK_GE(reg_or_opcode, 0); CHECK_LT(reg_or_opcode, 8); @@ -1736,6 +1799,21 @@ void X86Assembler::EmitLabelLink(Label* label) { } +void X86Assembler::EmitLabelLink(NearLabel* label) { + CHECK(!label->IsBound()); + int position = buffer_.Size(); + if (label->IsLinked()) { + // Save the delta in the byte that we have to play with. + uint32_t delta = position - label->LinkPosition(); + CHECK(IsUint<8>(delta)); + EmitUint8(delta & 0xFF); + } else { + EmitUint8(0); + } + label->LinkTo(position); +} + + void X86Assembler::EmitGenericShift(int reg_or_opcode, const Operand& operand, const Immediate& imm) { |