summaryrefslogtreecommitdiff
path: root/compiler/utils/x86/assembler_x86.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/x86/assembler_x86.cc')
-rw-r--r--compiler/utils/x86/assembler_x86.cc78
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) {