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

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

Issue 935383002: Contribution of PowerPC port (continuation of 422063005) - PPC dir update 2 - mark2 (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/ppc/assembler-ppc.h ('k') | src/ppc/assembler-ppc-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ppc/assembler-ppc.cc
diff --git a/src/ppc/assembler-ppc.cc b/src/ppc/assembler-ppc.cc
index 8bb45e36cc6c1263ecdce9787343acc03a40b5a8..b1bec1668435673c539bf9cc1f453cb853f0fb06 100644
--- a/src/ppc/assembler-ppc.cc
+++ b/src/ppc/assembler-ppc.cc
@@ -142,7 +142,8 @@ const char* DoubleRegister::AllocationIndexToString(int index) {
// -----------------------------------------------------------------------------
// Implementation of RelocInfo
-const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
+const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE |
+ 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
bool RelocInfo::IsCodedSpecially() {
@@ -401,32 +402,41 @@ int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
const int kEndOfChain = -4;
+// Dummy opcodes for unbound label mov instructions or jump table entries.
+enum {
+ kUnboundMovLabelOffsetOpcode = 0 << 26,
+ kUnboundMovLabelAddrOpcode = 1 << 26,
+ kUnboundJumpTableEntryOpcode = 2 << 26
+};
+
+
int Assembler::target_at(int pos) {
Instr instr = instr_at(pos);
// check which type of branch this is 16 or 26 bit offset
int opcode = instr & kOpcodeMask;
- if (BX == opcode) {
- int imm26 = ((instr & kImm26Mask) << 6) >> 6;
- imm26 &= ~(kAAMask | kLKMask); // discard AA|LK bits if present
- if (imm26 == 0) return kEndOfChain;
- return pos + imm26;
- } else if (BCX == opcode) {
- int imm16 = SIGN_EXT_IMM16((instr & kImm16Mask));
- imm16 &= ~(kAAMask | kLKMask); // discard AA|LK bits if present
- if (imm16 == 0) return kEndOfChain;
- return pos + imm16;
- } else if ((instr & ~kImm26Mask) == 0) {
- // Emitted link to a label, not part of a branch (regexp PushBacktrack).
- if (instr == 0) {
- return kEndOfChain;
- } else {
- int32_t imm26 = SIGN_EXT_IMM26(instr);
- return (imm26 + pos);
- }
+ int link;
+ switch (opcode) {
+ case BX:
+ link = SIGN_EXT_IMM26(instr & kImm26Mask);
+ link &= ~(kAAMask | kLKMask); // discard AA|LK bits if present
+ break;
+ case BCX:
+ link = SIGN_EXT_IMM16((instr & kImm16Mask));
+ link &= ~(kAAMask | kLKMask); // discard AA|LK bits if present
+ break;
+ case kUnboundMovLabelOffsetOpcode:
+ case kUnboundMovLabelAddrOpcode:
+ case kUnboundJumpTableEntryOpcode:
+ link = SIGN_EXT_IMM26(instr & kImm26Mask);
+ link <<= 2;
+ break;
+ default:
+ DCHECK(false);
+ return -1;
}
- DCHECK(false);
- return -1;
+ if (link == 0) return kEndOfChain;
+ return pos + link;
}
@@ -434,51 +444,66 @@ void Assembler::target_at_put(int pos, int target_pos) {
Instr instr = instr_at(pos);
int opcode = instr & kOpcodeMask;
- // check which type of branch this is 16 or 26 bit offset
- if (BX == opcode) {
- int imm26 = target_pos - pos;
- DCHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0);
- if (imm26 == kInstrSize && !(instr & kLKMask)) {
- // Branch to next instr without link.
- instr = ORI; // nop: ori, 0,0,0
- } else {
- instr &= ((~kImm26Mask) | kAAMask | kLKMask);
- instr |= (imm26 & kImm26Mask);
+ switch (opcode) {
+ case BX: {
+ int imm26 = target_pos - pos;
+ DCHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0);
+ if (imm26 == kInstrSize && !(instr & kLKMask)) {
+ // Branch to next instr without link.
+ instr = ORI; // nop: ori, 0,0,0
+ } else {
+ instr &= ((~kImm26Mask) | kAAMask | kLKMask);
+ instr |= (imm26 & kImm26Mask);
+ }
+ instr_at_put(pos, instr);
+ break;
}
- instr_at_put(pos, instr);
- return;
- } else if (BCX == opcode) {
- int imm16 = target_pos - pos;
- DCHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0);
- if (imm16 == kInstrSize && !(instr & kLKMask)) {
- // Branch to next instr without link.
- instr = ORI; // nop: ori, 0,0,0
- } else {
- instr &= ((~kImm16Mask) | kAAMask | kLKMask);
- instr |= (imm16 & kImm16Mask);
+ case BCX: {
+ int imm16 = target_pos - pos;
+ DCHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0);
+ if (imm16 == kInstrSize && !(instr & kLKMask)) {
+ // Branch to next instr without link.
+ instr = ORI; // nop: ori, 0,0,0
+ } else {
+ instr &= ((~kImm16Mask) | kAAMask | kLKMask);
+ instr |= (imm16 & kImm16Mask);
+ }
+ instr_at_put(pos, instr);
+ break;
}
- instr_at_put(pos, instr);
- return;
- } else if ((instr & ~kImm26Mask) == 0) {
- DCHECK(target_pos == kEndOfChain || target_pos >= 0);
- // Emitted link to a label, not part of a branch (regexp PushBacktrack).
- // Load the position of the label relative to the generated code object
- // pointer in a register.
-
- Register dst = r3; // we assume r3 for now
- DCHECK(IsNop(instr_at(pos + kInstrSize)));
- uint32_t target = target_pos + (Code::kHeaderSize - kHeapObjectTag);
- CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 2,
- CodePatcher::DONT_FLUSH);
- int target_hi = static_cast<int>(target) >> 16;
- int target_lo = static_cast<int>(target) & 0XFFFF;
-
- patcher.masm()->lis(dst, Operand(SIGN_EXT_IMM16(target_hi)));
- patcher.masm()->ori(dst, dst, Operand(target_lo));
- return;
+ case kUnboundMovLabelOffsetOpcode: {
+ // Load the position of the label relative to the generated code object
+ // pointer in a register.
+ Register dst = Register::from_code(instr_at(pos + kInstrSize));
+ int32_t offset = target_pos + (Code::kHeaderSize - kHeapObjectTag);
+ CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 2,
+ CodePatcher::DONT_FLUSH);
+ patcher.masm()->bitwise_mov32(dst, offset);
+ break;
+ }
+ case kUnboundMovLabelAddrOpcode: {
+ // Load the address of the label in a register.
+ Register dst = Register::from_code(instr_at(pos + kInstrSize));
+ intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + target_pos);
+ CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
+ kMovInstructionsNoConstantPool,
+ CodePatcher::DONT_FLUSH);
+ AddBoundInternalReferenceLoad(pos);
+ patcher.masm()->bitwise_mov(dst, addr);
+ break;
+ }
+ case kUnboundJumpTableEntryOpcode: {
+ intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + target_pos);
+ CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
+ kPointerSize / kInstrSize, CodePatcher::DONT_FLUSH);
+ AddBoundInternalReference(pos);
+ patcher.masm()->emit_ptr(addr);
+ break;
+ }
+ default:
+ DCHECK(false);
+ break;
}
-
- DCHECK(false);
}
@@ -487,13 +512,15 @@ int Assembler::max_reach_from(int pos) {
int opcode = instr & kOpcodeMask;
// check which type of branch this is 16 or 26 bit offset
- if (BX == opcode) {
- return 26;
- } else if (BCX == opcode) {
- return 16;
- } else if ((instr & ~kImm26Mask) == 0) {
- // Emitted label constant, not part of a branch (regexp PushBacktrack).
- return 26;
+ switch (opcode) {
+ case BX:
+ return 26;
+ case BCX:
+ return 16;
+ case kUnboundMovLabelOffsetOpcode:
+ case kUnboundMovLabelAddrOpcode:
+ case kUnboundJumpTableEntryOpcode:
+ return 0; // no limit on reach
}
DCHECK(false);
@@ -514,7 +541,7 @@ void Assembler::bind_to(Label* L, int pos) {
int32_t offset = pos - fixup_pos;
int maxReach = max_reach_from(fixup_pos);
next(L); // call next before overwriting link with target at fixup_pos
- if (is_intn(offset, maxReach) == false) {
+ if (maxReach && is_intn(offset, maxReach) == false) {
if (trampoline_pos == kInvalidSlotPos) {
trampoline_pos = get_trampoline_entry();
CHECK(trampoline_pos != kInvalidSlotPos);
@@ -636,19 +663,19 @@ int32_t Assembler::get_trampoline_entry() {
}
-int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
- int target_pos;
+int Assembler::link(Label* L) {
+ int position;
if (L->is_bound()) {
- target_pos = L->pos();
+ position = L->pos();
} else {
if (L->is_linked()) {
- target_pos = L->pos(); // L's link
+ position = L->pos(); // L's link
} else {
// was: target_pos = kEndOfChain;
- // However, using branch to self to mark the first reference
+ // However, using self to mark the first reference
// should avoid most instances of branch offset overflow. See
// target_at() for where this is converted back to kEndOfChain.
- target_pos = pc_offset();
+ position = pc_offset();
if (!trampoline_emitted_) {
unbound_labels_count_++;
next_buffer_check_ -= kTrampolineSlotsSize;
@@ -657,7 +684,7 @@ int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
L->link_to(pc_offset());
}
- return target_pos - pc_offset();
+ return position;
}
@@ -1478,58 +1505,45 @@ void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o,
// TOC and static chain are ignored and set to 0.
void Assembler::function_descriptor() {
#if ABI_USES_FUNCTION_DESCRIPTORS
+ Label instructions;
DCHECK(pc_offset() == 0);
- RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
- emit_ptr(reinterpret_cast<uintptr_t>(pc_) + 3 * kPointerSize);
+ emit_label_addr(&instructions);
emit_ptr(0);
emit_ptr(0);
+ bind(&instructions);
#endif
}
-#if ABI_USES_FUNCTION_DESCRIPTORS || V8_OOL_CONSTANT_POOL
void Assembler::RelocateInternalReference(Address pc, intptr_t delta,
Address code_start,
+ RelocInfo::Mode rmode,
ICacheFlushMode icache_flush_mode) {
- DCHECK(delta || code_start);
-#if ABI_USES_FUNCTION_DESCRIPTORS
- uintptr_t* fd = reinterpret_cast<uintptr_t*>(pc);
- if (fd[1] == 0 && fd[2] == 0) {
- // Function descriptor
+ if (RelocInfo::IsInternalReference(rmode)) {
+ // Jump table entry
+ DCHECK(delta || code_start);
+ uintptr_t* entry = reinterpret_cast<uintptr_t*>(pc);
if (delta) {
- fd[0] += delta;
+ *entry += delta;
} else {
- fd[0] = reinterpret_cast<uintptr_t>(code_start) + 3 * kPointerSize;
+ // remove when serializer properly supports internal references
+ *entry = reinterpret_cast<uintptr_t>(code_start) + 3 * kPointerSize;
}
- return;
- }
-#endif
-#if V8_OOL_CONSTANT_POOL
- // mov for LoadConstantPoolPointerRegister
- ConstantPoolArray* constant_pool = NULL;
- if (delta) {
- code_start = target_address_at(pc, constant_pool) + delta;
- }
- set_target_address_at(pc, constant_pool, code_start, icache_flush_mode);
-#endif
-}
-
-
-int Assembler::DecodeInternalReference(Vector<char> buffer, Address pc) {
-#if ABI_USES_FUNCTION_DESCRIPTORS
- uintptr_t* fd = reinterpret_cast<uintptr_t*>(pc);
- if (fd[1] == 0 && fd[2] == 0) {
- // Function descriptor
- SNPrintF(buffer, "[%08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
- "]"
- " function descriptor",
- fd[0], fd[1], fd[2]);
- return kPointerSize * 3;
+ } else {
+ // mov sequence
+ DCHECK(delta || code_start);
+ DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
+ ConstantPoolArray* constant_pool = NULL;
+ Address addr;
+ if (delta) {
+ addr = target_address_at(pc, constant_pool) + delta;
+ } else {
+ // remove when serializer properly supports internal references
+ addr = code_start;
+ }
+ set_target_address_at(pc, constant_pool, addr, icache_flush_mode);
}
-#endif
- return 0;
}
-#endif
int Assembler::instructions_required_for_mov(const Operand& x) const {
@@ -1658,8 +1672,11 @@ void Assembler::mov(Register dst, const Operand& src) {
}
DCHECK(!canOptimize);
+ bitwise_mov(dst, value);
+}
- {
+
+void Assembler::bitwise_mov(Register dst, intptr_t value) {
BlockTrampolinePoolScope block_trampoline_pool(this);
#if V8_TARGET_ARCH_PPC64
int32_t hi_32 = static_cast<int32_t>(value >> 32);
@@ -1679,37 +1696,114 @@ void Assembler::mov(Register dst, const Operand& src) {
lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
ori(dst, dst, Operand(lo_word));
#endif
- }
+}
+
+
+void Assembler::bitwise_mov32(Register dst, int32_t value) {
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ int hi_word = static_cast<int>(value >> 16);
+ int lo_word = static_cast<int>(value & 0xffff);
+ lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
+ ori(dst, dst, Operand(lo_word));
}
void Assembler::mov_label_offset(Register dst, Label* label) {
+ int position = link(label);
if (label->is_bound()) {
- int target = label->pos();
- mov(dst, Operand(target + Code::kHeaderSize - kHeapObjectTag));
+ // Load the position of the label relative to the generated code object.
+ mov(dst, Operand(position + Code::kHeaderSize - kHeapObjectTag));
} else {
- bool is_linked = label->is_linked();
- // Emit the link to the label in the code stream followed by extra
- // nop instructions.
- DCHECK(dst.is(r3)); // target_at_put assumes r3 for now
- int link = is_linked ? label->pos() - pc_offset() : 0;
- label->link_to(pc_offset());
-
- if (!is_linked && !trampoline_emitted_) {
- unbound_labels_count_++;
- next_buffer_check_ -= kTrampolineSlotsSize;
- }
+ // Encode internal reference to unbound label. We use a dummy opcode
+ // such that it won't collide with any opcode that might appear in the
+ // label's chain. Encode the destination register in the 2nd instruction.
+ int link = position - pc_offset();
+ DCHECK_EQ(0, link & 3);
+ link >>= 2;
+ DCHECK(is_int26(link));
// When the label is bound, these instructions will be patched
// with a 2 instruction mov sequence that will load the
// destination register with the position of the label from the
// beginning of the code.
//
- // When the label gets bound: target_at extracts the link and
- // target_at_put patches the instructions.
+ // target_at extracts the link and target_at_put patches the instructions.
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ emit(kUnboundMovLabelOffsetOpcode | (link & kImm26Mask));
+ emit(dst.code());
+ }
+}
+
+
+// TODO(mbrandy): allow loading internal reference from constant pool
+void Assembler::mov_label_addr(Register dst, Label* label) {
+ CheckBuffer();
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
+ int position = link(label);
+ if (label->is_bound()) {
+// CheckBuffer() is called too frequently. This will pre-grow
+// the buffer if needed to avoid spliting the relocation and instructions
+#if V8_OOL_CONSTANT_POOL
+ EnsureSpaceFor(kMovInstructionsNoConstantPool * kInstrSize);
+#endif
+
+ intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + position);
+ AddBoundInternalReferenceLoad(pc_offset());
+ bitwise_mov(dst, addr);
+ } else {
+ // Encode internal reference to unbound label. We use a dummy opcode
+ // such that it won't collide with any opcode that might appear in the
+ // label's chain. Encode the destination register in the 2nd instruction.
+ int link = position - pc_offset();
+ DCHECK_EQ(0, link & 3);
+ link >>= 2;
+ DCHECK(is_int26(link));
+
+ // When the label is bound, these instructions will be patched
+ // with a multi-instruction mov sequence that will load the
+ // destination register with the address of the label.
+ //
+ // target_at extracts the link and target_at_put patches the instructions.
+ BlockTrampolinePoolScope block_trampoline_pool(this);
+ emit(kUnboundMovLabelAddrOpcode | (link & kImm26Mask));
+ emit(dst.code());
+ DCHECK(kMovInstructionsNoConstantPool >= 2);
+ for (int i = 0; i < kMovInstructionsNoConstantPool - 2; i++) nop();
+ }
+}
+
+
+void Assembler::emit_label_addr(Label* label) {
+ CheckBuffer();
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ int position = link(label);
+ if (label->is_bound()) {
+// CheckBuffer() is called too frequently. This will pre-grow
+// the buffer if needed to avoid spliting the relocation and entry.
+#if V8_OOL_CONSTANT_POOL
+ EnsureSpaceFor(kPointerSize);
+#endif
+
+ intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + position);
+ AddBoundInternalReference(pc_offset());
+ emit_ptr(addr);
+ } else {
+ // Encode internal reference to unbound label. We use a dummy opcode
+ // such that it won't collide with any opcode that might appear in the
+ // label's chain.
+ int link = position - pc_offset();
+ DCHECK_EQ(0, link & 3);
+ link >>= 2;
+ DCHECK(is_int26(link));
+
+ // When the label is bound, the instruction(s) will be patched
+ // as a jump table entry containing the label address. target_at extracts
+ // the link and target_at_put patches the instruction(s).
BlockTrampolinePoolScope block_trampoline_pool(this);
- emit(link);
+ emit(kUnboundJumpTableEntryOpcode | (link & kImm26Mask));
+#if V8_TARGET_ARCH_PPC64
nop();
+#endif
}
}
@@ -2209,22 +2303,18 @@ void Assembler::GrowBuffer() {
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
reloc_info_writer.last_pc() + pc_delta);
-// None of our relocation types are pc relative pointing outside the code
-// buffer nor pc absolute pointing inside the code buffer, so there is no need
-// to relocate any emitted relocation entries.
-
-#if ABI_USES_FUNCTION_DESCRIPTORS || V8_OOL_CONSTANT_POOL
- // Relocate runtime entries.
- for (RelocIterator it(desc); !it.done(); it.next()) {
- RelocInfo::Mode rmode = it.rinfo()->rmode();
- if (rmode == RelocInfo::INTERNAL_REFERENCE) {
- RelocateInternalReference(it.rinfo()->pc(), pc_delta, 0);
- }
+ // Relocate internal references
+ for (int pos : internal_reference_positions_) {
+ RelocateInternalReference(buffer_ + pos, pc_delta, 0,
+ RelocInfo::INTERNAL_REFERENCE);
+ }
+ for (int pos : internal_reference_load_positions_) {
+ RelocateInternalReference(buffer_ + pos, pc_delta, 0,
+ RelocInfo::INTERNAL_REFERENCE_ENCODED);
}
#if V8_OOL_CONSTANT_POOL
constant_pool_builder_.Relocate(pc_delta);
#endif
-#endif
}
@@ -2242,7 +2332,7 @@ void Assembler::dd(uint32_t data) {
}
-void Assembler::emit_ptr(uintptr_t data) {
+void Assembler::emit_ptr(intptr_t data) {
CheckBuffer();
*reinterpret_cast<uintptr_t*>(pc_) = data;
pc_ += sizeof(uintptr_t);
« no previous file with comments | « src/ppc/assembler-ppc.h ('k') | src/ppc/assembler-ppc-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698