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

Unified Diff: src/x64/assembler-x64.cc

Issue 887013003: [x64] Assembler support for internal references and RIP relative addressing. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/assembler-x64.h ('k') | src/x64/assembler-x64-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/assembler-x64.cc
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 355996458cf70a163fc919f9cd7575e48e56ace1..597aa31f54d86c59d0cb5fe3dccae6334c716aa3 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -219,6 +219,13 @@ Operand::Operand(Register index,
}
+Operand::Operand(Label* label) : rex_(0), len_(1) {
+ DCHECK_NOT_NULL(label);
+ set_modrm(0, rbp);
+ set_disp64(reinterpret_cast<intptr_t>(label));
+}
+
+
Operand::Operand(const Operand& operand, int32_t offset) {
DCHECK(operand.len_ >= 1);
// Operand encodes REX ModR/M [SIB] [Disp].
@@ -365,15 +372,30 @@ void Assembler::bind_to(Label* L, int pos) {
int current = L->pos();
int next = long_at(current);
while (next != current) {
- // Relative address, relative to point after address.
- int imm32 = pos - (current + sizeof(int32_t));
- long_at_put(current, imm32);
+ if (current >= 4 && long_at(current - 4) == 0) {
+ // Absolute address.
+ intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
+ *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
+ internal_reference_positions_.push_back(current - 4);
+ } else {
+ // Relative address, relative to point after address.
+ int imm32 = pos - (current + sizeof(int32_t));
+ long_at_put(current, imm32);
+ }
current = next;
next = long_at(next);
}
// Fix up last fixup on linked list.
- int last_imm32 = pos - (current + sizeof(int32_t));
- long_at_put(current, last_imm32);
+ if (current >= 4 && long_at(current - 4) == 0) {
+ // Absolute address.
+ intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
+ *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
+ internal_reference_positions_.push_back(current - 4);
+ } else {
+ // Relative address, relative to point after address.
+ int imm32 = pos - (current + sizeof(int32_t));
+ long_at_put(current, imm32);
+ }
}
while (L->is_near_linked()) {
int fixup_pos = L->near_link_pos();
@@ -441,15 +463,10 @@ void Assembler::GrowBuffer() {
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
reloc_info_writer.last_pc() + pc_delta);
- // Relocate runtime entries.
- for (RelocIterator it(desc); !it.done(); it.next()) {
- RelocInfo::Mode rmode = it.rinfo()->rmode();
- if (rmode == RelocInfo::INTERNAL_REFERENCE) {
- intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
- if (*p != 0) { // 0 means uninitialized.
- *p += pc_delta;
- }
- }
+ // Relocate internal references.
+ for (auto pos : internal_reference_positions_) {
+ intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos);
+ *p += pc_delta;
}
DCHECK(!buffer_overflow());
@@ -463,11 +480,29 @@ void Assembler::emit_operand(int code, const Operand& adr) {
// Emit updated ModR/M byte containing the given register.
DCHECK((adr.buf_[0] & 0x38) == 0);
- pc_[0] = adr.buf_[0] | code << 3;
-
- // Emit the rest of the encoded operand.
- for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
- pc_ += length;
+ *pc_++ = adr.buf_[0] | code << 3;
+
+ // Recognize RIP relative addressing.
+ if (adr.buf_[0] == 5) {
+ DCHECK_EQ(9u, length);
+ Label* label = *reinterpret_cast<Label* const*>(&adr.buf_[1]);
+ if (label->is_bound()) {
+ int offset = label->pos() - pc_offset() - sizeof(int32_t);
+ DCHECK_GE(0, offset);
+ emitl(offset);
+ } else if (label->is_linked()) {
+ emitl(label->pos());
+ label->link_to(pc_offset() - sizeof(int32_t));
+ } else {
+ DCHECK(label->is_unused());
+ int32_t current = pc_offset();
+ emitl(current);
+ label->link_to(current);
+ }
+ } else {
+ // Emit the rest of the encoded operand.
+ for (unsigned i = 1; i < length; i++) *pc_++ = adr.buf_[i];
+ }
}
@@ -1815,6 +1850,13 @@ void Assembler::ret(int imm16) {
}
+void Assembler::ud2() {
+ EnsureSpace ensure_space(this);
+ emit(0x0F);
+ emit(0x0B);
+}
+
+
void Assembler::setcc(Condition cc, Register reg) {
if (cc > last_condition) {
movb(reg, Immediate(cc == always ? 1 : 0));
@@ -3347,6 +3389,27 @@ void Assembler::dd(uint32_t data) {
}
+void Assembler::dq(Label* label) {
+ EnsureSpace ensure_space(this);
+ if (label->is_bound()) {
+ internal_reference_positions_.push_back(pc_offset());
+ emitp(buffer_ + label->pos(), RelocInfo::INTERNAL_REFERENCE);
+ } else {
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ emitl(0); // Zero for the first 32bit marks it as 64bit absolute address.
+ if (label->is_linked()) {
+ emitl(label->pos());
+ label->link_to(pc_offset() - sizeof(int32_t));
+ } else {
+ DCHECK(label->is_unused());
+ int32_t current = pc_offset();
+ emitl(current);
+ label->link_to(current);
+ }
+ }
+}
+
+
// Relocation information implementations.
void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
« no previous file with comments | « src/x64/assembler-x64.h ('k') | src/x64/assembler-x64-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698